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 Test_lambda_line_nr() 1056 var lines =<< trim END 1057 vim9script 1058 # comment 1059 # comment 1060 var id = timer_start(1'000, (_) => 0) 1061 var out = execute('verbose ' .. timer_info(id)[0].callback 1062 ->string() 1063 ->substitute("('\\|')", ' ', 'g')) 1064 assert_match('Last set from .* line 4', out) 1065 END 1066 CheckScriptSuccess(lines) 1067enddef 1068 1069def FilterWithCond(x: string, Cond: func(string): bool): bool 1070 return Cond(x) 1071enddef 1072 1073def Test_lambda_return_type() 1074 var lines =<< trim END 1075 var Ref = (): => 123 1076 END 1077 CheckDefAndScriptFailure(lines, 'E1157:', 1) 1078 1079 # no space before the return type 1080 lines =<< trim END 1081 var Ref = (x):number => x + 1 1082 END 1083 CheckDefAndScriptFailure(lines, 'E1069:', 1) 1084 1085 # this works 1086 for x in ['foo', 'boo'] 1087 echo FilterWithCond(x, (v) => v =~ '^b') 1088 endfor 1089 1090 # this fails 1091 lines =<< trim END 1092 echo FilterWithCond('foo', (v) => v .. '^b') 1093 END 1094 CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1) 1095 1096 lines =<< trim END 1097 var Lambda1 = (x) => { 1098 return x 1099 } 1100 assert_equal('asdf', Lambda1('asdf')) 1101 var Lambda2 = (x): string => { 1102 return x 1103 } 1104 assert_equal('foo', Lambda2('foo')) 1105 END 1106 CheckDefAndScriptSuccess(lines) 1107 1108 lines =<< trim END 1109 var Lambda = (x): string => { 1110 return x 1111 } 1112 echo Lambda(['foo']) 1113 END 1114 CheckDefExecAndScriptFailure(lines, 'E1012:') 1115enddef 1116 1117def Test_lambda_uses_assigned_var() 1118 CheckDefSuccess([ 1119 'var x: any = "aaa"' 1120 'x = filter(["bbb"], (_, v) => v =~ x)']) 1121enddef 1122 1123def Test_pass_legacy_lambda_to_def_func() 1124 var lines =<< trim END 1125 vim9script 1126 func Foo() 1127 eval s:Bar({x -> 0}) 1128 endfunc 1129 def Bar(y: any) 1130 enddef 1131 Foo() 1132 END 1133 CheckScriptSuccess(lines) 1134 1135 lines =<< trim END 1136 vim9script 1137 def g:TestFunc(f: func) 1138 enddef 1139 legacy call g:TestFunc({-> 0}) 1140 delfunc g:TestFunc 1141 1142 def g:TestFunc(f: func(number)) 1143 enddef 1144 legacy call g:TestFunc({nr -> 0}) 1145 delfunc g:TestFunc 1146 END 1147 CheckScriptSuccess(lines) 1148enddef 1149 1150def Test_lambda_in_reduce_line_break() 1151 # this was using freed memory 1152 var lines =<< trim END 1153 vim9script 1154 const result: dict<number> = 1155 ['Bob', 'Sam', 'Cat', 'Bob', 'Cat', 'Cat'] 1156 ->reduce((acc, val) => { 1157 if has_key(acc, val) 1158 acc[val] += 1 1159 return acc 1160 else 1161 acc[val] = 1 1162 return acc 1163 endif 1164 }, {}) 1165 assert_equal({Bob: 2, Sam: 1, Cat: 3}, result) 1166 END 1167 CheckScriptSuccess(lines) 1168enddef 1169 1170" Default arg and varargs 1171def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 1172 var res = one .. ',' .. two 1173 for s in rest 1174 res ..= ',' .. s 1175 endfor 1176 return res 1177enddef 1178 1179def Test_call_def_varargs() 1180 assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs') 1181 MyDefVarargs('one')->assert_equal('one,foo') 1182 MyDefVarargs('one', 'two')->assert_equal('one,two') 1183 MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three') 1184 CheckDefFailure(['MyDefVarargs("one", 22)'], 1185 'E1013: Argument 2: type mismatch, expected string but got number') 1186 CheckDefFailure(['MyDefVarargs("one", "two", 123)'], 1187 'E1013: Argument 3: type mismatch, expected string but got number') 1188 1189 var lines =<< trim END 1190 vim9script 1191 def Func(...l: list<string>) 1192 echo l 1193 enddef 1194 Func('a', 'b', 'c') 1195 END 1196 CheckScriptSuccess(lines) 1197 1198 lines =<< trim END 1199 vim9script 1200 def Func(...l: list<string>) 1201 echo l 1202 enddef 1203 Func() 1204 END 1205 CheckScriptSuccess(lines) 1206 1207 lines =<< trim END 1208 vim9script 1209 def Func(...l: list<any>) 1210 echo l 1211 enddef 1212 Func(0) 1213 END 1214 CheckScriptSuccess(lines) 1215 1216 lines =<< trim END 1217 vim9script 1218 def Func(...l: any) 1219 echo l 1220 enddef 1221 Func(0) 1222 END 1223 CheckScriptFailure(lines, 'E1180:', 2) 1224 1225 lines =<< trim END 1226 vim9script 1227 def Func(..._l: list<string>) 1228 echo _l 1229 enddef 1230 Func('a', 'b', 'c') 1231 END 1232 CheckScriptSuccess(lines) 1233 1234 lines =<< trim END 1235 vim9script 1236 def Func(...l: list<string>) 1237 echo l 1238 enddef 1239 Func(1, 2, 3) 1240 END 1241 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch') 1242 1243 lines =<< trim END 1244 vim9script 1245 def Func(...l: list<string>) 1246 echo l 1247 enddef 1248 Func('a', 9) 1249 END 1250 CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch') 1251 1252 lines =<< trim END 1253 vim9script 1254 def Func(...l: list<string>) 1255 echo l 1256 enddef 1257 Func(1, 'a') 1258 END 1259 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch') 1260 1261 lines =<< trim END 1262 vim9script 1263 def Func( # some comment 1264 ...l = [] 1265 ) 1266 echo l 1267 enddef 1268 END 1269 CheckScriptFailure(lines, 'E1160:') 1270 1271 lines =<< trim END 1272 vim9script 1273 def DoIt() 1274 g:Later('') 1275 enddef 1276 defcompile 1277 def g:Later(...l: list<number>) 1278 enddef 1279 DoIt() 1280 END 1281 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got string') 1282enddef 1283 1284let s:value = '' 1285 1286def FuncOneDefArg(opt = 'text') 1287 s:value = opt 1288enddef 1289 1290def FuncTwoDefArg(nr = 123, opt = 'text'): string 1291 return nr .. opt 1292enddef 1293 1294def FuncVarargs(...arg: list<string>): string 1295 return join(arg, ',') 1296enddef 1297 1298def Test_func_type_varargs() 1299 var RefDefArg: func(?string) 1300 RefDefArg = FuncOneDefArg 1301 RefDefArg() 1302 s:value->assert_equal('text') 1303 RefDefArg('some') 1304 s:value->assert_equal('some') 1305 1306 var RefDef2Arg: func(?number, ?string): string 1307 RefDef2Arg = FuncTwoDefArg 1308 RefDef2Arg()->assert_equal('123text') 1309 RefDef2Arg(99)->assert_equal('99text') 1310 RefDef2Arg(77, 'some')->assert_equal('77some') 1311 1312 CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:') 1313 CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:') 1314 1315 var RefVarargs: func(...list<string>): string 1316 RefVarargs = FuncVarargs 1317 RefVarargs()->assert_equal('') 1318 RefVarargs('one')->assert_equal('one') 1319 RefVarargs('one', 'two')->assert_equal('one,two') 1320 1321 CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:') 1322 CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:') 1323enddef 1324 1325" Only varargs 1326def MyVarargsOnly(...args: list<string>): string 1327 return join(args, ',') 1328enddef 1329 1330def Test_call_varargs_only() 1331 MyVarargsOnly()->assert_equal('') 1332 MyVarargsOnly('one')->assert_equal('one') 1333 MyVarargsOnly('one', 'two')->assert_equal('one,two') 1334 CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number') 1335 CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number') 1336enddef 1337 1338def Test_using_var_as_arg() 1339 writefile(['def Func(x: number)', 'var x = 234', 'enddef', 'defcompile'], 'Xdef') 1340 assert_fails('so Xdef', 'E1006:', '', 1, 'Func') 1341 delete('Xdef') 1342enddef 1343 1344def DictArg(arg: dict<string>) 1345 arg['key'] = 'value' 1346enddef 1347 1348def ListArg(arg: list<string>) 1349 arg[0] = 'value' 1350enddef 1351 1352def Test_assign_to_argument() 1353 # works for dict and list 1354 var d: dict<string> = {} 1355 DictArg(d) 1356 d['key']->assert_equal('value') 1357 var l: list<string> = [] 1358 ListArg(l) 1359 l[0]->assert_equal('value') 1360 1361 CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:') 1362 delfunc! g:Func 1363enddef 1364 1365" These argument names are reserved in legacy functions. 1366def WithReservedNames(firstline: string, lastline: string): string 1367 return firstline .. lastline 1368enddef 1369 1370def Test_argument_names() 1371 assert_equal('OK', WithReservedNames('O', 'K')) 1372enddef 1373 1374def Test_call_func_defined_later() 1375 g:DefinedLater('one')->assert_equal('one') 1376 assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later') 1377enddef 1378 1379func DefinedLater(arg) 1380 return a:arg 1381endfunc 1382 1383def Test_call_funcref() 1384 g:SomeFunc('abc')->assert_equal(3) 1385 assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call 1386 assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref') 1387 1388 var lines =<< trim END 1389 vim9script 1390 def RetNumber(): number 1391 return 123 1392 enddef 1393 var Funcref: func: number = function('RetNumber') 1394 Funcref()->assert_equal(123) 1395 END 1396 CheckScriptSuccess(lines) 1397 1398 lines =<< trim END 1399 vim9script 1400 def RetNumber(): number 1401 return 123 1402 enddef 1403 def Bar(F: func: number): number 1404 return F() 1405 enddef 1406 var Funcref = function('RetNumber') 1407 Bar(Funcref)->assert_equal(123) 1408 END 1409 CheckScriptSuccess(lines) 1410 1411 lines =<< trim END 1412 vim9script 1413 def UseNumber(nr: number) 1414 echo nr 1415 enddef 1416 var Funcref: func(number) = function('UseNumber') 1417 Funcref(123) 1418 END 1419 CheckScriptSuccess(lines) 1420 1421 lines =<< trim END 1422 vim9script 1423 def UseNumber(nr: number) 1424 echo nr 1425 enddef 1426 var Funcref: func(string) = function('UseNumber') 1427 END 1428 CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)') 1429 1430 lines =<< trim END 1431 vim9script 1432 def EchoNr(nr = 34) 1433 g:echo = nr 1434 enddef 1435 var Funcref: func(?number) = function('EchoNr') 1436 Funcref() 1437 g:echo->assert_equal(34) 1438 Funcref(123) 1439 g:echo->assert_equal(123) 1440 END 1441 CheckScriptSuccess(lines) 1442 1443 lines =<< trim END 1444 vim9script 1445 def EchoList(...l: list<number>) 1446 g:echo = l 1447 enddef 1448 var Funcref: func(...list<number>) = function('EchoList') 1449 Funcref() 1450 g:echo->assert_equal([]) 1451 Funcref(1, 2, 3) 1452 g:echo->assert_equal([1, 2, 3]) 1453 END 1454 CheckScriptSuccess(lines) 1455 1456 lines =<< trim END 1457 vim9script 1458 def OptAndVar(nr: number, opt = 12, ...l: list<number>): number 1459 g:optarg = opt 1460 g:listarg = l 1461 return nr 1462 enddef 1463 var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar') 1464 Funcref(10)->assert_equal(10) 1465 g:optarg->assert_equal(12) 1466 g:listarg->assert_equal([]) 1467 1468 Funcref(11, 22)->assert_equal(11) 1469 g:optarg->assert_equal(22) 1470 g:listarg->assert_equal([]) 1471 1472 Funcref(17, 18, 1, 2, 3)->assert_equal(17) 1473 g:optarg->assert_equal(18) 1474 g:listarg->assert_equal([1, 2, 3]) 1475 END 1476 CheckScriptSuccess(lines) 1477enddef 1478 1479let SomeFunc = function('len') 1480let NotAFunc = 'text' 1481 1482def CombineFuncrefTypes() 1483 # same arguments, different return type 1484 var Ref1: func(bool): string 1485 var Ref2: func(bool): number 1486 var Ref3: func(bool): any 1487 Ref3 = g:cond ? Ref1 : Ref2 1488 1489 # different number of arguments 1490 var Refa1: func(bool): number 1491 var Refa2: func(bool, number): number 1492 var Refa3: func: number 1493 Refa3 = g:cond ? Refa1 : Refa2 1494 1495 # different argument types 1496 var Refb1: func(bool, string): number 1497 var Refb2: func(string, number): number 1498 var Refb3: func(any, any): number 1499 Refb3 = g:cond ? Refb1 : Refb2 1500enddef 1501 1502def FuncWithForwardCall() 1503 return g:DefinedEvenLater("yes") 1504enddef 1505 1506def DefinedEvenLater(arg: string): string 1507 return arg 1508enddef 1509 1510def Test_error_in_nested_function() 1511 # Error in called function requires unwinding the call stack. 1512 assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall') 1513enddef 1514 1515def Test_return_type_wrong() 1516 CheckScriptFailure([ 1517 'def Func(): number', 1518 'return "a"', 1519 'enddef', 1520 'defcompile'], 'expected number but got string') 1521 delfunc! g:Func 1522 CheckScriptFailure([ 1523 'def Func(): string', 1524 'return 1', 1525 'enddef', 1526 'defcompile'], 'expected string but got number') 1527 delfunc! g:Func 1528 CheckScriptFailure([ 1529 'def Func(): void', 1530 'return "a"', 1531 'enddef', 1532 'defcompile'], 1533 'E1096: Returning a value in a function without a return type') 1534 delfunc! g:Func 1535 CheckScriptFailure([ 1536 'def Func()', 1537 'return "a"', 1538 'enddef', 1539 'defcompile'], 1540 'E1096: Returning a value in a function without a return type') 1541 delfunc! g:Func 1542 1543 CheckScriptFailure([ 1544 'def Func(): number', 1545 'return', 1546 'enddef', 1547 'defcompile'], 'E1003:') 1548 delfunc! g:Func 1549 1550 CheckScriptFailure([ 1551 'def Func():number', 1552 'return 123', 1553 'enddef', 1554 'defcompile'], 'E1069:') 1555 delfunc! g:Func 1556 1557 CheckScriptFailure([ 1558 'def Func() :number', 1559 'return 123', 1560 'enddef', 1561 'defcompile'], 'E1059:') 1562 delfunc! g:Func 1563 1564 CheckScriptFailure([ 1565 'def Func() : number', 1566 'return 123', 1567 'enddef', 1568 'defcompile'], 'E1059:') 1569 delfunc! g:Func 1570 1571 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 1572 delfunc! g:Func 1573 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 1574 delfunc! g:Func 1575 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 1576 delfunc! g:Func 1577 1578 CheckScriptFailure([ 1579 'vim9script', 1580 'def FuncB()', 1581 ' return 123', 1582 'enddef', 1583 'def FuncA()', 1584 ' FuncB()', 1585 'enddef', 1586 'defcompile'], 'E1096:') 1587enddef 1588 1589def Test_arg_type_wrong() 1590 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 1591 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 1592 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 1593 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 1594 CheckScriptFailure(['def Func6(...x:list<number>)', 'echo "a"', 'enddef'], 'E1069:') 1595 CheckScriptFailure(['def Func7(...x: int)', 'echo "a"', 'enddef'], 'E1010:') 1596enddef 1597 1598def Test_white_space_before_comma() 1599 var lines =<< trim END 1600 vim9script 1601 def Func(a: number , b: number) 1602 enddef 1603 END 1604 CheckScriptFailure(lines, 'E1068:') 1605 call assert_fails('vim9cmd echo stridx("a" .. "b" , "a")', 'E1068:') 1606enddef 1607 1608def Test_white_space_after_comma() 1609 var lines =<< trim END 1610 vim9script 1611 def Func(a: number,b: number) 1612 enddef 1613 END 1614 CheckScriptFailure(lines, 'E1069:') 1615 1616 # OK in legacy function 1617 lines =<< trim END 1618 vim9script 1619 func Func(a,b) 1620 endfunc 1621 END 1622 CheckScriptSuccess(lines) 1623enddef 1624 1625def Test_vim9script_call() 1626 var lines =<< trim END 1627 vim9script 1628 var name = '' 1629 def MyFunc(arg: string) 1630 name = arg 1631 enddef 1632 MyFunc('foobar') 1633 name->assert_equal('foobar') 1634 1635 var str = 'barfoo' 1636 str->MyFunc() 1637 name->assert_equal('barfoo') 1638 1639 g:value = 'value' 1640 g:value->MyFunc() 1641 name->assert_equal('value') 1642 1643 var listvar = [] 1644 def ListFunc(arg: list<number>) 1645 listvar = arg 1646 enddef 1647 [1, 2, 3]->ListFunc() 1648 listvar->assert_equal([1, 2, 3]) 1649 1650 var dictvar = {} 1651 def DictFunc(arg: dict<number>) 1652 dictvar = arg 1653 enddef 1654 {a: 1, b: 2}->DictFunc() 1655 dictvar->assert_equal({a: 1, b: 2}) 1656 def CompiledDict() 1657 {a: 3, b: 4}->DictFunc() 1658 enddef 1659 CompiledDict() 1660 dictvar->assert_equal({a: 3, b: 4}) 1661 1662 {a: 3, b: 4}->DictFunc() 1663 dictvar->assert_equal({a: 3, b: 4}) 1664 1665 ('text')->MyFunc() 1666 name->assert_equal('text') 1667 ("some")->MyFunc() 1668 name->assert_equal('some') 1669 1670 # line starting with single quote is not a mark 1671 # line starting with double quote can be a method call 1672 'asdfasdf'->MyFunc() 1673 name->assert_equal('asdfasdf') 1674 "xyz"->MyFunc() 1675 name->assert_equal('xyz') 1676 1677 def UseString() 1678 'xyork'->MyFunc() 1679 enddef 1680 UseString() 1681 name->assert_equal('xyork') 1682 1683 def UseString2() 1684 "knife"->MyFunc() 1685 enddef 1686 UseString2() 1687 name->assert_equal('knife') 1688 1689 # prepending a colon makes it a mark 1690 new 1691 setline(1, ['aaa', 'bbb', 'ccc']) 1692 normal! 3Gmt1G 1693 :'t 1694 getcurpos()[1]->assert_equal(3) 1695 bwipe! 1696 1697 MyFunc( 1698 'continued' 1699 ) 1700 assert_equal('continued', 1701 name 1702 ) 1703 1704 call MyFunc( 1705 'more' 1706 .. 1707 'lines' 1708 ) 1709 assert_equal( 1710 'morelines', 1711 name) 1712 END 1713 writefile(lines, 'Xcall.vim') 1714 source Xcall.vim 1715 delete('Xcall.vim') 1716enddef 1717 1718def Test_vim9script_call_fail_decl() 1719 var lines =<< trim END 1720 vim9script 1721 var name = '' 1722 def MyFunc(arg: string) 1723 var name = 123 1724 enddef 1725 defcompile 1726 END 1727 CheckScriptFailure(lines, 'E1054:') 1728enddef 1729 1730def Test_vim9script_call_fail_type() 1731 var lines =<< trim END 1732 vim9script 1733 def MyFunc(arg: string) 1734 echo arg 1735 enddef 1736 MyFunc(1234) 1737 END 1738 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number') 1739enddef 1740 1741def Test_vim9script_call_fail_const() 1742 var lines =<< trim END 1743 vim9script 1744 const var = '' 1745 def MyFunc(arg: string) 1746 var = 'asdf' 1747 enddef 1748 defcompile 1749 END 1750 writefile(lines, 'Xcall_const.vim') 1751 assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') 1752 delete('Xcall_const.vim') 1753 1754 lines =<< trim END 1755 const g:Aconst = 77 1756 def Change() 1757 # comment 1758 g:Aconst = 99 1759 enddef 1760 call Change() 1761 unlet g:Aconst 1762 END 1763 CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) 1764enddef 1765 1766" Test that inside :function a Python function can be defined, :def is not 1767" recognized. 1768func Test_function_python() 1769 CheckFeature python3 1770 let py = 'python3' 1771 execute py "<< EOF" 1772def do_something(): 1773 return 1 1774EOF 1775endfunc 1776 1777def Test_delfunc() 1778 var lines =<< trim END 1779 vim9script 1780 def g:GoneSoon() 1781 echo 'hello' 1782 enddef 1783 1784 def CallGoneSoon() 1785 GoneSoon() 1786 enddef 1787 defcompile 1788 1789 delfunc g:GoneSoon 1790 CallGoneSoon() 1791 END 1792 writefile(lines, 'XToDelFunc') 1793 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1794 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1795 1796 delete('XToDelFunc') 1797enddef 1798 1799def Test_redef_failure() 1800 writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 1801 so Xdef 1802 writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 1803 so Xdef 1804 writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 1805 assert_fails('so Xdef', 'E1027:', '', 1, 'Func0') 1806 writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 1807 so Xdef 1808 delete('Xdef') 1809 1810 assert_fails('g:Func0()', 'E1091:') 1811 g:Func1()->assert_equal('Func1') 1812 g:Func2()->assert_equal('Func2') 1813 1814 delfunc! Func0 1815 delfunc! Func1 1816 delfunc! Func2 1817enddef 1818 1819def Test_vim9script_func() 1820 var lines =<< trim END 1821 vim9script 1822 func Func(arg) 1823 echo a:arg 1824 endfunc 1825 Func('text') 1826 END 1827 writefile(lines, 'XVim9Func') 1828 so XVim9Func 1829 1830 delete('XVim9Func') 1831enddef 1832 1833let s:funcResult = 0 1834 1835def FuncNoArgNoRet() 1836 s:funcResult = 11 1837enddef 1838 1839def FuncNoArgRetNumber(): number 1840 s:funcResult = 22 1841 return 1234 1842enddef 1843 1844def FuncNoArgRetString(): string 1845 s:funcResult = 45 1846 return 'text' 1847enddef 1848 1849def FuncOneArgNoRet(arg: number) 1850 s:funcResult = arg 1851enddef 1852 1853def FuncOneArgRetNumber(arg: number): number 1854 s:funcResult = arg 1855 return arg 1856enddef 1857 1858def FuncTwoArgNoRet(one: bool, two: number) 1859 s:funcResult = two 1860enddef 1861 1862def FuncOneArgRetString(arg: string): string 1863 return arg 1864enddef 1865 1866def FuncOneArgRetAny(arg: any): any 1867 return arg 1868enddef 1869 1870def Test_func_type() 1871 var Ref1: func() 1872 s:funcResult = 0 1873 Ref1 = FuncNoArgNoRet 1874 Ref1() 1875 s:funcResult->assert_equal(11) 1876 1877 var Ref2: func 1878 s:funcResult = 0 1879 Ref2 = FuncNoArgNoRet 1880 Ref2() 1881 s:funcResult->assert_equal(11) 1882 1883 s:funcResult = 0 1884 Ref2 = FuncOneArgNoRet 1885 Ref2(12) 1886 s:funcResult->assert_equal(12) 1887 1888 s:funcResult = 0 1889 Ref2 = FuncNoArgRetNumber 1890 Ref2()->assert_equal(1234) 1891 s:funcResult->assert_equal(22) 1892 1893 s:funcResult = 0 1894 Ref2 = FuncOneArgRetNumber 1895 Ref2(13)->assert_equal(13) 1896 s:funcResult->assert_equal(13) 1897enddef 1898 1899def Test_repeat_return_type() 1900 var res = 0 1901 for n in repeat([1], 3) 1902 res += n 1903 endfor 1904 res->assert_equal(3) 1905 1906 res = 0 1907 for n in add([1, 2], 3) 1908 res += n 1909 endfor 1910 res->assert_equal(6) 1911enddef 1912 1913def Test_argv_return_type() 1914 next fileone filetwo 1915 var res = '' 1916 for name in argv() 1917 res ..= name 1918 endfor 1919 res->assert_equal('fileonefiletwo') 1920enddef 1921 1922def Test_func_type_part() 1923 var RefVoid: func: void 1924 RefVoid = FuncNoArgNoRet 1925 RefVoid = FuncOneArgNoRet 1926 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number') 1927 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string') 1928 1929 var RefAny: func(): any 1930 RefAny = FuncNoArgRetNumber 1931 RefAny = FuncNoArgRetString 1932 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()') 1933 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)') 1934 1935 var RefAnyNoArgs: func: any = RefAny 1936 1937 var RefNr: func: number 1938 RefNr = FuncNoArgRetNumber 1939 RefNr = FuncOneArgRetNumber 1940 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()') 1941 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string') 1942 1943 var RefStr: func: string 1944 RefStr = FuncNoArgRetString 1945 RefStr = FuncOneArgRetString 1946 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()') 1947 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number') 1948enddef 1949 1950def Test_func_type_fails() 1951 CheckDefFailure(['var ref1: func()'], 'E704:') 1952 1953 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number') 1954 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)') 1955 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number') 1956 CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)') 1957 CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)') 1958 CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)') 1959 1960 CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:') 1961 CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:') 1962 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:') 1963 CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:') 1964enddef 1965 1966def Test_func_return_type() 1967 var nr: number 1968 nr = FuncNoArgRetNumber() 1969 nr->assert_equal(1234) 1970 1971 nr = FuncOneArgRetAny(122) 1972 nr->assert_equal(122) 1973 1974 var str: string 1975 str = FuncOneArgRetAny('yes') 1976 str->assert_equal('yes') 1977 1978 CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number') 1979enddef 1980 1981def Test_func_common_type() 1982 def FuncOne(n: number): number 1983 return n 1984 enddef 1985 def FuncTwo(s: string): number 1986 return len(s) 1987 enddef 1988 def FuncThree(n: number, s: string): number 1989 return n + len(s) 1990 enddef 1991 var list = [FuncOne, FuncTwo, FuncThree] 1992 assert_equal(8, list[0](8)) 1993 assert_equal(4, list[1]('word')) 1994 assert_equal(7, list[2](3, 'word')) 1995enddef 1996 1997def MultiLine( 1998 arg1: string, 1999 arg2 = 1234, 2000 ...rest: list<string> 2001 ): string 2002 return arg1 .. arg2 .. join(rest, '-') 2003enddef 2004 2005def MultiLineComment( 2006 arg1: string, # comment 2007 arg2 = 1234, # comment 2008 ...rest: list<string> # comment 2009 ): string # comment 2010 return arg1 .. arg2 .. join(rest, '-') 2011enddef 2012 2013def Test_multiline() 2014 MultiLine('text')->assert_equal('text1234') 2015 MultiLine('text', 777)->assert_equal('text777') 2016 MultiLine('text', 777, 'one')->assert_equal('text777one') 2017 MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 2018enddef 2019 2020func Test_multiline_not_vim9() 2021 call MultiLine('text')->assert_equal('text1234') 2022 call MultiLine('text', 777)->assert_equal('text777') 2023 call MultiLine('text', 777, 'one')->assert_equal('text777one') 2024 call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 2025endfunc 2026 2027 2028" When using CheckScriptFailure() for the below test, E1010 is generated instead 2029" of E1056. 2030func Test_E1056_1059() 2031 let caught_1056 = 0 2032 try 2033 def F(): 2034 return 1 2035 enddef 2036 catch /E1056:/ 2037 let caught_1056 = 1 2038 endtry 2039 eval caught_1056->assert_equal(1) 2040 2041 let caught_1059 = 0 2042 try 2043 def F5(items : list) 2044 echo 'a' 2045 enddef 2046 catch /E1059:/ 2047 let caught_1059 = 1 2048 endtry 2049 eval caught_1059->assert_equal(1) 2050endfunc 2051 2052func DelMe() 2053 echo 'DelMe' 2054endfunc 2055 2056def Test_error_reporting() 2057 # comment lines at the start of the function 2058 var lines =<< trim END 2059 " comment 2060 def Func() 2061 # comment 2062 # comment 2063 invalid 2064 enddef 2065 defcompile 2066 END 2067 writefile(lines, 'Xdef') 2068 try 2069 source Xdef 2070 assert_report('should have failed') 2071 catch /E476:/ 2072 v:exception->assert_match('Invalid command: invalid') 2073 v:throwpoint->assert_match(', line 3$') 2074 endtry 2075 delfunc! g:Func 2076 2077 # comment lines after the start of the function 2078 lines =<< trim END 2079 " comment 2080 def Func() 2081 var x = 1234 2082 # comment 2083 # comment 2084 invalid 2085 enddef 2086 defcompile 2087 END 2088 writefile(lines, 'Xdef') 2089 try 2090 source Xdef 2091 assert_report('should have failed') 2092 catch /E476:/ 2093 v:exception->assert_match('Invalid command: invalid') 2094 v:throwpoint->assert_match(', line 4$') 2095 endtry 2096 delfunc! g:Func 2097 2098 lines =<< trim END 2099 vim9script 2100 def Func() 2101 var db = {foo: 1, bar: 2} 2102 # comment 2103 var x = db.asdf 2104 enddef 2105 defcompile 2106 Func() 2107 END 2108 writefile(lines, 'Xdef') 2109 try 2110 source Xdef 2111 assert_report('should have failed') 2112 catch /E716:/ 2113 v:throwpoint->assert_match('_Func, line 3$') 2114 endtry 2115 delfunc! g:Func 2116 2117 delete('Xdef') 2118enddef 2119 2120def Test_deleted_function() 2121 CheckDefExecFailure([ 2122 'var RefMe: func = function("g:DelMe")', 2123 'delfunc g:DelMe', 2124 'echo RefMe()'], 'E117:') 2125enddef 2126 2127def Test_unknown_function() 2128 CheckDefExecFailure([ 2129 'var Ref: func = function("NotExist")', 2130 'delfunc g:NotExist'], 'E700:') 2131enddef 2132 2133def RefFunc(Ref: func(any): any): string 2134 return Ref('more') 2135enddef 2136 2137def Test_closure_simple() 2138 var local = 'some ' 2139 RefFunc((s) => local .. s)->assert_equal('some more') 2140enddef 2141 2142def MakeRef() 2143 var local = 'some ' 2144 g:Ref = (s) => local .. s 2145enddef 2146 2147def Test_closure_ref_after_return() 2148 MakeRef() 2149 g:Ref('thing')->assert_equal('some thing') 2150 unlet g:Ref 2151enddef 2152 2153def MakeTwoRefs() 2154 var local = ['some'] 2155 g:Extend = (s) => local->add(s) 2156 g:Read = () => local 2157enddef 2158 2159def Test_closure_two_refs() 2160 MakeTwoRefs() 2161 join(g:Read(), ' ')->assert_equal('some') 2162 g:Extend('more') 2163 join(g:Read(), ' ')->assert_equal('some more') 2164 g:Extend('even') 2165 join(g:Read(), ' ')->assert_equal('some more even') 2166 2167 unlet g:Extend 2168 unlet g:Read 2169enddef 2170 2171def ReadRef(Ref: func(): list<string>): string 2172 return join(Ref(), ' ') 2173enddef 2174 2175def ExtendRef(Ref: func(string): list<string>, add: string) 2176 Ref(add) 2177enddef 2178 2179def Test_closure_two_indirect_refs() 2180 MakeTwoRefs() 2181 ReadRef(g:Read)->assert_equal('some') 2182 ExtendRef(g:Extend, 'more') 2183 ReadRef(g:Read)->assert_equal('some more') 2184 ExtendRef(g:Extend, 'even') 2185 ReadRef(g:Read)->assert_equal('some more even') 2186 2187 unlet g:Extend 2188 unlet g:Read 2189enddef 2190 2191def MakeArgRefs(theArg: string) 2192 var local = 'loc_val' 2193 g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s 2194enddef 2195 2196def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 2197 var local = 'the_loc' 2198 g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest) 2199enddef 2200 2201def Test_closure_using_argument() 2202 MakeArgRefs('arg_val') 2203 g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val') 2204 2205 MakeArgRefsVarargs('arg_val', 'one', 'two') 2206 g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two') 2207 2208 unlet g:UseArg 2209 unlet g:UseVararg 2210 2211 var lines =<< trim END 2212 vim9script 2213 def Test(Fun: func(number): number): list<number> 2214 return map([1, 2, 3], (_, i) => Fun(i)) 2215 enddef 2216 def Inc(nr: number): number 2217 return nr + 2 2218 enddef 2219 assert_equal([3, 4, 5], Test(Inc)) 2220 END 2221 CheckScriptSuccess(lines) 2222enddef 2223 2224def MakeGetAndAppendRefs() 2225 var local = 'a' 2226 2227 def Append(arg: string) 2228 local ..= arg 2229 enddef 2230 g:Append = Append 2231 2232 def Get(): string 2233 return local 2234 enddef 2235 g:Get = Get 2236enddef 2237 2238def Test_closure_append_get() 2239 MakeGetAndAppendRefs() 2240 g:Get()->assert_equal('a') 2241 g:Append('-b') 2242 g:Get()->assert_equal('a-b') 2243 g:Append('-c') 2244 g:Get()->assert_equal('a-b-c') 2245 2246 unlet g:Append 2247 unlet g:Get 2248enddef 2249 2250def Test_nested_closure() 2251 var local = 'text' 2252 def Closure(arg: string): string 2253 return local .. arg 2254 enddef 2255 Closure('!!!')->assert_equal('text!!!') 2256enddef 2257 2258func GetResult(Ref) 2259 return a:Ref('some') 2260endfunc 2261 2262def Test_call_closure_not_compiled() 2263 var text = 'text' 2264 g:Ref = (s) => s .. text 2265 GetResult(g:Ref)->assert_equal('sometext') 2266enddef 2267 2268def Test_double_closure_fails() 2269 var lines =<< trim END 2270 vim9script 2271 def Func() 2272 var name = 0 2273 for i in range(2) 2274 timer_start(0, () => name) 2275 endfor 2276 enddef 2277 Func() 2278 END 2279 CheckScriptSuccess(lines) 2280enddef 2281 2282def Test_nested_closure_used() 2283 var lines =<< trim END 2284 vim9script 2285 def Func() 2286 var x = 'hello' 2287 var Closure = () => x 2288 g:Myclosure = () => Closure() 2289 enddef 2290 Func() 2291 assert_equal('hello', g:Myclosure()) 2292 END 2293 CheckScriptSuccess(lines) 2294enddef 2295 2296def Test_nested_closure_fails() 2297 var lines =<< trim END 2298 vim9script 2299 def FuncA() 2300 FuncB(0) 2301 enddef 2302 def FuncB(n: number): list<string> 2303 return map([0], (_, v) => n) 2304 enddef 2305 FuncA() 2306 END 2307 CheckScriptFailure(lines, 'E1012:') 2308enddef 2309 2310def Test_global_closure() 2311 var lines =<< trim END 2312 vim9script 2313 def ReverseEveryNLines(n: number, line1: number, line2: number) 2314 var mods = 'sil keepj keepp lockm ' 2315 var range = ':' .. line1 .. ',' .. line2 2316 def g:Offset(): number 2317 var offset = (line('.') - line1 + 1) % n 2318 return offset != 0 ? offset : n 2319 enddef 2320 exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()' 2321 enddef 2322 2323 new 2324 repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1) 2325 ReverseEveryNLines(3, 1, 9) 2326 END 2327 CheckScriptSuccess(lines) 2328 var expected = repeat(['ccc', 'bbb', 'aaa'], 3) 2329 assert_equal(expected, getline(1, 9)) 2330 bwipe! 2331enddef 2332 2333def Test_global_closure_called_directly() 2334 var lines =<< trim END 2335 vim9script 2336 def Outer() 2337 var x = 1 2338 def g:Inner() 2339 var y = x 2340 x += 1 2341 assert_equal(1, y) 2342 enddef 2343 g:Inner() 2344 assert_equal(2, x) 2345 enddef 2346 Outer() 2347 END 2348 CheckScriptSuccess(lines) 2349 delfunc g:Inner 2350enddef 2351 2352def Test_failure_in_called_function() 2353 # this was using the frame index as the return value 2354 var lines =<< trim END 2355 vim9script 2356 au TerminalWinOpen * eval [][0] 2357 def PopupTerm(a: any) 2358 # make sure typvals on stack are string 2359 ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join() 2360 FireEvent() 2361 enddef 2362 def FireEvent() 2363 do TerminalWinOpen 2364 enddef 2365 # use try/catch to make eval fail 2366 try 2367 call PopupTerm(0) 2368 catch 2369 endtry 2370 au! TerminalWinOpen 2371 END 2372 CheckScriptSuccess(lines) 2373enddef 2374 2375def Test_nested_lambda() 2376 var lines =<< trim END 2377 vim9script 2378 def Func() 2379 var x = 4 2380 var Lambda1 = () => 7 2381 var Lambda2 = () => [Lambda1(), x] 2382 var res = Lambda2() 2383 assert_equal([7, 4], res) 2384 enddef 2385 Func() 2386 END 2387 CheckScriptSuccess(lines) 2388enddef 2389 2390def Test_double_nested_lambda() 2391 var lines =<< trim END 2392 vim9script 2393 def F(head: string): func(string): func(string): string 2394 return (sep: string): func(string): string => ((tail: string): string => { 2395 return head .. sep .. tail 2396 }) 2397 enddef 2398 assert_equal('hello-there', F('hello')('-')('there')) 2399 END 2400 CheckScriptSuccess(lines) 2401enddef 2402 2403def Test_nested_inline_lambda() 2404 var lines =<< trim END 2405 vim9script 2406 def F(text: string): func(string): func(string): string 2407 return (arg: string): func(string): string => ((sep: string): string => { 2408 return sep .. arg .. text 2409 }) 2410 enddef 2411 assert_equal('--there++', F('++')('there')('--')) 2412 END 2413 CheckScriptSuccess(lines) 2414 2415 lines =<< trim END 2416 vim9script 2417 echo range(4)->mapnew((_, v) => { 2418 return range(v) ->mapnew((_, s) => { 2419 return string(s) 2420 }) 2421 }) 2422 END 2423 CheckScriptSuccess(lines) 2424 2425 lines =<< trim END 2426 vim9script 2427 2428 def s:func() 2429 range(10) 2430 ->mapnew((_, _) => ({ 2431 key: range(10)->mapnew((_, _) => { 2432 return ' ' 2433 }), 2434 })) 2435 enddef 2436 2437 defcomp 2438 END 2439 CheckScriptSuccess(lines) 2440enddef 2441 2442def Shadowed(): list<number> 2443 var FuncList: list<func: number> = [() => 42] 2444 return FuncList->mapnew((_, Shadowed) => Shadowed()) 2445enddef 2446 2447def Test_lambda_arg_shadows_func() 2448 assert_equal([42], Shadowed()) 2449enddef 2450 2451def Line_continuation_in_def(dir: string = ''): string 2452 var path: string = empty(dir) 2453 \ ? 'empty' 2454 \ : 'full' 2455 return path 2456enddef 2457 2458def Test_line_continuation_in_def() 2459 Line_continuation_in_def('.')->assert_equal('full') 2460enddef 2461 2462def Test_script_var_in_lambda() 2463 var lines =<< trim END 2464 vim9script 2465 var script = 'test' 2466 assert_equal(['test'], map(['one'], (_, _) => script)) 2467 END 2468 CheckScriptSuccess(lines) 2469enddef 2470 2471def Line_continuation_in_lambda(): list<string> 2472 var x = range(97, 100) 2473 ->mapnew((_, v) => nr2char(v) 2474 ->toupper()) 2475 ->reverse() 2476 return x 2477enddef 2478 2479def Test_line_continuation_in_lambda() 2480 Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A']) 2481 2482 var lines =<< trim END 2483 vim9script 2484 var res = [{n: 1, m: 2, s: 'xxx'}] 2485 ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s', 2486 v.n, 2487 v.m, 2488 substitute(v.s, '.*', 'yyy', '') 2489 )) 2490 assert_equal(['1:2:yyy'], res) 2491 END 2492 CheckScriptSuccess(lines) 2493enddef 2494 2495def Test_list_lambda() 2496 timer_start(1000, (_) => 0) 2497 var body = execute(timer_info()[0].callback 2498 ->string() 2499 ->substitute("('", ' ', '') 2500 ->substitute("')", '', '') 2501 ->substitute('function\zs', ' ', '')) 2502 assert_match('def <lambda>\d\+(_: any): number\n1 return 0\n enddef', body) 2503enddef 2504 2505def Test_lambda_block_variable() 2506 var lines =<< trim END 2507 vim9script 2508 var flist: list<func> 2509 for i in range(10) 2510 var inloop = i 2511 flist[i] = () => inloop 2512 endfor 2513 END 2514 CheckScriptSuccess(lines) 2515 2516 lines =<< trim END 2517 vim9script 2518 if true 2519 var outloop = 5 2520 var flist: list<func> 2521 for i in range(10) 2522 flist[i] = () => outloop 2523 endfor 2524 endif 2525 END 2526 CheckScriptSuccess(lines) 2527 2528 lines =<< trim END 2529 vim9script 2530 if true 2531 var outloop = 5 2532 endif 2533 var flist: list<func> 2534 for i in range(10) 2535 flist[i] = () => outloop 2536 endfor 2537 END 2538 CheckScriptFailure(lines, 'E1001: Variable not found: outloop', 1) 2539 2540 lines =<< trim END 2541 vim9script 2542 for i in range(10) 2543 var Ref = () => 0 2544 endfor 2545 assert_equal(0, ((i) => 0)(0)) 2546 END 2547 CheckScriptSuccess(lines) 2548enddef 2549 2550def Test_legacy_lambda() 2551 legacy echo {x -> 'hello ' .. x}('foo') 2552 2553 var lines =<< trim END 2554 echo {x -> 'hello ' .. x}('foo') 2555 END 2556 CheckDefAndScriptFailure(lines, 'E720:') 2557 2558 lines =<< trim END 2559 vim9script 2560 def Func() 2561 echo (() => 'no error')() 2562 enddef 2563 legacy call s:Func() 2564 END 2565 CheckScriptSuccess(lines) 2566enddef 2567 2568def Test_legacy() 2569 var lines =<< trim END 2570 vim9script 2571 func g:LegacyFunction() 2572 let g:legacyvar = 1 2573 endfunc 2574 def Testit() 2575 legacy call g:LegacyFunction() 2576 enddef 2577 Testit() 2578 assert_equal(1, g:legacyvar) 2579 unlet g:legacyvar 2580 delfunc g:LegacyFunction 2581 END 2582 CheckScriptSuccess(lines) 2583enddef 2584 2585def Test_legacy_errors() 2586 for cmd in ['if', 'elseif', 'else', 'endif', 2587 'for', 'endfor', 'continue', 'break', 2588 'while', 'endwhile', 2589 'try', 'catch', 'finally', 'endtry'] 2590 CheckDefFailure(['legacy ' .. cmd .. ' expr'], 'E1189:') 2591 endfor 2592enddef 2593 2594def Test_call_legacy_with_dict() 2595 var lines =<< trim END 2596 vim9script 2597 func Legacy() dict 2598 let g:result = self.value 2599 endfunc 2600 def TestDirect() 2601 var d = {value: 'yes', func: Legacy} 2602 d.func() 2603 enddef 2604 TestDirect() 2605 assert_equal('yes', g:result) 2606 unlet g:result 2607 2608 def TestIndirect() 2609 var d = {value: 'foo', func: Legacy} 2610 var Fi = d.func 2611 Fi() 2612 enddef 2613 TestIndirect() 2614 assert_equal('foo', g:result) 2615 unlet g:result 2616 2617 var d = {value: 'bar', func: Legacy} 2618 d.func() 2619 assert_equal('bar', g:result) 2620 unlet g:result 2621 END 2622 CheckScriptSuccess(lines) 2623enddef 2624 2625def DoFilterThis(a: string): list<string> 2626 # closure nested inside another closure using argument 2627 var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0) 2628 return ['x', 'y', 'a', 'x2', 'c']->Filter() 2629enddef 2630 2631def Test_nested_closure_using_argument() 2632 assert_equal(['x', 'x2'], DoFilterThis('x')) 2633enddef 2634 2635def Test_triple_nested_closure() 2636 var what = 'x' 2637 var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0 2638 var Filter = (l) => filter(l, (_, v) => Match(v, what)) 2639 assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter()) 2640enddef 2641 2642func Test_silent_echo() 2643 CheckScreendump 2644 2645 let lines =<< trim END 2646 vim9script 2647 def EchoNothing() 2648 silent echo '' 2649 enddef 2650 defcompile 2651 END 2652 call writefile(lines, 'XTest_silent_echo') 2653 2654 " Check that the balloon shows up after a mouse move 2655 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 2656 call term_sendkeys(buf, ":abc") 2657 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 2658 2659 " clean up 2660 call StopVimInTerminal(buf) 2661 call delete('XTest_silent_echo') 2662endfunc 2663 2664def SilentlyError() 2665 execute('silent! invalid') 2666 g:did_it = 'yes' 2667enddef 2668 2669func UserError() 2670 silent! invalid 2671endfunc 2672 2673def SilentlyUserError() 2674 UserError() 2675 g:did_it = 'yes' 2676enddef 2677 2678" This can't be a :def function, because the assert would not be reached. 2679func Test_ignore_silent_error() 2680 let g:did_it = 'no' 2681 call SilentlyError() 2682 call assert_equal('yes', g:did_it) 2683 2684 let g:did_it = 'no' 2685 call SilentlyUserError() 2686 call assert_equal('yes', g:did_it) 2687 2688 unlet g:did_it 2689endfunc 2690 2691def Test_ignore_silent_error_in_filter() 2692 var lines =<< trim END 2693 vim9script 2694 def Filter(winid: number, key: string): bool 2695 if key == 'o' 2696 silent! eval [][0] 2697 return true 2698 endif 2699 return popup_filter_menu(winid, key) 2700 enddef 2701 2702 popup_create('popup', {filter: Filter}) 2703 feedkeys("o\r", 'xnt') 2704 END 2705 CheckScriptSuccess(lines) 2706enddef 2707 2708def Fibonacci(n: number): number 2709 if n < 2 2710 return n 2711 else 2712 return Fibonacci(n - 1) + Fibonacci(n - 2) 2713 endif 2714enddef 2715 2716def Test_recursive_call() 2717 Fibonacci(20)->assert_equal(6765) 2718enddef 2719 2720def TreeWalk(dir: string): list<any> 2721 return readdir(dir)->mapnew((_, val) => 2722 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 2723 ? {[val]: TreeWalk(dir .. '/' .. val)} 2724 : val 2725 ) 2726enddef 2727 2728def Test_closure_in_map() 2729 mkdir('XclosureDir/tdir', 'p') 2730 writefile(['111'], 'XclosureDir/file1') 2731 writefile(['222'], 'XclosureDir/file2') 2732 writefile(['333'], 'XclosureDir/tdir/file3') 2733 2734 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) 2735 2736 delete('XclosureDir', 'rf') 2737enddef 2738 2739def Test_invalid_function_name() 2740 var lines =<< trim END 2741 vim9script 2742 def s: list<string> 2743 END 2744 CheckScriptFailure(lines, 'E129:') 2745 2746 lines =<< trim END 2747 vim9script 2748 def g: list<string> 2749 END 2750 CheckScriptFailure(lines, 'E129:') 2751 2752 lines =<< trim END 2753 vim9script 2754 def <SID>: list<string> 2755 END 2756 CheckScriptFailure(lines, 'E884:') 2757 2758 lines =<< trim END 2759 vim9script 2760 def F list<string> 2761 END 2762 CheckScriptFailure(lines, 'E488:') 2763enddef 2764 2765def Test_partial_call() 2766 var lines =<< trim END 2767 var Xsetlist: func 2768 Xsetlist = function('setloclist', [0]) 2769 Xsetlist([], ' ', {title: 'test'}) 2770 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2771 2772 Xsetlist = function('setloclist', [0, [], ' ']) 2773 Xsetlist({title: 'test'}) 2774 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2775 2776 Xsetlist = function('setqflist') 2777 Xsetlist([], ' ', {title: 'test'}) 2778 getqflist({title: 1})->assert_equal({title: 'test'}) 2779 2780 Xsetlist = function('setqflist', [[], ' ']) 2781 Xsetlist({title: 'test'}) 2782 getqflist({title: 1})->assert_equal({title: 'test'}) 2783 2784 var Len: func: number = function('len', ['word']) 2785 assert_equal(4, Len()) 2786 2787 var RepeatFunc = function('repeat', ['o']) 2788 assert_equal('ooooo', RepeatFunc(5)) 2789 END 2790 CheckDefAndScriptSuccess(lines) 2791 2792 lines =<< trim END 2793 vim9script 2794 def Foo(Parser: any) 2795 enddef 2796 var Expr: func(dict<any>): dict<any> 2797 const Call = Foo(Expr) 2798 END 2799 CheckScriptFailure(lines, 'E1235:') 2800enddef 2801 2802def Test_cmd_modifier() 2803 tab echo '0' 2804 CheckDefFailure(['5tab echo 3'], 'E16:') 2805enddef 2806 2807def Test_restore_modifiers() 2808 # check that when compiling a :def function command modifiers are not messed 2809 # up. 2810 var lines =<< trim END 2811 vim9script 2812 set eventignore= 2813 autocmd QuickFixCmdPost * copen 2814 def AutocmdsDisabled() 2815 eval 1 + 2 2816 enddef 2817 func Func() 2818 noautocmd call s:AutocmdsDisabled() 2819 let g:ei_after = &eventignore 2820 endfunc 2821 Func() 2822 END 2823 CheckScriptSuccess(lines) 2824 g:ei_after->assert_equal('') 2825enddef 2826 2827def StackTop() 2828 eval 1 + 2 2829 eval 2 + 3 2830 # call not on fourth line 2831 StackBot() 2832enddef 2833 2834def StackBot() 2835 # throw an error 2836 eval [][0] 2837enddef 2838 2839def Test_callstack_def() 2840 try 2841 StackTop() 2842 catch 2843 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2') 2844 endtry 2845enddef 2846 2847" Re-using spot for variable used in block 2848def Test_block_scoped_var() 2849 var lines =<< trim END 2850 vim9script 2851 def Func() 2852 var x = ['a', 'b', 'c'] 2853 if 1 2854 var y = 'x' 2855 map(x, (_, _) => y) 2856 endif 2857 var z = x 2858 assert_equal(['x', 'x', 'x'], z) 2859 enddef 2860 Func() 2861 END 2862 CheckScriptSuccess(lines) 2863enddef 2864 2865def Test_reset_did_emsg() 2866 var lines =<< trim END 2867 @s = 'blah' 2868 au BufWinLeave * # 2869 def Func() 2870 var winid = popup_create('popup', {}) 2871 exe '*s' 2872 popup_close(winid) 2873 enddef 2874 Func() 2875 END 2876 CheckScriptFailure(lines, 'E492:', 8) 2877 delfunc! g:Func 2878enddef 2879 2880def Test_did_emsg_reset() 2881 # executing an autocommand resets did_emsg, this should not result in a 2882 # builtin function considered failing 2883 var lines =<< trim END 2884 vim9script 2885 au BufWinLeave * # 2886 def Func() 2887 popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()}) 2888 eval [][0] 2889 enddef 2890 nno <F3> <cmd>call <sid>Func()<cr> 2891 feedkeys("\<F3>\e", 'xt') 2892 END 2893 writefile(lines, 'XemsgReset') 2894 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) 2895 delete('XemsgReset') 2896 nunmap <F3> 2897 au! BufWinLeave 2898enddef 2899 2900def Test_abort_with_silent_call() 2901 var lines =<< trim END 2902 vim9script 2903 g:result = 'none' 2904 def Func() 2905 g:result += 3 2906 g:result = 'yes' 2907 enddef 2908 # error is silenced, but function aborts on error 2909 silent! Func() 2910 assert_equal('none', g:result) 2911 unlet g:result 2912 END 2913 CheckScriptSuccess(lines) 2914enddef 2915 2916def Test_continues_with_silent_error() 2917 var lines =<< trim END 2918 vim9script 2919 g:result = 'none' 2920 def Func() 2921 silent! g:result += 3 2922 g:result = 'yes' 2923 enddef 2924 # error is silenced, function does not abort 2925 Func() 2926 assert_equal('yes', g:result) 2927 unlet g:result 2928 END 2929 CheckScriptSuccess(lines) 2930enddef 2931 2932def Test_abort_even_with_silent() 2933 var lines =<< trim END 2934 vim9script 2935 g:result = 'none' 2936 def Func() 2937 eval {-> ''}() .. '' .. {}['X'] 2938 g:result = 'yes' 2939 enddef 2940 silent! Func() 2941 assert_equal('none', g:result) 2942 unlet g:result 2943 END 2944 CheckScriptSuccess(lines) 2945enddef 2946 2947def Test_cmdmod_silent_restored() 2948 var lines =<< trim END 2949 vim9script 2950 def Func() 2951 g:result = 'none' 2952 silent! g:result += 3 2953 g:result = 'none' 2954 g:result += 3 2955 enddef 2956 Func() 2957 END 2958 # can't use CheckScriptFailure, it ignores the :silent! 2959 var fname = 'Xdefsilent' 2960 writefile(lines, fname) 2961 var caught = 'no' 2962 try 2963 exe 'source ' .. fname 2964 catch /E1030:/ 2965 caught = 'yes' 2966 assert_match('Func, line 4', v:throwpoint) 2967 endtry 2968 assert_equal('yes', caught) 2969 delete(fname) 2970enddef 2971 2972def Test_cmdmod_silent_nested() 2973 var lines =<< trim END 2974 vim9script 2975 var result = '' 2976 2977 def Error() 2978 result ..= 'Eb' 2979 eval [][0] 2980 result ..= 'Ea' 2981 enddef 2982 2983 def Crash() 2984 result ..= 'Cb' 2985 sil! Error() 2986 result ..= 'Ca' 2987 enddef 2988 2989 Crash() 2990 assert_equal('CbEbEaCa', result) 2991 END 2992 CheckScriptSuccess(lines) 2993enddef 2994 2995def Test_dict_member_with_silent() 2996 var lines =<< trim END 2997 vim9script 2998 g:result = 'none' 2999 var d: dict<any> 3000 def Func() 3001 try 3002 g:result = map([], (_, v) => ({}[v]))->join() .. d[''] 3003 catch 3004 endtry 3005 enddef 3006 silent! Func() 3007 assert_equal('0', g:result) 3008 unlet g:result 3009 END 3010 CheckScriptSuccess(lines) 3011enddef 3012 3013def Test_skip_cmds_with_silent() 3014 var lines =<< trim END 3015 vim9script 3016 3017 def Func(b: bool) 3018 Crash() 3019 enddef 3020 3021 def Crash() 3022 sil! :/not found/d _ 3023 sil! :/not found/put _ 3024 enddef 3025 3026 Func(true) 3027 END 3028 CheckScriptSuccess(lines) 3029enddef 3030 3031def Test_opfunc() 3032 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@ 3033 def g:Opfunc(_: any): string 3034 setline(1, 'ASDF') 3035 return '' 3036 enddef 3037 new 3038 setline(1, 'asdf') 3039 feedkeys("\<F3>$", 'x') 3040 assert_equal('ASDF', getline(1)) 3041 3042 bwipe! 3043 nunmap <F3> 3044enddef 3045 3046" this was crashing on exit 3047def Test_nested_lambda_in_closure() 3048 var lines =<< trim END 3049 vim9script 3050 command WriteDone writefile(['Done'], 'XnestedDone') 3051 def Outer() 3052 def g:Inner() 3053 echo map([1, 2, 3], {_, v -> v + 1}) 3054 enddef 3055 g:Inner() 3056 enddef 3057 defcompile 3058 # not reached 3059 END 3060 if !RunVim([], lines, '--clean -c WriteDone -c quit') 3061 return 3062 endif 3063 assert_equal(['Done'], readfile('XnestedDone')) 3064 delete('XnestedDone') 3065enddef 3066 3067def Test_check_func_arg_types() 3068 var lines =<< trim END 3069 vim9script 3070 def F1(x: string): string 3071 return x 3072 enddef 3073 3074 def F2(x: number): number 3075 return x + 1 3076 enddef 3077 3078 def G(g: func): dict<func> 3079 return {f: g} 3080 enddef 3081 3082 def H(d: dict<func>): string 3083 return d.f('a') 3084 enddef 3085 END 3086 3087 CheckScriptSuccess(lines + ['echo H(G(F1))']) 3088 CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:') 3089enddef 3090 3091def Test_list_any_type_checked() 3092 var lines =<< trim END 3093 vim9script 3094 def Foo() 3095 --decl-- 3096 Bar(l) 3097 enddef 3098 def Bar(ll: list<dict<any>>) 3099 enddef 3100 Foo() 3101 END 3102 lines[2] = 'var l: list<any>' 3103 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<any>', 2) 3104 3105 lines[2] = 'var l: list<any> = []' 3106 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<any>', 2) 3107 3108 lines[2] = 'var l: list<any> = [11]' 3109 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<number>', 2) 3110enddef 3111 3112def Test_compile_error() 3113 var lines =<< trim END 3114 def g:Broken() 3115 echo 'a' + {} 3116 enddef 3117 call g:Broken() 3118 END 3119 # First call: compilation error 3120 CheckScriptFailure(lines, 'E1051: Wrong argument type for +') 3121 3122 # Second call won't try compiling again 3123 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 3124 delfunc g:Broken 3125 3126 # No error when compiling with :silent! 3127 lines =<< trim END 3128 def g:Broken() 3129 echo 'a' + [] 3130 enddef 3131 silent! defcompile 3132 END 3133 CheckScriptSuccess(lines) 3134 3135 # Calling the function won't try compiling again 3136 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 3137 delfunc g:Broken 3138enddef 3139 3140def Test_ignored_argument() 3141 var lines =<< trim END 3142 vim9script 3143 def Ignore(_, _): string 3144 return 'yes' 3145 enddef 3146 assert_equal('yes', Ignore(1, 2)) 3147 3148 func Ok(_) 3149 return a:_ 3150 endfunc 3151 assert_equal('ok', Ok('ok')) 3152 3153 func Oktoo() 3154 let _ = 'too' 3155 return _ 3156 endfunc 3157 assert_equal('too', Oktoo()) 3158 3159 assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1))) 3160 END 3161 CheckScriptSuccess(lines) 3162 3163 lines =<< trim END 3164 def Ignore(_: string): string 3165 return _ 3166 enddef 3167 defcompile 3168 END 3169 CheckScriptFailure(lines, 'E1181:', 1) 3170 3171 lines =<< trim END 3172 var _ = 1 3173 END 3174 CheckDefAndScriptFailure(lines, 'E1181:', 1) 3175 3176 lines =<< trim END 3177 var x = _ 3178 END 3179 CheckDefAndScriptFailure(lines, 'E1181:', 1) 3180enddef 3181 3182def Test_too_many_arguments() 3183 var lines =<< trim END 3184 echo [0, 1, 2]->map(() => 123) 3185 END 3186 CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1) 3187 3188 lines =<< trim END 3189 echo [0, 1, 2]->map((_) => 123) 3190 END 3191 CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1) 3192enddef 3193 3194def Test_closing_brace_at_start_of_line() 3195 var lines =<< trim END 3196 def Func() 3197 enddef 3198 Func( 3199 ) 3200 END 3201 call CheckDefAndScriptSuccess(lines) 3202enddef 3203 3204func CreateMydict() 3205 let g:mydict = {} 3206 func g:mydict.afunc() 3207 let g:result = self.key 3208 endfunc 3209endfunc 3210 3211def Test_numbered_function_reference() 3212 CreateMydict() 3213 var output = execute('legacy func g:mydict.afunc') 3214 var funcName = 'g:' .. substitute(output, '.*function \(\d\+\).*', '\1', '') 3215 execute 'function(' .. funcName .. ', [], {key: 42})()' 3216 # check that the function still exists 3217 assert_equal(output, execute('legacy func g:mydict.afunc')) 3218 unlet g:mydict 3219enddef 3220 3221if has('python3') 3222 def Test_python3_heredoc() 3223 py3 << trim EOF 3224 import vim 3225 vim.vars['didit'] = 'yes' 3226 EOF 3227 assert_equal('yes', g:didit) 3228 3229 python3 << trim EOF 3230 import vim 3231 vim.vars['didit'] = 'again' 3232 EOF 3233 assert_equal('again', g:didit) 3234 enddef 3235endif 3236 3237" This messes up syntax highlight, keep near the end. 3238if has('lua') 3239 def Test_lua_heredoc() 3240 g:d = {} 3241 lua << trim EOF 3242 x = vim.eval('g:d') 3243 x['key'] = 'val' 3244 EOF 3245 assert_equal('val', g:d.key) 3246 enddef 3247endif 3248 3249 3250" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3251