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