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