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