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