1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source term_util.vim 5source view_util.vim 6source vim9.vim 7source screendump.vim 8 9func Test_def_basic() 10 def SomeFunc(): string 11 return 'yes' 12 enddef 13 call SomeFunc()->assert_equal('yes') 14endfunc 15 16func Test_compiling_error() 17 " use a terminal to see the whole error message 18 CheckRunVimInTerminal 19 20 call TestCompilingError() 21 call TestCompilingErrorInTry() 22endfunc 23 24def TestCompilingError() 25 var lines =<< trim END 26 vim9script 27 def Fails() 28 echo nothing 29 enddef 30 defcompile 31 END 32 writefile(lines, 'XTest_compile_error') 33 var buf = RunVimInTerminal('-S XTest_compile_error', 34 {rows: 10, wait_for_ruler: 0}) 35 WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing', 36 Term_getlines(buf, range(1, 9)))) 37 38 # clean up 39 StopVimInTerminal(buf) 40 delete('XTest_compile_error') 41enddef 42 43def TestCompilingErrorInTry() 44 var dir = 'Xdir/autoload' 45 mkdir(dir, 'p') 46 47 var lines =<< trim END 48 vim9script 49 def script#OnlyCompiled() 50 g:runtime = 'yes' 51 invalid 52 enddef 53 END 54 writefile(lines, dir .. '/script.vim') 55 56 lines =<< trim END 57 vim9script 58 todo 59 try 60 script#OnlyCompiled() 61 catch /nothing/ 62 endtry 63 END 64 lines[1] = 'set rtp=' .. getcwd() .. '/Xdir' 65 writefile(lines, 'XTest_compile_error') 66 67 var buf = RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0}) 68 WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid', 69 Term_getlines(buf, range(1, 9)))) 70 71 # clean up 72 StopVimInTerminal(buf) 73 delete('XTest_compile_error') 74 delete('Xdir', 'rf') 75enddef 76 77def Test_autoload_name_mismatch() 78 var dir = 'Xdir/autoload' 79 mkdir(dir, 'p') 80 81 var lines =<< trim END 82 vim9script 83 def scriptX#Function() 84 # comment 85 g:runtime = 'yes' 86 enddef 87 END 88 writefile(lines, dir .. '/script.vim') 89 90 var save_rtp = &rtp 91 exe 'set rtp=' .. getcwd() .. '/Xdir' 92 lines =<< trim END 93 call script#Function() 94 END 95 CheckScriptFailure(lines, 'E746:', 2) 96 97 &rtp = save_rtp 98 delete(dir, 'rf') 99enddef 100 101def CallRecursive(n: number): number 102 return CallRecursive(n + 1) 103enddef 104 105def CallMapRecursive(l: list<number>): number 106 return map(l, (_, v) => CallMapRecursive([v]))[0] 107enddef 108 109def Test_funcdepth_error() 110 set maxfuncdepth=10 111 112 var caught = false 113 try 114 CallRecursive(1) 115 catch /E132:/ 116 caught = true 117 endtry 118 assert_true(caught) 119 120 caught = false 121 try 122 CallMapRecursive([1]) 123 catch /E132:/ 124 caught = true 125 endtry 126 assert_true(caught) 127 128 set maxfuncdepth& 129enddef 130 131def Test_endfunc_enddef() 132 var lines =<< trim END 133 def Test() 134 echo 'test' 135 endfunc 136 enddef 137 END 138 CheckScriptFailure(lines, 'E1151:', 3) 139 140 lines =<< trim END 141 def Test() 142 func Nested() 143 echo 'test' 144 enddef 145 enddef 146 END 147 CheckScriptFailure(lines, 'E1152:', 4) 148 149 lines =<< trim END 150 def Ok() 151 echo 'hello' 152 enddef | echo 'there' 153 def Bad() 154 echo 'hello' 155 enddef there 156 END 157 CheckScriptFailure(lines, 'E1173: Text found after enddef: there', 6) 158enddef 159 160def Test_missing_endfunc_enddef() 161 var lines =<< trim END 162 vim9script 163 def Test() 164 echo 'test' 165 endef 166 END 167 CheckScriptFailure(lines, 'E1057:', 2) 168 169 lines =<< trim END 170 vim9script 171 func Some() 172 echo 'test' 173 enfffunc 174 END 175 CheckScriptFailure(lines, 'E126:', 2) 176enddef 177 178def Test_white_space_before_paren() 179 var lines =<< trim END 180 vim9script 181 def Test () 182 echo 'test' 183 enddef 184 END 185 CheckScriptFailure(lines, 'E1068:', 2) 186 187 lines =<< trim END 188 vim9script 189 func Test () 190 echo 'test' 191 endfunc 192 END 193 CheckScriptFailure(lines, 'E1068:', 2) 194 195 lines =<< trim END 196 def Test () 197 echo 'test' 198 enddef 199 END 200 CheckScriptFailure(lines, 'E1068:', 1) 201 202 lines =<< trim END 203 func Test () 204 echo 'test' 205 endfunc 206 END 207 CheckScriptSuccess(lines) 208enddef 209 210def Test_enddef_dict_key() 211 var d = { 212 enddef: 'x', 213 endfunc: 'y', 214 } 215 assert_equal({enddef: 'x', endfunc: 'y'}, d) 216enddef 217 218def ReturnString(): string 219 return 'string' 220enddef 221 222def ReturnNumber(): number 223 return 123 224enddef 225 226let g:notNumber = 'string' 227 228def ReturnGlobal(): number 229 return g:notNumber 230enddef 231 232def Test_return_something() 233 ReturnString()->assert_equal('string') 234 ReturnNumber()->assert_equal(123) 235 assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal') 236enddef 237 238def Test_check_argument_type() 239 var lines =<< trim END 240 vim9script 241 def Val(a: number, b: number): number 242 return 0 243 enddef 244 def Func() 245 var x: any = true 246 Val(0, x) 247 enddef 248 disass Func 249 Func() 250 END 251 CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2) 252enddef 253 254def Test_missing_return() 255 CheckDefFailure(['def Missing(): number', 256 ' if g:cond', 257 ' echo "no return"', 258 ' else', 259 ' return 0', 260 ' endif' 261 'enddef'], 'E1027:') 262 CheckDefFailure(['def Missing(): number', 263 ' if g:cond', 264 ' return 1', 265 ' else', 266 ' echo "no return"', 267 ' endif' 268 'enddef'], 'E1027:') 269 CheckDefFailure(['def Missing(): number', 270 ' if g:cond', 271 ' return 1', 272 ' else', 273 ' return 2', 274 ' endif' 275 ' return 3' 276 'enddef'], 'E1095:') 277enddef 278 279def Test_return_bool() 280 var lines =<< trim END 281 vim9script 282 def MenuFilter(id: number, key: string): bool 283 return popup_filter_menu(id, key) 284 enddef 285 def YesnoFilter(id: number, key: string): bool 286 return popup_filter_yesno(id, key) 287 enddef 288 defcompile 289 END 290 CheckScriptSuccess(lines) 291enddef 292 293let s:nothing = 0 294def ReturnNothing() 295 s:nothing = 1 296 if true 297 return 298 endif 299 s:nothing = 2 300enddef 301 302def Test_return_nothing() 303 ReturnNothing() 304 s:nothing->assert_equal(1) 305enddef 306 307def Test_return_invalid() 308 var lines =<< trim END 309 vim9script 310 def Func(): invalid 311 return xxx 312 enddef 313 defcompile 314 END 315 CheckScriptFailure(lines, 'E1010:', 2) 316 317 lines =<< trim END 318 vim9script 319 def Test(Fun: func(number): number): list<number> 320 return map([1, 2, 3], (_, i) => Fun(i)) 321 enddef 322 defcompile 323 def Inc(nr: number): nr 324 return nr + 2 325 enddef 326 echo Test(Inc) 327 END 328 # doing this twice was leaking memory 329 CheckScriptFailure(lines, 'E1010:') 330 CheckScriptFailure(lines, 'E1010:') 331enddef 332 333func Increment() 334 let g:counter += 1 335endfunc 336 337def Test_call_ufunc_count() 338 g:counter = 1 339 Increment() 340 Increment() 341 Increment() 342 # works with and without :call 343 g:counter->assert_equal(4) 344 eval g:counter->assert_equal(4) 345 unlet g:counter 346enddef 347 348def MyVarargs(arg: string, ...rest: list<string>): string 349 var res = arg 350 for s in rest 351 res ..= ',' .. s 352 endfor 353 return res 354enddef 355 356def Test_call_varargs() 357 MyVarargs('one')->assert_equal('one') 358 MyVarargs('one', 'two')->assert_equal('one,two') 359 MyVarargs('one', 'two', 'three')->assert_equal('one,two,three') 360enddef 361 362def MyDefaultArgs(name = 'string'): string 363 return name 364enddef 365 366def MyDefaultSecond(name: string, second: bool = true): string 367 return second ? name : 'none' 368enddef 369 370 371def Test_call_default_args() 372 MyDefaultArgs()->assert_equal('string') 373 MyDefaultArgs(v:none)->assert_equal('string') 374 MyDefaultArgs('one')->assert_equal('one') 375 assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 4, 'Test_call_default_args') 376 377 MyDefaultSecond('test')->assert_equal('test') 378 MyDefaultSecond('test', true)->assert_equal('test') 379 MyDefaultSecond('test', false)->assert_equal('none') 380 381 var lines =<< trim END 382 def MyDefaultThird(name: string, aa = 'aa', bb = 'bb'): string 383 return name .. aa .. bb 384 enddef 385 386 MyDefaultThird('->')->assert_equal('->aabb') 387 MyDefaultThird('->', v:none)->assert_equal('->aabb') 388 MyDefaultThird('->', 'xx')->assert_equal('->xxbb') 389 MyDefaultThird('->', v:none, v:none)->assert_equal('->aabb') 390 MyDefaultThird('->', 'xx', v:none)->assert_equal('->xxbb') 391 MyDefaultThird('->', v:none, 'yy')->assert_equal('->aayy') 392 MyDefaultThird('->', 'xx', 'yy')->assert_equal('->xxyy') 393 END 394 CheckDefAndScriptSuccess(lines) 395 396 CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:') 397 delfunc g:Func 398 CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string') 399 delfunc g:Func 400 401 lines =<< trim END 402 vim9script 403 def Func(a = b == 0 ? 1 : 2, b = 0) 404 enddef 405 defcompile 406 END 407 CheckScriptFailure(lines, 'E1001: Variable not found: b') 408enddef 409 410def FuncWithComment( # comment 411 a: number, #comment 412 b: bool, # comment 413 c: string) #comment 414 assert_equal(4, a) 415 assert_equal(true, b) 416 assert_equal('yes', c) 417enddef 418 419def Test_func_with_comments() 420 FuncWithComment(4, true, 'yes') 421 422 var lines =<< trim END 423 def Func(# comment 424 arg: string) 425 enddef 426 END 427 CheckScriptFailure(lines, 'E125:', 1) 428 429 lines =<< trim END 430 def Func( 431 arg: string# comment 432 ) 433 enddef 434 END 435 CheckScriptFailure(lines, 'E475:', 2) 436 437 lines =<< trim END 438 def Func( 439 arg: string 440 )# comment 441 enddef 442 END 443 CheckScriptFailure(lines, 'E488:', 3) 444enddef 445 446def Test_nested_function() 447 def Nested(arg: string): string 448 return 'nested ' .. arg 449 enddef 450 Nested('function')->assert_equal('nested function') 451 452 CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:') 453 CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:') 454 455 CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') 456 CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:') 457 CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:') 458 459 var lines =<< trim END 460 def Outer() 461 def Inner() 462 # comment 463 enddef 464 def Inner() 465 enddef 466 enddef 467 END 468 CheckDefFailure(lines, 'E1073:') 469 470 lines =<< trim END 471 def Outer() 472 def Inner() 473 # comment 474 enddef 475 def! Inner() 476 enddef 477 enddef 478 END 479 CheckDefFailure(lines, 'E1117:') 480 481 # nested function inside conditional 482 lines =<< trim END 483 vim9script 484 var thecount = 0 485 if true 486 def Test(): number 487 def TheFunc(): number 488 thecount += 1 489 return thecount 490 enddef 491 return TheFunc() 492 enddef 493 endif 494 defcompile 495 assert_equal(1, Test()) 496 assert_equal(2, Test()) 497 END 498 CheckScriptSuccess(lines) 499 500 # also works when "thecount" is inside the "if" block 501 lines =<< trim END 502 vim9script 503 if true 504 var thecount = 0 505 def Test(): number 506 def TheFunc(): number 507 thecount += 1 508 return thecount 509 enddef 510 return TheFunc() 511 enddef 512 endif 513 defcompile 514 assert_equal(1, Test()) 515 assert_equal(2, Test()) 516 END 517 CheckScriptSuccess(lines) 518enddef 519 520def Test_not_nested_function() 521 echo printf('%d', 522 function('len')('xxx')) 523enddef 524 525func Test_call_default_args_from_func() 526 call MyDefaultArgs()->assert_equal('string') 527 call MyDefaultArgs('one')->assert_equal('one') 528 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func') 529endfunc 530 531def Test_nested_global_function() 532 var lines =<< trim END 533 vim9script 534 def Outer() 535 def g:Inner(): string 536 return 'inner' 537 enddef 538 enddef 539 defcompile 540 Outer() 541 g:Inner()->assert_equal('inner') 542 delfunc g:Inner 543 Outer() 544 g:Inner()->assert_equal('inner') 545 delfunc g:Inner 546 Outer() 547 g:Inner()->assert_equal('inner') 548 delfunc g:Inner 549 END 550 CheckScriptSuccess(lines) 551 552 lines =<< trim END 553 vim9script 554 def Outer() 555 def g:Inner(): string 556 return 'inner' 557 enddef 558 enddef 559 defcompile 560 Outer() 561 Outer() 562 END 563 CheckScriptFailure(lines, "E122:") 564 delfunc g:Inner 565 566 lines =<< trim END 567 vim9script 568 def Outer() 569 def g:Inner() 570 echo map([1, 2, 3], (_, v) => v + 1) 571 enddef 572 g:Inner() 573 enddef 574 Outer() 575 END 576 CheckScriptSuccess(lines) 577 delfunc g:Inner 578 579 lines =<< trim END 580 vim9script 581 def Func() 582 echo 'script' 583 enddef 584 def Outer() 585 def Func() 586 echo 'inner' 587 enddef 588 enddef 589 defcompile 590 END 591 CheckScriptFailure(lines, "E1073:") 592enddef 593 594def DefListAll() 595 def 596enddef 597 598def DefListOne() 599 def DefListOne 600enddef 601 602def DefListMatches() 603 def /DefList 604enddef 605 606def Test_nested_def_list() 607 var funcs = split(execute('call DefListAll()'), "\n") 608 assert_true(len(funcs) > 10) 609 assert_true(funcs->index('def DefListAll()') >= 0) 610 611 funcs = split(execute('call DefListOne()'), "\n") 612 assert_equal([' def DefListOne()', '1 def DefListOne', ' enddef'], funcs) 613 614 funcs = split(execute('call DefListMatches()'), "\n") 615 assert_true(len(funcs) >= 3) 616 assert_true(funcs->index('def DefListAll()') >= 0) 617 assert_true(funcs->index('def DefListOne()') >= 0) 618 assert_true(funcs->index('def DefListMatches()') >= 0) 619 620 var lines =<< trim END 621 vim9script 622 def Func() 623 def +Func+ 624 enddef 625 defcompile 626 END 627 CheckScriptFailure(lines, 'E476:', 1) 628enddef 629 630def Test_global_local_function() 631 var lines =<< trim END 632 vim9script 633 def g:Func(): string 634 return 'global' 635 enddef 636 def Func(): string 637 return 'local' 638 enddef 639 g:Func()->assert_equal('global') 640 Func()->assert_equal('local') 641 delfunc g:Func 642 END 643 CheckScriptSuccess(lines) 644 645 lines =<< trim END 646 vim9script 647 def g:Funcy() 648 echo 'funcy' 649 enddef 650 s:Funcy() 651 END 652 CheckScriptFailure(lines, 'E117:') 653enddef 654 655def Test_local_function_shadows_global() 656 var lines =<< trim END 657 vim9script 658 def g:Gfunc(): string 659 return 'global' 660 enddef 661 def AnotherFunc(): number 662 var Gfunc = function('len') 663 return Gfunc('testing') 664 enddef 665 g:Gfunc()->assert_equal('global') 666 AnotherFunc()->assert_equal(7) 667 delfunc g:Gfunc 668 END 669 CheckScriptSuccess(lines) 670 671 lines =<< trim END 672 vim9script 673 def g:Func(): string 674 return 'global' 675 enddef 676 def AnotherFunc() 677 g:Func = function('len') 678 enddef 679 AnotherFunc() 680 END 681 CheckScriptFailure(lines, 'E705:') 682 delfunc g:Func 683 684 # global function is found without g: prefix 685 lines =<< trim END 686 vim9script 687 def g:Func(): string 688 return 'global' 689 enddef 690 def AnotherFunc(): string 691 return Func() 692 enddef 693 assert_equal('global', AnotherFunc()) 694 delfunc g:Func 695 END 696 CheckScriptSuccess(lines) 697 698 lines =<< trim END 699 vim9script 700 def g:Func(): string 701 return 'global' 702 enddef 703 assert_equal('global', Func()) 704 delfunc g:Func 705 END 706 CheckScriptSuccess(lines) 707enddef 708 709func TakesOneArg(arg) 710 echo a:arg 711endfunc 712 713def Test_call_wrong_args() 714 CheckDefFailure(['TakesOneArg()'], 'E119:') 715 CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') 716 CheckDefFailure(['bufnr(xxx)'], 'E1001:') 717 CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:') 718 719 var lines =<< trim END 720 vim9script 721 def Func(s: string) 722 echo s 723 enddef 724 Func([]) 725 END 726 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5) 727 728 lines =<< trim END 729 vim9script 730 var name = 'piet' 731 def FuncOne(name: string) 732 echo nr 733 enddef 734 END 735 CheckScriptFailure(lines, 'E1168:') 736 737 lines =<< trim END 738 vim9script 739 def FuncOne(nr: number) 740 echo nr 741 enddef 742 def FuncTwo() 743 FuncOne() 744 enddef 745 defcompile 746 END 747 writefile(lines, 'Xscript') 748 var didCatch = false 749 try 750 source Xscript 751 catch 752 assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception) 753 assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint) 754 didCatch = true 755 endtry 756 assert_true(didCatch) 757 758 lines =<< trim END 759 vim9script 760 def FuncOne(nr: number) 761 echo nr 762 enddef 763 def FuncTwo() 764 FuncOne(1, 2) 765 enddef 766 defcompile 767 END 768 writefile(lines, 'Xscript') 769 didCatch = false 770 try 771 source Xscript 772 catch 773 assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception) 774 assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint) 775 didCatch = true 776 endtry 777 assert_true(didCatch) 778 779 delete('Xscript') 780enddef 781 782def Test_call_funcref_wrong_args() 783 var head =<< trim END 784 vim9script 785 def Func3(a1: string, a2: number, a3: list<number>) 786 echo a1 .. a2 .. a3[0] 787 enddef 788 def Testme() 789 var funcMap: dict<func> = {func: Func3} 790 END 791 var tail =<< trim END 792 enddef 793 Testme() 794 END 795 CheckScriptSuccess(head + ["funcMap['func']('str', 123, [1, 2, 3])"] + tail) 796 797 CheckScriptFailure(head + ["funcMap['func']('str', 123)"] + tail, 'E119:') 798 CheckScriptFailure(head + ["funcMap['func']('str', 123, [1], 4)"] + tail, 'E118:') 799 800 var lines =<< trim END 801 vim9script 802 var Ref: func(number): any 803 Ref = (j) => !j 804 echo Ref(false) 805 END 806 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4) 807 808 lines =<< trim END 809 vim9script 810 var Ref: func(number): any 811 Ref = (j) => !j 812 call Ref(false) 813 END 814 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4) 815enddef 816 817def Test_call_lambda_args() 818 var lines =<< trim END 819 var Callback = (..._) => 'anything' 820 assert_equal('anything', Callback()) 821 assert_equal('anything', Callback(1)) 822 assert_equal('anything', Callback('a', 2)) 823 824 assert_equal('xyz', ((a: string): string => a)('xyz')) 825 END 826 CheckDefAndScriptSuccess(lines) 827 828 CheckDefFailure(['echo ((i) => 0)()'], 829 'E119: Not enough arguments for function: ((i) => 0)()') 830 831 lines =<< trim END 832 var Ref = (x: number, y: number) => x + y 833 echo Ref(1, 'x') 834 END 835 CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string') 836 837 lines =<< trim END 838 var Ref: func(job, string, number) 839 Ref = (x, y) => 0 840 END 841 CheckDefAndScriptFailure(lines, 'E1012:') 842 843 lines =<< trim END 844 var Ref: func(job, string) 845 Ref = (x, y, z) => 0 846 END 847 CheckDefAndScriptFailure(lines, 'E1012:') 848 849 lines =<< trim END 850 var one = 1 851 var l = [1, 2, 3] 852 echo map(l, (one) => one) 853 END 854 CheckDefFailure(lines, 'E1167:') 855 CheckScriptFailure(['vim9script'] + lines, 'E1168:') 856 857 lines =<< trim END 858 def ShadowLocal() 859 var one = 1 860 var l = [1, 2, 3] 861 echo map(l, (one) => one) 862 enddef 863 END 864 CheckDefFailure(lines, 'E1167:') 865 866 lines =<< trim END 867 def Shadowarg(one: number) 868 var l = [1, 2, 3] 869 echo map(l, (one) => one) 870 enddef 871 END 872 CheckDefFailure(lines, 'E1167:') 873 874 lines =<< trim END 875 echo ((a) => a)('aa', 'bb') 876 END 877 CheckDefAndScriptFailure(lines, 'E118:', 1) 878enddef 879 880def FilterWithCond(x: string, Cond: func(string): bool): bool 881 return Cond(x) 882enddef 883 884def Test_lambda_return_type() 885 var lines =<< trim END 886 var Ref = (): => 123 887 END 888 CheckDefAndScriptFailure(lines, 'E1157:', 1) 889 890 # this works 891 for x in ['foo', 'boo'] 892 echo FilterWithCond(x, (v) => v =~ '^b') 893 endfor 894 895 # this fails 896 lines =<< trim END 897 echo FilterWithCond('foo', (v) => v .. '^b') 898 END 899 CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1) 900enddef 901 902def Test_lambda_uses_assigned_var() 903 CheckDefSuccess([ 904 'var x: any = "aaa"' 905 'x = filter(["bbb"], (_, v) => v =~ x)']) 906enddef 907 908def Test_pass_legacy_lambda_to_def_func() 909 var lines =<< trim END 910 vim9script 911 func Foo() 912 eval s:Bar({x -> 0}) 913 endfunc 914 def Bar(y: any) 915 enddef 916 Foo() 917 END 918 CheckScriptSuccess(lines) 919enddef 920 921" Default arg and varargs 922def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 923 var res = one .. ',' .. two 924 for s in rest 925 res ..= ',' .. s 926 endfor 927 return res 928enddef 929 930def Test_call_def_varargs() 931 assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs') 932 MyDefVarargs('one')->assert_equal('one,foo') 933 MyDefVarargs('one', 'two')->assert_equal('one,two') 934 MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three') 935 CheckDefFailure(['MyDefVarargs("one", 22)'], 936 'E1013: Argument 2: type mismatch, expected string but got number') 937 CheckDefFailure(['MyDefVarargs("one", "two", 123)'], 938 'E1013: Argument 3: type mismatch, expected string but got number') 939 940 var lines =<< trim END 941 vim9script 942 def Func(...l: list<string>) 943 echo l 944 enddef 945 Func('a', 'b', 'c') 946 END 947 CheckScriptSuccess(lines) 948 949 lines =<< trim END 950 vim9script 951 def Func(...l: list<string>) 952 echo l 953 enddef 954 Func() 955 END 956 CheckScriptSuccess(lines) 957 958 lines =<< trim END 959 vim9script 960 def Func(...l: list<any>) 961 echo l 962 enddef 963 Func(0) 964 END 965 CheckScriptSuccess(lines) 966 967 lines =<< trim END 968 vim9script 969 def Func(...l: any) 970 echo l 971 enddef 972 Func(0) 973 END 974 CheckScriptFailure(lines, 'E1180:', 2) 975 976 lines =<< trim END 977 vim9script 978 def Func(..._l: list<string>) 979 echo _l 980 enddef 981 Func('a', 'b', 'c') 982 END 983 CheckScriptSuccess(lines) 984 985 lines =<< trim END 986 vim9script 987 def Func(...l: list<string>) 988 echo l 989 enddef 990 Func(1, 2, 3) 991 END 992 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch') 993 994 lines =<< trim END 995 vim9script 996 def Func(...l: list<string>) 997 echo l 998 enddef 999 Func('a', 9) 1000 END 1001 CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch') 1002 1003 lines =<< trim END 1004 vim9script 1005 def Func(...l: list<string>) 1006 echo l 1007 enddef 1008 Func(1, 'a') 1009 END 1010 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch') 1011 1012 lines =<< trim END 1013 vim9script 1014 def Func( # some comment 1015 ...l = [] 1016 ) 1017 echo l 1018 enddef 1019 END 1020 CheckScriptFailure(lines, 'E1160:') 1021enddef 1022 1023let s:value = '' 1024 1025def FuncOneDefArg(opt = 'text') 1026 s:value = opt 1027enddef 1028 1029def FuncTwoDefArg(nr = 123, opt = 'text'): string 1030 return nr .. opt 1031enddef 1032 1033def FuncVarargs(...arg: list<string>): string 1034 return join(arg, ',') 1035enddef 1036 1037def Test_func_type_varargs() 1038 var RefDefArg: func(?string) 1039 RefDefArg = FuncOneDefArg 1040 RefDefArg() 1041 s:value->assert_equal('text') 1042 RefDefArg('some') 1043 s:value->assert_equal('some') 1044 1045 var RefDef2Arg: func(?number, ?string): string 1046 RefDef2Arg = FuncTwoDefArg 1047 RefDef2Arg()->assert_equal('123text') 1048 RefDef2Arg(99)->assert_equal('99text') 1049 RefDef2Arg(77, 'some')->assert_equal('77some') 1050 1051 CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:') 1052 CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:') 1053 1054 var RefVarargs: func(...list<string>): string 1055 RefVarargs = FuncVarargs 1056 RefVarargs()->assert_equal('') 1057 RefVarargs('one')->assert_equal('one') 1058 RefVarargs('one', 'two')->assert_equal('one,two') 1059 1060 CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:') 1061 CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:') 1062enddef 1063 1064" Only varargs 1065def MyVarargsOnly(...args: list<string>): string 1066 return join(args, ',') 1067enddef 1068 1069def Test_call_varargs_only() 1070 MyVarargsOnly()->assert_equal('') 1071 MyVarargsOnly('one')->assert_equal('one') 1072 MyVarargsOnly('one', 'two')->assert_equal('one,two') 1073 CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number') 1074 CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number') 1075enddef 1076 1077def Test_using_var_as_arg() 1078 writefile(['def Func(x: number)', 'var x = 234', 'enddef', 'defcompile'], 'Xdef') 1079 assert_fails('so Xdef', 'E1006:', '', 1, 'Func') 1080 delete('Xdef') 1081enddef 1082 1083def DictArg(arg: dict<string>) 1084 arg['key'] = 'value' 1085enddef 1086 1087def ListArg(arg: list<string>) 1088 arg[0] = 'value' 1089enddef 1090 1091def Test_assign_to_argument() 1092 # works for dict and list 1093 var d: dict<string> = {} 1094 DictArg(d) 1095 d['key']->assert_equal('value') 1096 var l: list<string> = [] 1097 ListArg(l) 1098 l[0]->assert_equal('value') 1099 1100 CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:') 1101 delfunc! g:Func 1102enddef 1103 1104" These argument names are reserved in legacy functions. 1105def WithReservedNames(firstline: string, lastline: string): string 1106 return firstline .. lastline 1107enddef 1108 1109def Test_argument_names() 1110 assert_equal('OK', WithReservedNames('O', 'K')) 1111enddef 1112 1113def Test_call_func_defined_later() 1114 g:DefinedLater('one')->assert_equal('one') 1115 assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later') 1116enddef 1117 1118func DefinedLater(arg) 1119 return a:arg 1120endfunc 1121 1122def Test_call_funcref() 1123 g:SomeFunc('abc')->assert_equal(3) 1124 assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call 1125 assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref') 1126 1127 var lines =<< trim END 1128 vim9script 1129 def RetNumber(): number 1130 return 123 1131 enddef 1132 var Funcref: func: number = function('RetNumber') 1133 Funcref()->assert_equal(123) 1134 END 1135 CheckScriptSuccess(lines) 1136 1137 lines =<< trim END 1138 vim9script 1139 def RetNumber(): number 1140 return 123 1141 enddef 1142 def Bar(F: func: number): number 1143 return F() 1144 enddef 1145 var Funcref = function('RetNumber') 1146 Bar(Funcref)->assert_equal(123) 1147 END 1148 CheckScriptSuccess(lines) 1149 1150 lines =<< trim END 1151 vim9script 1152 def UseNumber(nr: number) 1153 echo nr 1154 enddef 1155 var Funcref: func(number) = function('UseNumber') 1156 Funcref(123) 1157 END 1158 CheckScriptSuccess(lines) 1159 1160 lines =<< trim END 1161 vim9script 1162 def UseNumber(nr: number) 1163 echo nr 1164 enddef 1165 var Funcref: func(string) = function('UseNumber') 1166 END 1167 CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)') 1168 1169 lines =<< trim END 1170 vim9script 1171 def EchoNr(nr = 34) 1172 g:echo = nr 1173 enddef 1174 var Funcref: func(?number) = function('EchoNr') 1175 Funcref() 1176 g:echo->assert_equal(34) 1177 Funcref(123) 1178 g:echo->assert_equal(123) 1179 END 1180 CheckScriptSuccess(lines) 1181 1182 lines =<< trim END 1183 vim9script 1184 def EchoList(...l: list<number>) 1185 g:echo = l 1186 enddef 1187 var Funcref: func(...list<number>) = function('EchoList') 1188 Funcref() 1189 g:echo->assert_equal([]) 1190 Funcref(1, 2, 3) 1191 g:echo->assert_equal([1, 2, 3]) 1192 END 1193 CheckScriptSuccess(lines) 1194 1195 lines =<< trim END 1196 vim9script 1197 def OptAndVar(nr: number, opt = 12, ...l: list<number>): number 1198 g:optarg = opt 1199 g:listarg = l 1200 return nr 1201 enddef 1202 var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar') 1203 Funcref(10)->assert_equal(10) 1204 g:optarg->assert_equal(12) 1205 g:listarg->assert_equal([]) 1206 1207 Funcref(11, 22)->assert_equal(11) 1208 g:optarg->assert_equal(22) 1209 g:listarg->assert_equal([]) 1210 1211 Funcref(17, 18, 1, 2, 3)->assert_equal(17) 1212 g:optarg->assert_equal(18) 1213 g:listarg->assert_equal([1, 2, 3]) 1214 END 1215 CheckScriptSuccess(lines) 1216enddef 1217 1218let SomeFunc = function('len') 1219let NotAFunc = 'text' 1220 1221def CombineFuncrefTypes() 1222 # same arguments, different return type 1223 var Ref1: func(bool): string 1224 var Ref2: func(bool): number 1225 var Ref3: func(bool): any 1226 Ref3 = g:cond ? Ref1 : Ref2 1227 1228 # different number of arguments 1229 var Refa1: func(bool): number 1230 var Refa2: func(bool, number): number 1231 var Refa3: func: number 1232 Refa3 = g:cond ? Refa1 : Refa2 1233 1234 # different argument types 1235 var Refb1: func(bool, string): number 1236 var Refb2: func(string, number): number 1237 var Refb3: func(any, any): number 1238 Refb3 = g:cond ? Refb1 : Refb2 1239enddef 1240 1241def FuncWithForwardCall() 1242 return g:DefinedEvenLater("yes") 1243enddef 1244 1245def DefinedEvenLater(arg: string): string 1246 return arg 1247enddef 1248 1249def Test_error_in_nested_function() 1250 # Error in called function requires unwinding the call stack. 1251 assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall') 1252enddef 1253 1254def Test_return_type_wrong() 1255 CheckScriptFailure([ 1256 'def Func(): number', 1257 'return "a"', 1258 'enddef', 1259 'defcompile'], 'expected number but got string') 1260 delfunc! g:Func 1261 CheckScriptFailure([ 1262 'def Func(): string', 1263 'return 1', 1264 'enddef', 1265 'defcompile'], 'expected string but got number') 1266 delfunc! g:Func 1267 CheckScriptFailure([ 1268 'def Func(): void', 1269 'return "a"', 1270 'enddef', 1271 'defcompile'], 1272 'E1096: Returning a value in a function without a return type') 1273 delfunc! g:Func 1274 CheckScriptFailure([ 1275 'def Func()', 1276 'return "a"', 1277 'enddef', 1278 'defcompile'], 1279 'E1096: Returning a value in a function without a return type') 1280 delfunc! g:Func 1281 1282 CheckScriptFailure([ 1283 'def Func(): number', 1284 'return', 1285 'enddef', 1286 'defcompile'], 'E1003:') 1287 delfunc! g:Func 1288 1289 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 1290 delfunc! g:Func 1291 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 1292 delfunc! g:Func 1293 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 1294 delfunc! g:Func 1295 1296 CheckScriptFailure([ 1297 'vim9script', 1298 'def FuncB()', 1299 ' return 123', 1300 'enddef', 1301 'def FuncA()', 1302 ' FuncB()', 1303 'enddef', 1304 'defcompile'], 'E1096:') 1305enddef 1306 1307def Test_arg_type_wrong() 1308 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 1309 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 1310 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 1311 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 1312enddef 1313 1314def Test_white_space_before_comma() 1315 var lines =<< trim END 1316 vim9script 1317 def Func(a: number , b: number) 1318 enddef 1319 END 1320 CheckScriptFailure(lines, 'E1068:') 1321enddef 1322 1323def Test_white_space_after_comma() 1324 var lines =<< trim END 1325 vim9script 1326 def Func(a: number,b: number) 1327 enddef 1328 END 1329 CheckScriptFailure(lines, 'E1069:') 1330 1331 # OK in legacy function 1332 lines =<< trim END 1333 vim9script 1334 func Func(a,b) 1335 endfunc 1336 END 1337 CheckScriptSuccess(lines) 1338enddef 1339 1340def Test_vim9script_call() 1341 var lines =<< trim END 1342 vim9script 1343 var name = '' 1344 def MyFunc(arg: string) 1345 name = arg 1346 enddef 1347 MyFunc('foobar') 1348 name->assert_equal('foobar') 1349 1350 var str = 'barfoo' 1351 str->MyFunc() 1352 name->assert_equal('barfoo') 1353 1354 g:value = 'value' 1355 g:value->MyFunc() 1356 name->assert_equal('value') 1357 1358 var listvar = [] 1359 def ListFunc(arg: list<number>) 1360 listvar = arg 1361 enddef 1362 [1, 2, 3]->ListFunc() 1363 listvar->assert_equal([1, 2, 3]) 1364 1365 var dictvar = {} 1366 def DictFunc(arg: dict<number>) 1367 dictvar = arg 1368 enddef 1369 {a: 1, b: 2}->DictFunc() 1370 dictvar->assert_equal({a: 1, b: 2}) 1371 def CompiledDict() 1372 {a: 3, b: 4}->DictFunc() 1373 enddef 1374 CompiledDict() 1375 dictvar->assert_equal({a: 3, b: 4}) 1376 1377 {a: 3, b: 4}->DictFunc() 1378 dictvar->assert_equal({a: 3, b: 4}) 1379 1380 ('text')->MyFunc() 1381 name->assert_equal('text') 1382 ("some")->MyFunc() 1383 name->assert_equal('some') 1384 1385 # line starting with single quote is not a mark 1386 # line starting with double quote can be a method call 1387 'asdfasdf'->MyFunc() 1388 name->assert_equal('asdfasdf') 1389 "xyz"->MyFunc() 1390 name->assert_equal('xyz') 1391 1392 def UseString() 1393 'xyork'->MyFunc() 1394 enddef 1395 UseString() 1396 name->assert_equal('xyork') 1397 1398 def UseString2() 1399 "knife"->MyFunc() 1400 enddef 1401 UseString2() 1402 name->assert_equal('knife') 1403 1404 # prepending a colon makes it a mark 1405 new 1406 setline(1, ['aaa', 'bbb', 'ccc']) 1407 normal! 3Gmt1G 1408 :'t 1409 getcurpos()[1]->assert_equal(3) 1410 bwipe! 1411 1412 MyFunc( 1413 'continued' 1414 ) 1415 assert_equal('continued', 1416 name 1417 ) 1418 1419 call MyFunc( 1420 'more' 1421 .. 1422 'lines' 1423 ) 1424 assert_equal( 1425 'morelines', 1426 name) 1427 END 1428 writefile(lines, 'Xcall.vim') 1429 source Xcall.vim 1430 delete('Xcall.vim') 1431enddef 1432 1433def Test_vim9script_call_fail_decl() 1434 var lines =<< trim END 1435 vim9script 1436 var name = '' 1437 def MyFunc(arg: string) 1438 var name = 123 1439 enddef 1440 defcompile 1441 END 1442 CheckScriptFailure(lines, 'E1054:') 1443enddef 1444 1445def Test_vim9script_call_fail_type() 1446 var lines =<< trim END 1447 vim9script 1448 def MyFunc(arg: string) 1449 echo arg 1450 enddef 1451 MyFunc(1234) 1452 END 1453 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number') 1454enddef 1455 1456def Test_vim9script_call_fail_const() 1457 var lines =<< trim END 1458 vim9script 1459 const var = '' 1460 def MyFunc(arg: string) 1461 var = 'asdf' 1462 enddef 1463 defcompile 1464 END 1465 writefile(lines, 'Xcall_const.vim') 1466 assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') 1467 delete('Xcall_const.vim') 1468 1469 lines =<< trim END 1470 const g:Aconst = 77 1471 def Change() 1472 # comment 1473 g:Aconst = 99 1474 enddef 1475 call Change() 1476 unlet g:Aconst 1477 END 1478 CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) 1479enddef 1480 1481" Test that inside :function a Python function can be defined, :def is not 1482" recognized. 1483func Test_function_python() 1484 CheckFeature python3 1485 let py = 'python3' 1486 execute py "<< EOF" 1487def do_something(): 1488 return 1 1489EOF 1490endfunc 1491 1492def Test_delfunc() 1493 var lines =<< trim END 1494 vim9script 1495 def g:GoneSoon() 1496 echo 'hello' 1497 enddef 1498 1499 def CallGoneSoon() 1500 GoneSoon() 1501 enddef 1502 defcompile 1503 1504 delfunc g:GoneSoon 1505 CallGoneSoon() 1506 END 1507 writefile(lines, 'XToDelFunc') 1508 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1509 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1510 1511 delete('XToDelFunc') 1512enddef 1513 1514def Test_redef_failure() 1515 writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 1516 so Xdef 1517 writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 1518 so Xdef 1519 writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 1520 assert_fails('so Xdef', 'E1027:', '', 1, 'Func0') 1521 writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 1522 so Xdef 1523 delete('Xdef') 1524 1525 assert_fails('g:Func0()', 'E1091:') 1526 g:Func1()->assert_equal('Func1') 1527 g:Func2()->assert_equal('Func2') 1528 1529 delfunc! Func0 1530 delfunc! Func1 1531 delfunc! Func2 1532enddef 1533 1534def Test_vim9script_func() 1535 var lines =<< trim END 1536 vim9script 1537 func Func(arg) 1538 echo a:arg 1539 endfunc 1540 Func('text') 1541 END 1542 writefile(lines, 'XVim9Func') 1543 so XVim9Func 1544 1545 delete('XVim9Func') 1546enddef 1547 1548let s:funcResult = 0 1549 1550def FuncNoArgNoRet() 1551 s:funcResult = 11 1552enddef 1553 1554def FuncNoArgRetNumber(): number 1555 s:funcResult = 22 1556 return 1234 1557enddef 1558 1559def FuncNoArgRetString(): string 1560 s:funcResult = 45 1561 return 'text' 1562enddef 1563 1564def FuncOneArgNoRet(arg: number) 1565 s:funcResult = arg 1566enddef 1567 1568def FuncOneArgRetNumber(arg: number): number 1569 s:funcResult = arg 1570 return arg 1571enddef 1572 1573def FuncTwoArgNoRet(one: bool, two: number) 1574 s:funcResult = two 1575enddef 1576 1577def FuncOneArgRetString(arg: string): string 1578 return arg 1579enddef 1580 1581def FuncOneArgRetAny(arg: any): any 1582 return arg 1583enddef 1584 1585def Test_func_type() 1586 var Ref1: func() 1587 s:funcResult = 0 1588 Ref1 = FuncNoArgNoRet 1589 Ref1() 1590 s:funcResult->assert_equal(11) 1591 1592 var Ref2: func 1593 s:funcResult = 0 1594 Ref2 = FuncNoArgNoRet 1595 Ref2() 1596 s:funcResult->assert_equal(11) 1597 1598 s:funcResult = 0 1599 Ref2 = FuncOneArgNoRet 1600 Ref2(12) 1601 s:funcResult->assert_equal(12) 1602 1603 s:funcResult = 0 1604 Ref2 = FuncNoArgRetNumber 1605 Ref2()->assert_equal(1234) 1606 s:funcResult->assert_equal(22) 1607 1608 s:funcResult = 0 1609 Ref2 = FuncOneArgRetNumber 1610 Ref2(13)->assert_equal(13) 1611 s:funcResult->assert_equal(13) 1612enddef 1613 1614def Test_repeat_return_type() 1615 var res = 0 1616 for n in repeat([1], 3) 1617 res += n 1618 endfor 1619 res->assert_equal(3) 1620 1621 res = 0 1622 for n in add([1, 2], 3) 1623 res += n 1624 endfor 1625 res->assert_equal(6) 1626enddef 1627 1628def Test_argv_return_type() 1629 next fileone filetwo 1630 var res = '' 1631 for name in argv() 1632 res ..= name 1633 endfor 1634 res->assert_equal('fileonefiletwo') 1635enddef 1636 1637def Test_func_type_part() 1638 var RefVoid: func: void 1639 RefVoid = FuncNoArgNoRet 1640 RefVoid = FuncOneArgNoRet 1641 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number') 1642 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string') 1643 1644 var RefAny: func(): any 1645 RefAny = FuncNoArgRetNumber 1646 RefAny = FuncNoArgRetString 1647 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()') 1648 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)') 1649 1650 var RefAnyNoArgs: func: any = RefAny 1651 1652 var RefNr: func: number 1653 RefNr = FuncNoArgRetNumber 1654 RefNr = FuncOneArgRetNumber 1655 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()') 1656 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string') 1657 1658 var RefStr: func: string 1659 RefStr = FuncNoArgRetString 1660 RefStr = FuncOneArgRetString 1661 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()') 1662 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number') 1663enddef 1664 1665def Test_func_type_fails() 1666 CheckDefFailure(['var ref1: func()'], 'E704:') 1667 1668 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number') 1669 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)') 1670 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number') 1671 CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)') 1672 CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)') 1673 CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)') 1674 1675 CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:') 1676 CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:') 1677 CheckDefFailure(['var RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E1005:') 1678 CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:') 1679enddef 1680 1681def Test_func_return_type() 1682 var nr: number 1683 nr = FuncNoArgRetNumber() 1684 nr->assert_equal(1234) 1685 1686 nr = FuncOneArgRetAny(122) 1687 nr->assert_equal(122) 1688 1689 var str: string 1690 str = FuncOneArgRetAny('yes') 1691 str->assert_equal('yes') 1692 1693 CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number') 1694enddef 1695 1696def Test_func_common_type() 1697 def FuncOne(n: number): number 1698 return n 1699 enddef 1700 def FuncTwo(s: string): number 1701 return len(s) 1702 enddef 1703 def FuncThree(n: number, s: string): number 1704 return n + len(s) 1705 enddef 1706 var list = [FuncOne, FuncTwo, FuncThree] 1707 assert_equal(8, list[0](8)) 1708 assert_equal(4, list[1]('word')) 1709 assert_equal(7, list[2](3, 'word')) 1710enddef 1711 1712def MultiLine( 1713 arg1: string, 1714 arg2 = 1234, 1715 ...rest: list<string> 1716 ): string 1717 return arg1 .. arg2 .. join(rest, '-') 1718enddef 1719 1720def MultiLineComment( 1721 arg1: string, # comment 1722 arg2 = 1234, # comment 1723 ...rest: list<string> # comment 1724 ): string # comment 1725 return arg1 .. arg2 .. join(rest, '-') 1726enddef 1727 1728def Test_multiline() 1729 MultiLine('text')->assert_equal('text1234') 1730 MultiLine('text', 777)->assert_equal('text777') 1731 MultiLine('text', 777, 'one')->assert_equal('text777one') 1732 MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1733enddef 1734 1735func Test_multiline_not_vim9() 1736 call MultiLine('text')->assert_equal('text1234') 1737 call MultiLine('text', 777)->assert_equal('text777') 1738 call MultiLine('text', 777, 'one')->assert_equal('text777one') 1739 call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1740endfunc 1741 1742 1743" When using CheckScriptFailure() for the below test, E1010 is generated instead 1744" of E1056. 1745func Test_E1056_1059() 1746 let caught_1056 = 0 1747 try 1748 def F(): 1749 return 1 1750 enddef 1751 catch /E1056:/ 1752 let caught_1056 = 1 1753 endtry 1754 eval caught_1056->assert_equal(1) 1755 1756 let caught_1059 = 0 1757 try 1758 def F5(items : list) 1759 echo 'a' 1760 enddef 1761 catch /E1059:/ 1762 let caught_1059 = 1 1763 endtry 1764 eval caught_1059->assert_equal(1) 1765endfunc 1766 1767func DelMe() 1768 echo 'DelMe' 1769endfunc 1770 1771def Test_error_reporting() 1772 # comment lines at the start of the function 1773 var lines =<< trim END 1774 " comment 1775 def Func() 1776 # comment 1777 # comment 1778 invalid 1779 enddef 1780 defcompile 1781 END 1782 writefile(lines, 'Xdef') 1783 try 1784 source Xdef 1785 assert_report('should have failed') 1786 catch /E476:/ 1787 v:exception->assert_match('Invalid command: invalid') 1788 v:throwpoint->assert_match(', line 3$') 1789 endtry 1790 delfunc! g:Func 1791 1792 # comment lines after the start of the function 1793 lines =<< trim END 1794 " comment 1795 def Func() 1796 var x = 1234 1797 # comment 1798 # comment 1799 invalid 1800 enddef 1801 defcompile 1802 END 1803 writefile(lines, 'Xdef') 1804 try 1805 source Xdef 1806 assert_report('should have failed') 1807 catch /E476:/ 1808 v:exception->assert_match('Invalid command: invalid') 1809 v:throwpoint->assert_match(', line 4$') 1810 endtry 1811 delfunc! g:Func 1812 1813 lines =<< trim END 1814 vim9script 1815 def Func() 1816 var db = {foo: 1, bar: 2} 1817 # comment 1818 var x = db.asdf 1819 enddef 1820 defcompile 1821 Func() 1822 END 1823 writefile(lines, 'Xdef') 1824 try 1825 source Xdef 1826 assert_report('should have failed') 1827 catch /E716:/ 1828 v:throwpoint->assert_match('_Func, line 3$') 1829 endtry 1830 delfunc! g:Func 1831 1832 delete('Xdef') 1833enddef 1834 1835def Test_deleted_function() 1836 CheckDefExecFailure([ 1837 'var RefMe: func = function("g:DelMe")', 1838 'delfunc g:DelMe', 1839 'echo RefMe()'], 'E117:') 1840enddef 1841 1842def Test_unknown_function() 1843 CheckDefExecFailure([ 1844 'var Ref: func = function("NotExist")', 1845 'delfunc g:NotExist'], 'E700:') 1846enddef 1847 1848def RefFunc(Ref: func(any): any): string 1849 return Ref('more') 1850enddef 1851 1852def Test_closure_simple() 1853 var local = 'some ' 1854 RefFunc((s) => local .. s)->assert_equal('some more') 1855enddef 1856 1857def MakeRef() 1858 var local = 'some ' 1859 g:Ref = (s) => local .. s 1860enddef 1861 1862def Test_closure_ref_after_return() 1863 MakeRef() 1864 g:Ref('thing')->assert_equal('some thing') 1865 unlet g:Ref 1866enddef 1867 1868def MakeTwoRefs() 1869 var local = ['some'] 1870 g:Extend = (s) => local->add(s) 1871 g:Read = () => local 1872enddef 1873 1874def Test_closure_two_refs() 1875 MakeTwoRefs() 1876 join(g:Read(), ' ')->assert_equal('some') 1877 g:Extend('more') 1878 join(g:Read(), ' ')->assert_equal('some more') 1879 g:Extend('even') 1880 join(g:Read(), ' ')->assert_equal('some more even') 1881 1882 unlet g:Extend 1883 unlet g:Read 1884enddef 1885 1886def ReadRef(Ref: func(): list<string>): string 1887 return join(Ref(), ' ') 1888enddef 1889 1890def ExtendRef(Ref: func(string): list<string>, add: string) 1891 Ref(add) 1892enddef 1893 1894def Test_closure_two_indirect_refs() 1895 MakeTwoRefs() 1896 ReadRef(g:Read)->assert_equal('some') 1897 ExtendRef(g:Extend, 'more') 1898 ReadRef(g:Read)->assert_equal('some more') 1899 ExtendRef(g:Extend, 'even') 1900 ReadRef(g:Read)->assert_equal('some more even') 1901 1902 unlet g:Extend 1903 unlet g:Read 1904enddef 1905 1906def MakeArgRefs(theArg: string) 1907 var local = 'loc_val' 1908 g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s 1909enddef 1910 1911def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 1912 var local = 'the_loc' 1913 g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest) 1914enddef 1915 1916def Test_closure_using_argument() 1917 MakeArgRefs('arg_val') 1918 g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val') 1919 1920 MakeArgRefsVarargs('arg_val', 'one', 'two') 1921 g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two') 1922 1923 unlet g:UseArg 1924 unlet g:UseVararg 1925 1926 var lines =<< trim END 1927 vim9script 1928 def Test(Fun: func(number): number): list<number> 1929 return map([1, 2, 3], (_, i) => Fun(i)) 1930 enddef 1931 def Inc(nr: number): number 1932 return nr + 2 1933 enddef 1934 assert_equal([3, 4, 5], Test(Inc)) 1935 END 1936 CheckScriptSuccess(lines) 1937enddef 1938 1939def MakeGetAndAppendRefs() 1940 var local = 'a' 1941 1942 def Append(arg: string) 1943 local ..= arg 1944 enddef 1945 g:Append = Append 1946 1947 def Get(): string 1948 return local 1949 enddef 1950 g:Get = Get 1951enddef 1952 1953def Test_closure_append_get() 1954 MakeGetAndAppendRefs() 1955 g:Get()->assert_equal('a') 1956 g:Append('-b') 1957 g:Get()->assert_equal('a-b') 1958 g:Append('-c') 1959 g:Get()->assert_equal('a-b-c') 1960 1961 unlet g:Append 1962 unlet g:Get 1963enddef 1964 1965def Test_nested_closure() 1966 var local = 'text' 1967 def Closure(arg: string): string 1968 return local .. arg 1969 enddef 1970 Closure('!!!')->assert_equal('text!!!') 1971enddef 1972 1973func GetResult(Ref) 1974 return a:Ref('some') 1975endfunc 1976 1977def Test_call_closure_not_compiled() 1978 var text = 'text' 1979 g:Ref = (s) => s .. text 1980 GetResult(g:Ref)->assert_equal('sometext') 1981enddef 1982 1983def Test_double_closure_fails() 1984 var lines =<< trim END 1985 vim9script 1986 def Func() 1987 var name = 0 1988 for i in range(2) 1989 timer_start(0, () => name) 1990 endfor 1991 enddef 1992 Func() 1993 END 1994 CheckScriptSuccess(lines) 1995enddef 1996 1997def Test_nested_closure_used() 1998 var lines =<< trim END 1999 vim9script 2000 def Func() 2001 var x = 'hello' 2002 var Closure = () => x 2003 g:Myclosure = () => Closure() 2004 enddef 2005 Func() 2006 assert_equal('hello', g:Myclosure()) 2007 END 2008 CheckScriptSuccess(lines) 2009enddef 2010 2011def Test_nested_closure_fails() 2012 var lines =<< trim END 2013 vim9script 2014 def FuncA() 2015 FuncB(0) 2016 enddef 2017 def FuncB(n: number): list<string> 2018 return map([0], (_, v) => n) 2019 enddef 2020 FuncA() 2021 END 2022 CheckScriptFailure(lines, 'E1012:') 2023enddef 2024 2025def Test_global_closure() 2026 var lines =<< trim END 2027 vim9script 2028 def ReverseEveryNLines(n: number, line1: number, line2: number) 2029 var mods = 'sil keepj keepp lockm ' 2030 var range = ':' .. line1 .. ',' .. line2 2031 def g:Offset(): number 2032 var offset = (line('.') - line1 + 1) % n 2033 return offset != 0 ? offset : n 2034 enddef 2035 exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()' 2036 enddef 2037 2038 new 2039 repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1) 2040 ReverseEveryNLines(3, 1, 9) 2041 END 2042 CheckScriptSuccess(lines) 2043 var expected = repeat(['ccc', 'bbb', 'aaa'], 3) 2044 assert_equal(expected, getline(1, 9)) 2045 bwipe! 2046enddef 2047 2048def Test_global_closure_called_directly() 2049 var lines =<< trim END 2050 vim9script 2051 def Outer() 2052 var x = 1 2053 def g:Inner() 2054 var y = x 2055 x += 1 2056 assert_equal(1, y) 2057 enddef 2058 g:Inner() 2059 assert_equal(2, x) 2060 enddef 2061 Outer() 2062 END 2063 CheckScriptSuccess(lines) 2064 delfunc g:Inner 2065enddef 2066 2067def Test_failure_in_called_function() 2068 # this was using the frame index as the return value 2069 var lines =<< trim END 2070 vim9script 2071 au TerminalWinOpen * eval [][0] 2072 def PopupTerm(a: any) 2073 # make sure typvals on stack are string 2074 ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join() 2075 FireEvent() 2076 enddef 2077 def FireEvent() 2078 do TerminalWinOpen 2079 enddef 2080 # use try/catch to make eval fail 2081 try 2082 call PopupTerm(0) 2083 catch 2084 endtry 2085 au! TerminalWinOpen 2086 END 2087 CheckScriptSuccess(lines) 2088enddef 2089 2090def Test_nested_lambda() 2091 var lines =<< trim END 2092 vim9script 2093 def Func() 2094 var x = 4 2095 var Lambda1 = () => 7 2096 var Lambda2 = () => [Lambda1(), x] 2097 var res = Lambda2() 2098 assert_equal([7, 4], res) 2099 enddef 2100 Func() 2101 END 2102 CheckScriptSuccess(lines) 2103enddef 2104 2105def Shadowed(): list<number> 2106 var FuncList: list<func: number> = [() => 42] 2107 return FuncList->mapnew((_, Shadowed) => Shadowed()) 2108enddef 2109 2110def Test_lambda_arg_shadows_func() 2111 assert_equal([42], Shadowed()) 2112enddef 2113 2114def Line_continuation_in_def(dir: string = ''): string 2115 var path: string = empty(dir) 2116 \ ? 'empty' 2117 \ : 'full' 2118 return path 2119enddef 2120 2121def Test_line_continuation_in_def() 2122 Line_continuation_in_def('.')->assert_equal('full') 2123enddef 2124 2125def Test_script_var_in_lambda() 2126 var lines =<< trim END 2127 vim9script 2128 var script = 'test' 2129 assert_equal(['test'], map(['one'], (_, _) => script)) 2130 END 2131 CheckScriptSuccess(lines) 2132enddef 2133 2134def Line_continuation_in_lambda(): list<string> 2135 var x = range(97, 100) 2136 ->mapnew((_, v) => nr2char(v) 2137 ->toupper()) 2138 ->reverse() 2139 return x 2140enddef 2141 2142def Test_line_continuation_in_lambda() 2143 Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A']) 2144 2145 var lines =<< trim END 2146 vim9script 2147 var res = [{n: 1, m: 2, s: 'xxx'}] 2148 ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s', 2149 v.n, 2150 v.m, 2151 substitute(v.s, '.*', 'yyy', '') 2152 )) 2153 assert_equal(['1:2:yyy'], res) 2154 END 2155 CheckScriptSuccess(lines) 2156enddef 2157 2158def Test_list_lambda() 2159 timer_start(1000, (_) => 0) 2160 var body = execute(timer_info()[0].callback 2161 ->string() 2162 ->substitute("('", ' ', '') 2163 ->substitute("')", '', '') 2164 ->substitute('function\zs', ' ', '')) 2165 assert_match('def <lambda>\d\+(_: any): number\n1 return 0\n enddef', body) 2166enddef 2167 2168def Test_legacy_lambda() 2169 legacy echo {x -> 'hello ' .. x}('foo') 2170 2171 var lines =<< trim END 2172 echo {x -> 'hello ' .. x}('foo') 2173 END 2174 CheckDefAndScriptFailure(lines, 'E720:') 2175 2176 lines =<< trim END 2177 vim9script 2178 def Func() 2179 echo (() => 'no error')() 2180 enddef 2181 legacy call s:Func() 2182 END 2183 CheckScriptSuccess(lines) 2184enddef 2185 2186def DoFilterThis(a: string): list<string> 2187 # closure nested inside another closure using argument 2188 var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0) 2189 return ['x', 'y', 'a', 'x2', 'c']->Filter() 2190enddef 2191 2192def Test_nested_closure_using_argument() 2193 assert_equal(['x', 'x2'], DoFilterThis('x')) 2194enddef 2195 2196def Test_triple_nested_closure() 2197 var what = 'x' 2198 var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0 2199 var Filter = (l) => filter(l, (_, v) => Match(v, what)) 2200 assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter()) 2201enddef 2202 2203func Test_silent_echo() 2204 CheckScreendump 2205 2206 let lines =<< trim END 2207 vim9script 2208 def EchoNothing() 2209 silent echo '' 2210 enddef 2211 defcompile 2212 END 2213 call writefile(lines, 'XTest_silent_echo') 2214 2215 " Check that the balloon shows up after a mouse move 2216 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 2217 call term_sendkeys(buf, ":abc") 2218 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 2219 2220 " clean up 2221 call StopVimInTerminal(buf) 2222 call delete('XTest_silent_echo') 2223endfunc 2224 2225def SilentlyError() 2226 execute('silent! invalid') 2227 g:did_it = 'yes' 2228enddef 2229 2230func UserError() 2231 silent! invalid 2232endfunc 2233 2234def SilentlyUserError() 2235 UserError() 2236 g:did_it = 'yes' 2237enddef 2238 2239" This can't be a :def function, because the assert would not be reached. 2240func Test_ignore_silent_error() 2241 let g:did_it = 'no' 2242 call SilentlyError() 2243 call assert_equal('yes', g:did_it) 2244 2245 let g:did_it = 'no' 2246 call SilentlyUserError() 2247 call assert_equal('yes', g:did_it) 2248 2249 unlet g:did_it 2250endfunc 2251 2252def Test_ignore_silent_error_in_filter() 2253 var lines =<< trim END 2254 vim9script 2255 def Filter(winid: number, key: string): bool 2256 if key == 'o' 2257 silent! eval [][0] 2258 return true 2259 endif 2260 return popup_filter_menu(winid, key) 2261 enddef 2262 2263 popup_create('popup', {filter: Filter}) 2264 feedkeys("o\r", 'xnt') 2265 END 2266 CheckScriptSuccess(lines) 2267enddef 2268 2269def Fibonacci(n: number): number 2270 if n < 2 2271 return n 2272 else 2273 return Fibonacci(n - 1) + Fibonacci(n - 2) 2274 endif 2275enddef 2276 2277def Test_recursive_call() 2278 Fibonacci(20)->assert_equal(6765) 2279enddef 2280 2281def TreeWalk(dir: string): list<any> 2282 return readdir(dir)->mapnew((_, val) => 2283 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 2284 ? {[val]: TreeWalk(dir .. '/' .. val)} 2285 : val 2286 ) 2287enddef 2288 2289def Test_closure_in_map() 2290 mkdir('XclosureDir/tdir', 'p') 2291 writefile(['111'], 'XclosureDir/file1') 2292 writefile(['222'], 'XclosureDir/file2') 2293 writefile(['333'], 'XclosureDir/tdir/file3') 2294 2295 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) 2296 2297 delete('XclosureDir', 'rf') 2298enddef 2299 2300def Test_invalid_function_name() 2301 var lines =<< trim END 2302 vim9script 2303 def s: list<string> 2304 END 2305 CheckScriptFailure(lines, 'E129:') 2306 2307 lines =<< trim END 2308 vim9script 2309 def g: list<string> 2310 END 2311 CheckScriptFailure(lines, 'E129:') 2312 2313 lines =<< trim END 2314 vim9script 2315 def <SID>: list<string> 2316 END 2317 CheckScriptFailure(lines, 'E884:') 2318 2319 lines =<< trim END 2320 vim9script 2321 def F list<string> 2322 END 2323 CheckScriptFailure(lines, 'E488:') 2324enddef 2325 2326def Test_partial_call() 2327 var Xsetlist = function('setloclist', [0]) 2328 Xsetlist([], ' ', {title: 'test'}) 2329 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2330 2331 Xsetlist = function('setloclist', [0, [], ' ']) 2332 Xsetlist({title: 'test'}) 2333 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2334 2335 Xsetlist = function('setqflist') 2336 Xsetlist([], ' ', {title: 'test'}) 2337 getqflist({title: 1})->assert_equal({title: 'test'}) 2338 2339 Xsetlist = function('setqflist', [[], ' ']) 2340 Xsetlist({title: 'test'}) 2341 getqflist({title: 1})->assert_equal({title: 'test'}) 2342 2343 var Len: func: number = function('len', ['word']) 2344 assert_equal(4, Len()) 2345enddef 2346 2347def Test_cmd_modifier() 2348 tab echo '0' 2349 CheckDefFailure(['5tab echo 3'], 'E16:') 2350enddef 2351 2352def Test_restore_modifiers() 2353 # check that when compiling a :def function command modifiers are not messed 2354 # up. 2355 var lines =<< trim END 2356 vim9script 2357 set eventignore= 2358 autocmd QuickFixCmdPost * copen 2359 def AutocmdsDisabled() 2360 eval 0 2361 enddef 2362 func Func() 2363 noautocmd call s:AutocmdsDisabled() 2364 let g:ei_after = &eventignore 2365 endfunc 2366 Func() 2367 END 2368 CheckScriptSuccess(lines) 2369 g:ei_after->assert_equal('') 2370enddef 2371 2372def StackTop() 2373 eval 1 2374 eval 2 2375 # call not on fourth line 2376 StackBot() 2377enddef 2378 2379def StackBot() 2380 # throw an error 2381 eval [][0] 2382enddef 2383 2384def Test_callstack_def() 2385 try 2386 StackTop() 2387 catch 2388 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2') 2389 endtry 2390enddef 2391 2392" Re-using spot for variable used in block 2393def Test_block_scoped_var() 2394 var lines =<< trim END 2395 vim9script 2396 def Func() 2397 var x = ['a', 'b', 'c'] 2398 if 1 2399 var y = 'x' 2400 map(x, (_, _) => y) 2401 endif 2402 var z = x 2403 assert_equal(['x', 'x', 'x'], z) 2404 enddef 2405 Func() 2406 END 2407 CheckScriptSuccess(lines) 2408enddef 2409 2410def Test_reset_did_emsg() 2411 var lines =<< trim END 2412 @s = 'blah' 2413 au BufWinLeave * # 2414 def Func() 2415 var winid = popup_create('popup', {}) 2416 exe '*s' 2417 popup_close(winid) 2418 enddef 2419 Func() 2420 END 2421 CheckScriptFailure(lines, 'E492:', 8) 2422 delfunc! g:Func 2423enddef 2424 2425def Test_did_emsg_reset() 2426 # executing an autocommand resets did_emsg, this should not result in a 2427 # builtin function considered failing 2428 var lines =<< trim END 2429 vim9script 2430 au BufWinLeave * # 2431 def Func() 2432 popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()}) 2433 eval [][0] 2434 enddef 2435 nno <F3> <cmd>call <sid>Func()<cr> 2436 feedkeys("\<F3>\e", 'xt') 2437 END 2438 writefile(lines, 'XemsgReset') 2439 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) 2440 delete('XemsgReset') 2441 nunmap <F3> 2442 au! BufWinLeave 2443enddef 2444 2445def Test_abort_with_silent_call() 2446 var lines =<< trim END 2447 vim9script 2448 g:result = 'none' 2449 def Func() 2450 g:result += 3 2451 g:result = 'yes' 2452 enddef 2453 # error is silenced, but function aborts on error 2454 silent! Func() 2455 assert_equal('none', g:result) 2456 unlet g:result 2457 END 2458 CheckScriptSuccess(lines) 2459enddef 2460 2461def Test_continues_with_silent_error() 2462 var lines =<< trim END 2463 vim9script 2464 g:result = 'none' 2465 def Func() 2466 silent! g:result += 3 2467 g:result = 'yes' 2468 enddef 2469 # error is silenced, function does not abort 2470 Func() 2471 assert_equal('yes', g:result) 2472 unlet g:result 2473 END 2474 CheckScriptSuccess(lines) 2475enddef 2476 2477def Test_abort_even_with_silent() 2478 var lines =<< trim END 2479 vim9script 2480 g:result = 'none' 2481 def Func() 2482 eval {-> ''}() .. '' .. {}['X'] 2483 g:result = 'yes' 2484 enddef 2485 silent! Func() 2486 assert_equal('none', g:result) 2487 unlet g:result 2488 END 2489 CheckScriptSuccess(lines) 2490enddef 2491 2492def Test_cmdmod_silent_restored() 2493 var lines =<< trim END 2494 vim9script 2495 def Func() 2496 g:result = 'none' 2497 silent! g:result += 3 2498 g:result = 'none' 2499 g:result += 3 2500 enddef 2501 Func() 2502 END 2503 # can't use CheckScriptFailure, it ignores the :silent! 2504 var fname = 'Xdefsilent' 2505 writefile(lines, fname) 2506 var caught = 'no' 2507 try 2508 exe 'source ' .. fname 2509 catch /E1030:/ 2510 caught = 'yes' 2511 assert_match('Func, line 4', v:throwpoint) 2512 endtry 2513 assert_equal('yes', caught) 2514 delete(fname) 2515enddef 2516 2517def Test_cmdmod_silent_nested() 2518 var lines =<< trim END 2519 vim9script 2520 var result = '' 2521 2522 def Error() 2523 result ..= 'Eb' 2524 eval [][0] 2525 result ..= 'Ea' 2526 enddef 2527 2528 def Crash() 2529 result ..= 'Cb' 2530 sil! Error() 2531 result ..= 'Ca' 2532 enddef 2533 2534 Crash() 2535 assert_equal('CbEbEaCa', result) 2536 END 2537 CheckScriptSuccess(lines) 2538enddef 2539 2540def Test_dict_member_with_silent() 2541 var lines =<< trim END 2542 vim9script 2543 g:result = 'none' 2544 var d: dict<any> 2545 def Func() 2546 try 2547 g:result = map([], (_, v) => ({}[v]))->join() .. d[''] 2548 catch 2549 endtry 2550 enddef 2551 silent! Func() 2552 assert_equal('0', g:result) 2553 unlet g:result 2554 END 2555 CheckScriptSuccess(lines) 2556enddef 2557 2558def Test_skip_cmds_with_silent() 2559 var lines =<< trim END 2560 vim9script 2561 2562 def Func(b: bool) 2563 Crash() 2564 enddef 2565 2566 def Crash() 2567 sil! :/not found/d _ 2568 sil! :/not found/put _ 2569 enddef 2570 2571 Func(true) 2572 END 2573 CheckScriptSuccess(lines) 2574enddef 2575 2576def Test_opfunc() 2577 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@ 2578 def g:Opfunc(_: any): string 2579 setline(1, 'ASDF') 2580 return '' 2581 enddef 2582 new 2583 setline(1, 'asdf') 2584 feedkeys("\<F3>$", 'x') 2585 assert_equal('ASDF', getline(1)) 2586 2587 bwipe! 2588 nunmap <F3> 2589enddef 2590 2591" this was crashing on exit 2592def Test_nested_lambda_in_closure() 2593 var lines =<< trim END 2594 vim9script 2595 command WriteDone writefile(['Done'], 'XnestedDone') 2596 def Outer() 2597 def g:Inner() 2598 echo map([1, 2, 3], {_, v -> v + 1}) 2599 enddef 2600 g:Inner() 2601 enddef 2602 defcompile 2603 # not reached 2604 END 2605 if !RunVim([], lines, '--clean -c WriteDone -c quit') 2606 return 2607 endif 2608 assert_equal(['Done'], readfile('XnestedDone')) 2609 delete('XnestedDone') 2610enddef 2611 2612def Test_check_func_arg_types() 2613 var lines =<< trim END 2614 vim9script 2615 def F1(x: string): string 2616 return x 2617 enddef 2618 2619 def F2(x: number): number 2620 return x + 1 2621 enddef 2622 2623 def G(g: func): dict<func> 2624 return {f: g} 2625 enddef 2626 2627 def H(d: dict<func>): string 2628 return d.f('a') 2629 enddef 2630 END 2631 2632 CheckScriptSuccess(lines + ['echo H(G(F1))']) 2633 CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:') 2634enddef 2635 2636def Test_compile_error() 2637 var lines =<< trim END 2638 def g:Broken() 2639 echo 'a' + {} 2640 enddef 2641 call g:Broken() 2642 END 2643 # First call: compilation error 2644 CheckScriptFailure(lines, 'E1051: Wrong argument type for +') 2645 2646 # Second call won't try compiling again 2647 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2648 delfunc g:Broken 2649 2650 # No error when compiling with :silent! 2651 lines =<< trim END 2652 def g:Broken() 2653 echo 'a' + [] 2654 enddef 2655 silent! defcompile 2656 END 2657 CheckScriptSuccess(lines) 2658 2659 # Calling the function won't try compiling again 2660 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2661 delfunc g:Broken 2662enddef 2663 2664def Test_ignored_argument() 2665 var lines =<< trim END 2666 vim9script 2667 def Ignore(_, _): string 2668 return 'yes' 2669 enddef 2670 assert_equal('yes', Ignore(1, 2)) 2671 2672 func Ok(_) 2673 return a:_ 2674 endfunc 2675 assert_equal('ok', Ok('ok')) 2676 2677 func Oktoo() 2678 let _ = 'too' 2679 return _ 2680 endfunc 2681 assert_equal('too', Oktoo()) 2682 2683 assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1))) 2684 END 2685 CheckScriptSuccess(lines) 2686 2687 lines =<< trim END 2688 def Ignore(_: string): string 2689 return _ 2690 enddef 2691 defcompile 2692 END 2693 CheckScriptFailure(lines, 'E1181:', 1) 2694 2695 lines =<< trim END 2696 var _ = 1 2697 END 2698 CheckDefAndScriptFailure(lines, 'E1181:', 1) 2699enddef 2700 2701def Test_too_many_arguments() 2702 var lines =<< trim END 2703 echo [0, 1, 2]->map(() => 123) 2704 END 2705 CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1) 2706 2707 lines =<< trim END 2708 echo [0, 1, 2]->map((_) => 123) 2709 END 2710 CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1) 2711enddef 2712 2713def Test_closing_brace_at_start_of_line() 2714 var lines =<< trim END 2715 def Func() 2716 enddef 2717 Func( 2718 ) 2719 END 2720 call CheckDefAndScriptSuccess(lines) 2721enddef 2722 2723 2724" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 2725