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