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