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