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:') 1152enddef 1153 1154let s:value = '' 1155 1156def FuncOneDefArg(opt = 'text') 1157 s:value = opt 1158enddef 1159 1160def FuncTwoDefArg(nr = 123, opt = 'text'): string 1161 return nr .. opt 1162enddef 1163 1164def FuncVarargs(...arg: list<string>): string 1165 return join(arg, ',') 1166enddef 1167 1168def Test_func_type_varargs() 1169 var RefDefArg: func(?string) 1170 RefDefArg = FuncOneDefArg 1171 RefDefArg() 1172 s:value->assert_equal('text') 1173 RefDefArg('some') 1174 s:value->assert_equal('some') 1175 1176 var RefDef2Arg: func(?number, ?string): string 1177 RefDef2Arg = FuncTwoDefArg 1178 RefDef2Arg()->assert_equal('123text') 1179 RefDef2Arg(99)->assert_equal('99text') 1180 RefDef2Arg(77, 'some')->assert_equal('77some') 1181 1182 CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:') 1183 CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:') 1184 1185 var RefVarargs: func(...list<string>): string 1186 RefVarargs = FuncVarargs 1187 RefVarargs()->assert_equal('') 1188 RefVarargs('one')->assert_equal('one') 1189 RefVarargs('one', 'two')->assert_equal('one,two') 1190 1191 CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:') 1192 CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:') 1193enddef 1194 1195" Only varargs 1196def MyVarargsOnly(...args: list<string>): string 1197 return join(args, ',') 1198enddef 1199 1200def Test_call_varargs_only() 1201 MyVarargsOnly()->assert_equal('') 1202 MyVarargsOnly('one')->assert_equal('one') 1203 MyVarargsOnly('one', 'two')->assert_equal('one,two') 1204 CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number') 1205 CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number') 1206enddef 1207 1208def Test_using_var_as_arg() 1209 writefile(['def Func(x: number)', 'var x = 234', 'enddef', 'defcompile'], 'Xdef') 1210 assert_fails('so Xdef', 'E1006:', '', 1, 'Func') 1211 delete('Xdef') 1212enddef 1213 1214def DictArg(arg: dict<string>) 1215 arg['key'] = 'value' 1216enddef 1217 1218def ListArg(arg: list<string>) 1219 arg[0] = 'value' 1220enddef 1221 1222def Test_assign_to_argument() 1223 # works for dict and list 1224 var d: dict<string> = {} 1225 DictArg(d) 1226 d['key']->assert_equal('value') 1227 var l: list<string> = [] 1228 ListArg(l) 1229 l[0]->assert_equal('value') 1230 1231 CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:') 1232 delfunc! g:Func 1233enddef 1234 1235" These argument names are reserved in legacy functions. 1236def WithReservedNames(firstline: string, lastline: string): string 1237 return firstline .. lastline 1238enddef 1239 1240def Test_argument_names() 1241 assert_equal('OK', WithReservedNames('O', 'K')) 1242enddef 1243 1244def Test_call_func_defined_later() 1245 g:DefinedLater('one')->assert_equal('one') 1246 assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later') 1247enddef 1248 1249func DefinedLater(arg) 1250 return a:arg 1251endfunc 1252 1253def Test_call_funcref() 1254 g:SomeFunc('abc')->assert_equal(3) 1255 assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call 1256 assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref') 1257 1258 var lines =<< trim END 1259 vim9script 1260 def RetNumber(): number 1261 return 123 1262 enddef 1263 var Funcref: func: number = function('RetNumber') 1264 Funcref()->assert_equal(123) 1265 END 1266 CheckScriptSuccess(lines) 1267 1268 lines =<< trim END 1269 vim9script 1270 def RetNumber(): number 1271 return 123 1272 enddef 1273 def Bar(F: func: number): number 1274 return F() 1275 enddef 1276 var Funcref = function('RetNumber') 1277 Bar(Funcref)->assert_equal(123) 1278 END 1279 CheckScriptSuccess(lines) 1280 1281 lines =<< trim END 1282 vim9script 1283 def UseNumber(nr: number) 1284 echo nr 1285 enddef 1286 var Funcref: func(number) = function('UseNumber') 1287 Funcref(123) 1288 END 1289 CheckScriptSuccess(lines) 1290 1291 lines =<< trim END 1292 vim9script 1293 def UseNumber(nr: number) 1294 echo nr 1295 enddef 1296 var Funcref: func(string) = function('UseNumber') 1297 END 1298 CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)') 1299 1300 lines =<< trim END 1301 vim9script 1302 def EchoNr(nr = 34) 1303 g:echo = nr 1304 enddef 1305 var Funcref: func(?number) = function('EchoNr') 1306 Funcref() 1307 g:echo->assert_equal(34) 1308 Funcref(123) 1309 g:echo->assert_equal(123) 1310 END 1311 CheckScriptSuccess(lines) 1312 1313 lines =<< trim END 1314 vim9script 1315 def EchoList(...l: list<number>) 1316 g:echo = l 1317 enddef 1318 var Funcref: func(...list<number>) = function('EchoList') 1319 Funcref() 1320 g:echo->assert_equal([]) 1321 Funcref(1, 2, 3) 1322 g:echo->assert_equal([1, 2, 3]) 1323 END 1324 CheckScriptSuccess(lines) 1325 1326 lines =<< trim END 1327 vim9script 1328 def OptAndVar(nr: number, opt = 12, ...l: list<number>): number 1329 g:optarg = opt 1330 g:listarg = l 1331 return nr 1332 enddef 1333 var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar') 1334 Funcref(10)->assert_equal(10) 1335 g:optarg->assert_equal(12) 1336 g:listarg->assert_equal([]) 1337 1338 Funcref(11, 22)->assert_equal(11) 1339 g:optarg->assert_equal(22) 1340 g:listarg->assert_equal([]) 1341 1342 Funcref(17, 18, 1, 2, 3)->assert_equal(17) 1343 g:optarg->assert_equal(18) 1344 g:listarg->assert_equal([1, 2, 3]) 1345 END 1346 CheckScriptSuccess(lines) 1347enddef 1348 1349let SomeFunc = function('len') 1350let NotAFunc = 'text' 1351 1352def CombineFuncrefTypes() 1353 # same arguments, different return type 1354 var Ref1: func(bool): string 1355 var Ref2: func(bool): number 1356 var Ref3: func(bool): any 1357 Ref3 = g:cond ? Ref1 : Ref2 1358 1359 # different number of arguments 1360 var Refa1: func(bool): number 1361 var Refa2: func(bool, number): number 1362 var Refa3: func: number 1363 Refa3 = g:cond ? Refa1 : Refa2 1364 1365 # different argument types 1366 var Refb1: func(bool, string): number 1367 var Refb2: func(string, number): number 1368 var Refb3: func(any, any): number 1369 Refb3 = g:cond ? Refb1 : Refb2 1370enddef 1371 1372def FuncWithForwardCall() 1373 return g:DefinedEvenLater("yes") 1374enddef 1375 1376def DefinedEvenLater(arg: string): string 1377 return arg 1378enddef 1379 1380def Test_error_in_nested_function() 1381 # Error in called function requires unwinding the call stack. 1382 assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall') 1383enddef 1384 1385def Test_return_type_wrong() 1386 CheckScriptFailure([ 1387 'def Func(): number', 1388 'return "a"', 1389 'enddef', 1390 'defcompile'], 'expected number but got string') 1391 delfunc! g:Func 1392 CheckScriptFailure([ 1393 'def Func(): string', 1394 'return 1', 1395 'enddef', 1396 'defcompile'], 'expected string but got number') 1397 delfunc! g:Func 1398 CheckScriptFailure([ 1399 'def Func(): void', 1400 'return "a"', 1401 'enddef', 1402 'defcompile'], 1403 'E1096: Returning a value in a function without a return type') 1404 delfunc! g:Func 1405 CheckScriptFailure([ 1406 'def Func()', 1407 'return "a"', 1408 'enddef', 1409 'defcompile'], 1410 'E1096: Returning a value in a function without a return type') 1411 delfunc! g:Func 1412 1413 CheckScriptFailure([ 1414 'def Func(): number', 1415 'return', 1416 'enddef', 1417 'defcompile'], 'E1003:') 1418 delfunc! g:Func 1419 1420 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 1421 delfunc! g:Func 1422 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 1423 delfunc! g:Func 1424 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 1425 delfunc! g:Func 1426 1427 CheckScriptFailure([ 1428 'vim9script', 1429 'def FuncB()', 1430 ' return 123', 1431 'enddef', 1432 'def FuncA()', 1433 ' FuncB()', 1434 'enddef', 1435 'defcompile'], 'E1096:') 1436enddef 1437 1438def Test_arg_type_wrong() 1439 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 1440 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 1441 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 1442 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 1443 CheckScriptFailure(['def Func6(...x:list<number>)', 'echo "a"', 'enddef'], 'E1069:') 1444 CheckScriptFailure(['def Func7(...x: int)', 'echo "a"', 'enddef'], 'E1010:') 1445enddef 1446 1447def Test_white_space_before_comma() 1448 var lines =<< trim END 1449 vim9script 1450 def Func(a: number , b: number) 1451 enddef 1452 END 1453 CheckScriptFailure(lines, 'E1068:') 1454 call assert_fails('vim9cmd echo stridx("a" .. "b" , "a")', 'E1068:') 1455enddef 1456 1457def Test_white_space_after_comma() 1458 var lines =<< trim END 1459 vim9script 1460 def Func(a: number,b: number) 1461 enddef 1462 END 1463 CheckScriptFailure(lines, 'E1069:') 1464 1465 # OK in legacy function 1466 lines =<< trim END 1467 vim9script 1468 func Func(a,b) 1469 endfunc 1470 END 1471 CheckScriptSuccess(lines) 1472enddef 1473 1474def Test_vim9script_call() 1475 var lines =<< trim END 1476 vim9script 1477 var name = '' 1478 def MyFunc(arg: string) 1479 name = arg 1480 enddef 1481 MyFunc('foobar') 1482 name->assert_equal('foobar') 1483 1484 var str = 'barfoo' 1485 str->MyFunc() 1486 name->assert_equal('barfoo') 1487 1488 g:value = 'value' 1489 g:value->MyFunc() 1490 name->assert_equal('value') 1491 1492 var listvar = [] 1493 def ListFunc(arg: list<number>) 1494 listvar = arg 1495 enddef 1496 [1, 2, 3]->ListFunc() 1497 listvar->assert_equal([1, 2, 3]) 1498 1499 var dictvar = {} 1500 def DictFunc(arg: dict<number>) 1501 dictvar = arg 1502 enddef 1503 {a: 1, b: 2}->DictFunc() 1504 dictvar->assert_equal({a: 1, b: 2}) 1505 def CompiledDict() 1506 {a: 3, b: 4}->DictFunc() 1507 enddef 1508 CompiledDict() 1509 dictvar->assert_equal({a: 3, b: 4}) 1510 1511 {a: 3, b: 4}->DictFunc() 1512 dictvar->assert_equal({a: 3, b: 4}) 1513 1514 ('text')->MyFunc() 1515 name->assert_equal('text') 1516 ("some")->MyFunc() 1517 name->assert_equal('some') 1518 1519 # line starting with single quote is not a mark 1520 # line starting with double quote can be a method call 1521 'asdfasdf'->MyFunc() 1522 name->assert_equal('asdfasdf') 1523 "xyz"->MyFunc() 1524 name->assert_equal('xyz') 1525 1526 def UseString() 1527 'xyork'->MyFunc() 1528 enddef 1529 UseString() 1530 name->assert_equal('xyork') 1531 1532 def UseString2() 1533 "knife"->MyFunc() 1534 enddef 1535 UseString2() 1536 name->assert_equal('knife') 1537 1538 # prepending a colon makes it a mark 1539 new 1540 setline(1, ['aaa', 'bbb', 'ccc']) 1541 normal! 3Gmt1G 1542 :'t 1543 getcurpos()[1]->assert_equal(3) 1544 bwipe! 1545 1546 MyFunc( 1547 'continued' 1548 ) 1549 assert_equal('continued', 1550 name 1551 ) 1552 1553 call MyFunc( 1554 'more' 1555 .. 1556 'lines' 1557 ) 1558 assert_equal( 1559 'morelines', 1560 name) 1561 END 1562 writefile(lines, 'Xcall.vim') 1563 source Xcall.vim 1564 delete('Xcall.vim') 1565enddef 1566 1567def Test_vim9script_call_fail_decl() 1568 var lines =<< trim END 1569 vim9script 1570 var name = '' 1571 def MyFunc(arg: string) 1572 var name = 123 1573 enddef 1574 defcompile 1575 END 1576 CheckScriptFailure(lines, 'E1054:') 1577enddef 1578 1579def Test_vim9script_call_fail_type() 1580 var lines =<< trim END 1581 vim9script 1582 def MyFunc(arg: string) 1583 echo arg 1584 enddef 1585 MyFunc(1234) 1586 END 1587 CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number') 1588enddef 1589 1590def Test_vim9script_call_fail_const() 1591 var lines =<< trim END 1592 vim9script 1593 const var = '' 1594 def MyFunc(arg: string) 1595 var = 'asdf' 1596 enddef 1597 defcompile 1598 END 1599 writefile(lines, 'Xcall_const.vim') 1600 assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') 1601 delete('Xcall_const.vim') 1602 1603 lines =<< trim END 1604 const g:Aconst = 77 1605 def Change() 1606 # comment 1607 g:Aconst = 99 1608 enddef 1609 call Change() 1610 unlet g:Aconst 1611 END 1612 CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) 1613enddef 1614 1615" Test that inside :function a Python function can be defined, :def is not 1616" recognized. 1617func Test_function_python() 1618 CheckFeature python3 1619 let py = 'python3' 1620 execute py "<< EOF" 1621def do_something(): 1622 return 1 1623EOF 1624endfunc 1625 1626def Test_delfunc() 1627 var lines =<< trim END 1628 vim9script 1629 def g:GoneSoon() 1630 echo 'hello' 1631 enddef 1632 1633 def CallGoneSoon() 1634 GoneSoon() 1635 enddef 1636 defcompile 1637 1638 delfunc g:GoneSoon 1639 CallGoneSoon() 1640 END 1641 writefile(lines, 'XToDelFunc') 1642 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1643 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1644 1645 delete('XToDelFunc') 1646enddef 1647 1648def Test_redef_failure() 1649 writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 1650 so Xdef 1651 writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 1652 so Xdef 1653 writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 1654 assert_fails('so Xdef', 'E1027:', '', 1, 'Func0') 1655 writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 1656 so Xdef 1657 delete('Xdef') 1658 1659 assert_fails('g:Func0()', 'E1091:') 1660 g:Func1()->assert_equal('Func1') 1661 g:Func2()->assert_equal('Func2') 1662 1663 delfunc! Func0 1664 delfunc! Func1 1665 delfunc! Func2 1666enddef 1667 1668def Test_vim9script_func() 1669 var lines =<< trim END 1670 vim9script 1671 func Func(arg) 1672 echo a:arg 1673 endfunc 1674 Func('text') 1675 END 1676 writefile(lines, 'XVim9Func') 1677 so XVim9Func 1678 1679 delete('XVim9Func') 1680enddef 1681 1682let s:funcResult = 0 1683 1684def FuncNoArgNoRet() 1685 s:funcResult = 11 1686enddef 1687 1688def FuncNoArgRetNumber(): number 1689 s:funcResult = 22 1690 return 1234 1691enddef 1692 1693def FuncNoArgRetString(): string 1694 s:funcResult = 45 1695 return 'text' 1696enddef 1697 1698def FuncOneArgNoRet(arg: number) 1699 s:funcResult = arg 1700enddef 1701 1702def FuncOneArgRetNumber(arg: number): number 1703 s:funcResult = arg 1704 return arg 1705enddef 1706 1707def FuncTwoArgNoRet(one: bool, two: number) 1708 s:funcResult = two 1709enddef 1710 1711def FuncOneArgRetString(arg: string): string 1712 return arg 1713enddef 1714 1715def FuncOneArgRetAny(arg: any): any 1716 return arg 1717enddef 1718 1719def Test_func_type() 1720 var Ref1: func() 1721 s:funcResult = 0 1722 Ref1 = FuncNoArgNoRet 1723 Ref1() 1724 s:funcResult->assert_equal(11) 1725 1726 var Ref2: func 1727 s:funcResult = 0 1728 Ref2 = FuncNoArgNoRet 1729 Ref2() 1730 s:funcResult->assert_equal(11) 1731 1732 s:funcResult = 0 1733 Ref2 = FuncOneArgNoRet 1734 Ref2(12) 1735 s:funcResult->assert_equal(12) 1736 1737 s:funcResult = 0 1738 Ref2 = FuncNoArgRetNumber 1739 Ref2()->assert_equal(1234) 1740 s:funcResult->assert_equal(22) 1741 1742 s:funcResult = 0 1743 Ref2 = FuncOneArgRetNumber 1744 Ref2(13)->assert_equal(13) 1745 s:funcResult->assert_equal(13) 1746enddef 1747 1748def Test_repeat_return_type() 1749 var res = 0 1750 for n in repeat([1], 3) 1751 res += n 1752 endfor 1753 res->assert_equal(3) 1754 1755 res = 0 1756 for n in add([1, 2], 3) 1757 res += n 1758 endfor 1759 res->assert_equal(6) 1760enddef 1761 1762def Test_argv_return_type() 1763 next fileone filetwo 1764 var res = '' 1765 for name in argv() 1766 res ..= name 1767 endfor 1768 res->assert_equal('fileonefiletwo') 1769enddef 1770 1771def Test_func_type_part() 1772 var RefVoid: func: void 1773 RefVoid = FuncNoArgNoRet 1774 RefVoid = FuncOneArgNoRet 1775 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number') 1776 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string') 1777 1778 var RefAny: func(): any 1779 RefAny = FuncNoArgRetNumber 1780 RefAny = FuncNoArgRetString 1781 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()') 1782 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)') 1783 1784 var RefAnyNoArgs: func: any = RefAny 1785 1786 var RefNr: func: number 1787 RefNr = FuncNoArgRetNumber 1788 RefNr = FuncOneArgRetNumber 1789 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()') 1790 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string') 1791 1792 var RefStr: func: string 1793 RefStr = FuncNoArgRetString 1794 RefStr = FuncOneArgRetString 1795 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()') 1796 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number') 1797enddef 1798 1799def Test_func_type_fails() 1800 CheckDefFailure(['var ref1: func()'], 'E704:') 1801 1802 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number') 1803 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)') 1804 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number') 1805 CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)') 1806 CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)') 1807 CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)') 1808 1809 CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:') 1810 CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:') 1811 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:') 1812 CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:') 1813enddef 1814 1815def Test_func_return_type() 1816 var nr: number 1817 nr = FuncNoArgRetNumber() 1818 nr->assert_equal(1234) 1819 1820 nr = FuncOneArgRetAny(122) 1821 nr->assert_equal(122) 1822 1823 var str: string 1824 str = FuncOneArgRetAny('yes') 1825 str->assert_equal('yes') 1826 1827 CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number') 1828enddef 1829 1830def Test_func_common_type() 1831 def FuncOne(n: number): number 1832 return n 1833 enddef 1834 def FuncTwo(s: string): number 1835 return len(s) 1836 enddef 1837 def FuncThree(n: number, s: string): number 1838 return n + len(s) 1839 enddef 1840 var list = [FuncOne, FuncTwo, FuncThree] 1841 assert_equal(8, list[0](8)) 1842 assert_equal(4, list[1]('word')) 1843 assert_equal(7, list[2](3, 'word')) 1844enddef 1845 1846def MultiLine( 1847 arg1: string, 1848 arg2 = 1234, 1849 ...rest: list<string> 1850 ): string 1851 return arg1 .. arg2 .. join(rest, '-') 1852enddef 1853 1854def MultiLineComment( 1855 arg1: string, # comment 1856 arg2 = 1234, # comment 1857 ...rest: list<string> # comment 1858 ): string # comment 1859 return arg1 .. arg2 .. join(rest, '-') 1860enddef 1861 1862def Test_multiline() 1863 MultiLine('text')->assert_equal('text1234') 1864 MultiLine('text', 777)->assert_equal('text777') 1865 MultiLine('text', 777, 'one')->assert_equal('text777one') 1866 MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1867enddef 1868 1869func Test_multiline_not_vim9() 1870 call MultiLine('text')->assert_equal('text1234') 1871 call MultiLine('text', 777)->assert_equal('text777') 1872 call MultiLine('text', 777, 'one')->assert_equal('text777one') 1873 call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1874endfunc 1875 1876 1877" When using CheckScriptFailure() for the below test, E1010 is generated instead 1878" of E1056. 1879func Test_E1056_1059() 1880 let caught_1056 = 0 1881 try 1882 def F(): 1883 return 1 1884 enddef 1885 catch /E1056:/ 1886 let caught_1056 = 1 1887 endtry 1888 eval caught_1056->assert_equal(1) 1889 1890 let caught_1059 = 0 1891 try 1892 def F5(items : list) 1893 echo 'a' 1894 enddef 1895 catch /E1059:/ 1896 let caught_1059 = 1 1897 endtry 1898 eval caught_1059->assert_equal(1) 1899endfunc 1900 1901func DelMe() 1902 echo 'DelMe' 1903endfunc 1904 1905def Test_error_reporting() 1906 # comment lines at the start of the function 1907 var lines =<< trim END 1908 " comment 1909 def Func() 1910 # comment 1911 # comment 1912 invalid 1913 enddef 1914 defcompile 1915 END 1916 writefile(lines, 'Xdef') 1917 try 1918 source Xdef 1919 assert_report('should have failed') 1920 catch /E476:/ 1921 v:exception->assert_match('Invalid command: invalid') 1922 v:throwpoint->assert_match(', line 3$') 1923 endtry 1924 delfunc! g:Func 1925 1926 # comment lines after the start of the function 1927 lines =<< trim END 1928 " comment 1929 def Func() 1930 var x = 1234 1931 # comment 1932 # comment 1933 invalid 1934 enddef 1935 defcompile 1936 END 1937 writefile(lines, 'Xdef') 1938 try 1939 source Xdef 1940 assert_report('should have failed') 1941 catch /E476:/ 1942 v:exception->assert_match('Invalid command: invalid') 1943 v:throwpoint->assert_match(', line 4$') 1944 endtry 1945 delfunc! g:Func 1946 1947 lines =<< trim END 1948 vim9script 1949 def Func() 1950 var db = {foo: 1, bar: 2} 1951 # comment 1952 var x = db.asdf 1953 enddef 1954 defcompile 1955 Func() 1956 END 1957 writefile(lines, 'Xdef') 1958 try 1959 source Xdef 1960 assert_report('should have failed') 1961 catch /E716:/ 1962 v:throwpoint->assert_match('_Func, line 3$') 1963 endtry 1964 delfunc! g:Func 1965 1966 delete('Xdef') 1967enddef 1968 1969def Test_deleted_function() 1970 CheckDefExecFailure([ 1971 'var RefMe: func = function("g:DelMe")', 1972 'delfunc g:DelMe', 1973 'echo RefMe()'], 'E117:') 1974enddef 1975 1976def Test_unknown_function() 1977 CheckDefExecFailure([ 1978 'var Ref: func = function("NotExist")', 1979 'delfunc g:NotExist'], 'E700:') 1980enddef 1981 1982def RefFunc(Ref: func(any): any): string 1983 return Ref('more') 1984enddef 1985 1986def Test_closure_simple() 1987 var local = 'some ' 1988 RefFunc((s) => local .. s)->assert_equal('some more') 1989enddef 1990 1991def MakeRef() 1992 var local = 'some ' 1993 g:Ref = (s) => local .. s 1994enddef 1995 1996def Test_closure_ref_after_return() 1997 MakeRef() 1998 g:Ref('thing')->assert_equal('some thing') 1999 unlet g:Ref 2000enddef 2001 2002def MakeTwoRefs() 2003 var local = ['some'] 2004 g:Extend = (s) => local->add(s) 2005 g:Read = () => local 2006enddef 2007 2008def Test_closure_two_refs() 2009 MakeTwoRefs() 2010 join(g:Read(), ' ')->assert_equal('some') 2011 g:Extend('more') 2012 join(g:Read(), ' ')->assert_equal('some more') 2013 g:Extend('even') 2014 join(g:Read(), ' ')->assert_equal('some more even') 2015 2016 unlet g:Extend 2017 unlet g:Read 2018enddef 2019 2020def ReadRef(Ref: func(): list<string>): string 2021 return join(Ref(), ' ') 2022enddef 2023 2024def ExtendRef(Ref: func(string): list<string>, add: string) 2025 Ref(add) 2026enddef 2027 2028def Test_closure_two_indirect_refs() 2029 MakeTwoRefs() 2030 ReadRef(g:Read)->assert_equal('some') 2031 ExtendRef(g:Extend, 'more') 2032 ReadRef(g:Read)->assert_equal('some more') 2033 ExtendRef(g:Extend, 'even') 2034 ReadRef(g:Read)->assert_equal('some more even') 2035 2036 unlet g:Extend 2037 unlet g:Read 2038enddef 2039 2040def MakeArgRefs(theArg: string) 2041 var local = 'loc_val' 2042 g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s 2043enddef 2044 2045def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 2046 var local = 'the_loc' 2047 g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest) 2048enddef 2049 2050def Test_closure_using_argument() 2051 MakeArgRefs('arg_val') 2052 g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val') 2053 2054 MakeArgRefsVarargs('arg_val', 'one', 'two') 2055 g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two') 2056 2057 unlet g:UseArg 2058 unlet g:UseVararg 2059 2060 var lines =<< trim END 2061 vim9script 2062 def Test(Fun: func(number): number): list<number> 2063 return map([1, 2, 3], (_, i) => Fun(i)) 2064 enddef 2065 def Inc(nr: number): number 2066 return nr + 2 2067 enddef 2068 assert_equal([3, 4, 5], Test(Inc)) 2069 END 2070 CheckScriptSuccess(lines) 2071enddef 2072 2073def MakeGetAndAppendRefs() 2074 var local = 'a' 2075 2076 def Append(arg: string) 2077 local ..= arg 2078 enddef 2079 g:Append = Append 2080 2081 def Get(): string 2082 return local 2083 enddef 2084 g:Get = Get 2085enddef 2086 2087def Test_closure_append_get() 2088 MakeGetAndAppendRefs() 2089 g:Get()->assert_equal('a') 2090 g:Append('-b') 2091 g:Get()->assert_equal('a-b') 2092 g:Append('-c') 2093 g:Get()->assert_equal('a-b-c') 2094 2095 unlet g:Append 2096 unlet g:Get 2097enddef 2098 2099def Test_nested_closure() 2100 var local = 'text' 2101 def Closure(arg: string): string 2102 return local .. arg 2103 enddef 2104 Closure('!!!')->assert_equal('text!!!') 2105enddef 2106 2107func GetResult(Ref) 2108 return a:Ref('some') 2109endfunc 2110 2111def Test_call_closure_not_compiled() 2112 var text = 'text' 2113 g:Ref = (s) => s .. text 2114 GetResult(g:Ref)->assert_equal('sometext') 2115enddef 2116 2117def Test_double_closure_fails() 2118 var lines =<< trim END 2119 vim9script 2120 def Func() 2121 var name = 0 2122 for i in range(2) 2123 timer_start(0, () => name) 2124 endfor 2125 enddef 2126 Func() 2127 END 2128 CheckScriptSuccess(lines) 2129enddef 2130 2131def Test_nested_closure_used() 2132 var lines =<< trim END 2133 vim9script 2134 def Func() 2135 var x = 'hello' 2136 var Closure = () => x 2137 g:Myclosure = () => Closure() 2138 enddef 2139 Func() 2140 assert_equal('hello', g:Myclosure()) 2141 END 2142 CheckScriptSuccess(lines) 2143enddef 2144 2145def Test_nested_closure_fails() 2146 var lines =<< trim END 2147 vim9script 2148 def FuncA() 2149 FuncB(0) 2150 enddef 2151 def FuncB(n: number): list<string> 2152 return map([0], (_, v) => n) 2153 enddef 2154 FuncA() 2155 END 2156 CheckScriptFailure(lines, 'E1012:') 2157enddef 2158 2159def Test_global_closure() 2160 var lines =<< trim END 2161 vim9script 2162 def ReverseEveryNLines(n: number, line1: number, line2: number) 2163 var mods = 'sil keepj keepp lockm ' 2164 var range = ':' .. line1 .. ',' .. line2 2165 def g:Offset(): number 2166 var offset = (line('.') - line1 + 1) % n 2167 return offset != 0 ? offset : n 2168 enddef 2169 exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()' 2170 enddef 2171 2172 new 2173 repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1) 2174 ReverseEveryNLines(3, 1, 9) 2175 END 2176 CheckScriptSuccess(lines) 2177 var expected = repeat(['ccc', 'bbb', 'aaa'], 3) 2178 assert_equal(expected, getline(1, 9)) 2179 bwipe! 2180enddef 2181 2182def Test_global_closure_called_directly() 2183 var lines =<< trim END 2184 vim9script 2185 def Outer() 2186 var x = 1 2187 def g:Inner() 2188 var y = x 2189 x += 1 2190 assert_equal(1, y) 2191 enddef 2192 g:Inner() 2193 assert_equal(2, x) 2194 enddef 2195 Outer() 2196 END 2197 CheckScriptSuccess(lines) 2198 delfunc g:Inner 2199enddef 2200 2201def Test_failure_in_called_function() 2202 # this was using the frame index as the return value 2203 var lines =<< trim END 2204 vim9script 2205 au TerminalWinOpen * eval [][0] 2206 def PopupTerm(a: any) 2207 # make sure typvals on stack are string 2208 ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join() 2209 FireEvent() 2210 enddef 2211 def FireEvent() 2212 do TerminalWinOpen 2213 enddef 2214 # use try/catch to make eval fail 2215 try 2216 call PopupTerm(0) 2217 catch 2218 endtry 2219 au! TerminalWinOpen 2220 END 2221 CheckScriptSuccess(lines) 2222enddef 2223 2224def Test_nested_lambda() 2225 var lines =<< trim END 2226 vim9script 2227 def Func() 2228 var x = 4 2229 var Lambda1 = () => 7 2230 var Lambda2 = () => [Lambda1(), x] 2231 var res = Lambda2() 2232 assert_equal([7, 4], res) 2233 enddef 2234 Func() 2235 END 2236 CheckScriptSuccess(lines) 2237enddef 2238 2239def Test_double_nested_lambda() 2240 var lines =<< trim END 2241 vim9script 2242 def F(head: string): func(string): func(string): string 2243 return (sep: string): func(string): string => ((tail: string): string => { 2244 return head .. sep .. tail 2245 }) 2246 enddef 2247 assert_equal('hello-there', F('hello')('-')('there')) 2248 END 2249 CheckScriptSuccess(lines) 2250enddef 2251 2252def Test_nested_inline_lambda() 2253 # TODO: use the "text" argument 2254 var lines =<< trim END 2255 vim9script 2256 def F(text: string): func(string): func(string): string 2257 return (arg: string): func(string): string => ((sep: string): string => { 2258 return sep .. arg 2259 }) 2260 enddef 2261 assert_equal('--there', F('unused')('there')('--')) 2262 END 2263 CheckScriptSuccess(lines) 2264 2265 lines =<< trim END 2266 vim9script 2267 echo range(4)->mapnew((_, v) => { 2268 return range(v) ->mapnew((_, s) => { 2269 return string(s) 2270 }) 2271 }) 2272 END 2273 CheckScriptSuccess(lines) 2274 2275 lines =<< trim END 2276 vim9script 2277 2278 def s:func() 2279 range(10) 2280 ->mapnew((_, _) => ({ 2281 key: range(10)->mapnew((_, _) => { 2282 return ' ' 2283 }), 2284 })) 2285 enddef 2286 2287 defcomp 2288 END 2289 CheckScriptSuccess(lines) 2290enddef 2291 2292def Shadowed(): list<number> 2293 var FuncList: list<func: number> = [() => 42] 2294 return FuncList->mapnew((_, Shadowed) => Shadowed()) 2295enddef 2296 2297def Test_lambda_arg_shadows_func() 2298 assert_equal([42], Shadowed()) 2299enddef 2300 2301def Line_continuation_in_def(dir: string = ''): string 2302 var path: string = empty(dir) 2303 \ ? 'empty' 2304 \ : 'full' 2305 return path 2306enddef 2307 2308def Test_line_continuation_in_def() 2309 Line_continuation_in_def('.')->assert_equal('full') 2310enddef 2311 2312def Test_script_var_in_lambda() 2313 var lines =<< trim END 2314 vim9script 2315 var script = 'test' 2316 assert_equal(['test'], map(['one'], (_, _) => script)) 2317 END 2318 CheckScriptSuccess(lines) 2319enddef 2320 2321def Line_continuation_in_lambda(): list<string> 2322 var x = range(97, 100) 2323 ->mapnew((_, v) => nr2char(v) 2324 ->toupper()) 2325 ->reverse() 2326 return x 2327enddef 2328 2329def Test_line_continuation_in_lambda() 2330 Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A']) 2331 2332 var lines =<< trim END 2333 vim9script 2334 var res = [{n: 1, m: 2, s: 'xxx'}] 2335 ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s', 2336 v.n, 2337 v.m, 2338 substitute(v.s, '.*', 'yyy', '') 2339 )) 2340 assert_equal(['1:2:yyy'], res) 2341 END 2342 CheckScriptSuccess(lines) 2343enddef 2344 2345def Test_list_lambda() 2346 timer_start(1000, (_) => 0) 2347 var body = execute(timer_info()[0].callback 2348 ->string() 2349 ->substitute("('", ' ', '') 2350 ->substitute("')", '', '') 2351 ->substitute('function\zs', ' ', '')) 2352 assert_match('def <lambda>\d\+(_: any): number\n1 return 0\n enddef', body) 2353enddef 2354 2355def Test_lamba_block_variable() 2356 var lines =<< trim END 2357 vim9script 2358 var flist: list<func> 2359 for i in range(10) 2360 var inloop = i 2361 flist[i] = () => inloop 2362 endfor 2363 END 2364 CheckScriptSuccess(lines) 2365 2366 lines =<< trim END 2367 vim9script 2368 if true 2369 var outloop = 5 2370 var flist: list<func> 2371 for i in range(10) 2372 flist[i] = () => outloop 2373 endfor 2374 endif 2375 END 2376 CheckScriptSuccess(lines) 2377 2378 lines =<< trim END 2379 vim9script 2380 if true 2381 var outloop = 5 2382 endif 2383 var flist: list<func> 2384 for i in range(10) 2385 flist[i] = () => outloop 2386 endfor 2387 END 2388 CheckScriptFailure(lines, 'E1001: Variable not found: outloop', 1) 2389enddef 2390 2391def Test_legacy_lambda() 2392 legacy echo {x -> 'hello ' .. x}('foo') 2393 2394 var lines =<< trim END 2395 echo {x -> 'hello ' .. x}('foo') 2396 END 2397 CheckDefAndScriptFailure(lines, 'E720:') 2398 2399 lines =<< trim END 2400 vim9script 2401 def Func() 2402 echo (() => 'no error')() 2403 enddef 2404 legacy call s:Func() 2405 END 2406 CheckScriptSuccess(lines) 2407enddef 2408 2409def Test_legacy() 2410 var lines =<< trim END 2411 vim9script 2412 func g:LegacyFunction() 2413 let g:legacyvar = 1 2414 endfunc 2415 def Testit() 2416 legacy call g:LegacyFunction() 2417 enddef 2418 Testit() 2419 assert_equal(1, g:legacyvar) 2420 unlet g:legacyvar 2421 delfunc g:LegacyFunction 2422 END 2423 CheckScriptSuccess(lines) 2424enddef 2425 2426def Test_legacy_errors() 2427 for cmd in ['if', 'elseif', 'else', 'endif', 2428 'for', 'endfor', 'continue', 'break', 2429 'while', 'endwhile', 2430 'try', 'catch', 'finally', 'endtry'] 2431 CheckDefFailure(['legacy ' .. cmd .. ' expr'], 'E1189:') 2432 endfor 2433enddef 2434 2435def DoFilterThis(a: string): list<string> 2436 # closure nested inside another closure using argument 2437 var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0) 2438 return ['x', 'y', 'a', 'x2', 'c']->Filter() 2439enddef 2440 2441def Test_nested_closure_using_argument() 2442 assert_equal(['x', 'x2'], DoFilterThis('x')) 2443enddef 2444 2445def Test_triple_nested_closure() 2446 var what = 'x' 2447 var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0 2448 var Filter = (l) => filter(l, (_, v) => Match(v, what)) 2449 assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter()) 2450enddef 2451 2452func Test_silent_echo() 2453 CheckScreendump 2454 2455 let lines =<< trim END 2456 vim9script 2457 def EchoNothing() 2458 silent echo '' 2459 enddef 2460 defcompile 2461 END 2462 call writefile(lines, 'XTest_silent_echo') 2463 2464 " Check that the balloon shows up after a mouse move 2465 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 2466 call term_sendkeys(buf, ":abc") 2467 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 2468 2469 " clean up 2470 call StopVimInTerminal(buf) 2471 call delete('XTest_silent_echo') 2472endfunc 2473 2474def SilentlyError() 2475 execute('silent! invalid') 2476 g:did_it = 'yes' 2477enddef 2478 2479func UserError() 2480 silent! invalid 2481endfunc 2482 2483def SilentlyUserError() 2484 UserError() 2485 g:did_it = 'yes' 2486enddef 2487 2488" This can't be a :def function, because the assert would not be reached. 2489func Test_ignore_silent_error() 2490 let g:did_it = 'no' 2491 call SilentlyError() 2492 call assert_equal('yes', g:did_it) 2493 2494 let g:did_it = 'no' 2495 call SilentlyUserError() 2496 call assert_equal('yes', g:did_it) 2497 2498 unlet g:did_it 2499endfunc 2500 2501def Test_ignore_silent_error_in_filter() 2502 var lines =<< trim END 2503 vim9script 2504 def Filter(winid: number, key: string): bool 2505 if key == 'o' 2506 silent! eval [][0] 2507 return true 2508 endif 2509 return popup_filter_menu(winid, key) 2510 enddef 2511 2512 popup_create('popup', {filter: Filter}) 2513 feedkeys("o\r", 'xnt') 2514 END 2515 CheckScriptSuccess(lines) 2516enddef 2517 2518def Fibonacci(n: number): number 2519 if n < 2 2520 return n 2521 else 2522 return Fibonacci(n - 1) + Fibonacci(n - 2) 2523 endif 2524enddef 2525 2526def Test_recursive_call() 2527 Fibonacci(20)->assert_equal(6765) 2528enddef 2529 2530def TreeWalk(dir: string): list<any> 2531 return readdir(dir)->mapnew((_, val) => 2532 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 2533 ? {[val]: TreeWalk(dir .. '/' .. val)} 2534 : val 2535 ) 2536enddef 2537 2538def Test_closure_in_map() 2539 mkdir('XclosureDir/tdir', 'p') 2540 writefile(['111'], 'XclosureDir/file1') 2541 writefile(['222'], 'XclosureDir/file2') 2542 writefile(['333'], 'XclosureDir/tdir/file3') 2543 2544 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) 2545 2546 delete('XclosureDir', 'rf') 2547enddef 2548 2549def Test_invalid_function_name() 2550 var lines =<< trim END 2551 vim9script 2552 def s: list<string> 2553 END 2554 CheckScriptFailure(lines, 'E129:') 2555 2556 lines =<< trim END 2557 vim9script 2558 def g: list<string> 2559 END 2560 CheckScriptFailure(lines, 'E129:') 2561 2562 lines =<< trim END 2563 vim9script 2564 def <SID>: list<string> 2565 END 2566 CheckScriptFailure(lines, 'E884:') 2567 2568 lines =<< trim END 2569 vim9script 2570 def F list<string> 2571 END 2572 CheckScriptFailure(lines, 'E488:') 2573enddef 2574 2575def Test_partial_call() 2576 var Xsetlist = function('setloclist', [0]) 2577 Xsetlist([], ' ', {title: 'test'}) 2578 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2579 2580 Xsetlist = function('setloclist', [0, [], ' ']) 2581 Xsetlist({title: 'test'}) 2582 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2583 2584 Xsetlist = function('setqflist') 2585 Xsetlist([], ' ', {title: 'test'}) 2586 getqflist({title: 1})->assert_equal({title: 'test'}) 2587 2588 Xsetlist = function('setqflist', [[], ' ']) 2589 Xsetlist({title: 'test'}) 2590 getqflist({title: 1})->assert_equal({title: 'test'}) 2591 2592 var Len: func: number = function('len', ['word']) 2593 assert_equal(4, Len()) 2594enddef 2595 2596def Test_cmd_modifier() 2597 tab echo '0' 2598 CheckDefFailure(['5tab echo 3'], 'E16:') 2599enddef 2600 2601def Test_restore_modifiers() 2602 # check that when compiling a :def function command modifiers are not messed 2603 # up. 2604 var lines =<< trim END 2605 vim9script 2606 set eventignore= 2607 autocmd QuickFixCmdPost * copen 2608 def AutocmdsDisabled() 2609 eval 1 + 2 2610 enddef 2611 func Func() 2612 noautocmd call s:AutocmdsDisabled() 2613 let g:ei_after = &eventignore 2614 endfunc 2615 Func() 2616 END 2617 CheckScriptSuccess(lines) 2618 g:ei_after->assert_equal('') 2619enddef 2620 2621def StackTop() 2622 eval 1 + 2 2623 eval 2 + 3 2624 # call not on fourth line 2625 StackBot() 2626enddef 2627 2628def StackBot() 2629 # throw an error 2630 eval [][0] 2631enddef 2632 2633def Test_callstack_def() 2634 try 2635 StackTop() 2636 catch 2637 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2') 2638 endtry 2639enddef 2640 2641" Re-using spot for variable used in block 2642def Test_block_scoped_var() 2643 var lines =<< trim END 2644 vim9script 2645 def Func() 2646 var x = ['a', 'b', 'c'] 2647 if 1 2648 var y = 'x' 2649 map(x, (_, _) => y) 2650 endif 2651 var z = x 2652 assert_equal(['x', 'x', 'x'], z) 2653 enddef 2654 Func() 2655 END 2656 CheckScriptSuccess(lines) 2657enddef 2658 2659def Test_reset_did_emsg() 2660 var lines =<< trim END 2661 @s = 'blah' 2662 au BufWinLeave * # 2663 def Func() 2664 var winid = popup_create('popup', {}) 2665 exe '*s' 2666 popup_close(winid) 2667 enddef 2668 Func() 2669 END 2670 CheckScriptFailure(lines, 'E492:', 8) 2671 delfunc! g:Func 2672enddef 2673 2674def Test_did_emsg_reset() 2675 # executing an autocommand resets did_emsg, this should not result in a 2676 # builtin function considered failing 2677 var lines =<< trim END 2678 vim9script 2679 au BufWinLeave * # 2680 def Func() 2681 popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()}) 2682 eval [][0] 2683 enddef 2684 nno <F3> <cmd>call <sid>Func()<cr> 2685 feedkeys("\<F3>\e", 'xt') 2686 END 2687 writefile(lines, 'XemsgReset') 2688 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) 2689 delete('XemsgReset') 2690 nunmap <F3> 2691 au! BufWinLeave 2692enddef 2693 2694def Test_abort_with_silent_call() 2695 var lines =<< trim END 2696 vim9script 2697 g:result = 'none' 2698 def Func() 2699 g:result += 3 2700 g:result = 'yes' 2701 enddef 2702 # error is silenced, but function aborts on error 2703 silent! Func() 2704 assert_equal('none', g:result) 2705 unlet g:result 2706 END 2707 CheckScriptSuccess(lines) 2708enddef 2709 2710def Test_continues_with_silent_error() 2711 var lines =<< trim END 2712 vim9script 2713 g:result = 'none' 2714 def Func() 2715 silent! g:result += 3 2716 g:result = 'yes' 2717 enddef 2718 # error is silenced, function does not abort 2719 Func() 2720 assert_equal('yes', g:result) 2721 unlet g:result 2722 END 2723 CheckScriptSuccess(lines) 2724enddef 2725 2726def Test_abort_even_with_silent() 2727 var lines =<< trim END 2728 vim9script 2729 g:result = 'none' 2730 def Func() 2731 eval {-> ''}() .. '' .. {}['X'] 2732 g:result = 'yes' 2733 enddef 2734 silent! Func() 2735 assert_equal('none', g:result) 2736 unlet g:result 2737 END 2738 CheckScriptSuccess(lines) 2739enddef 2740 2741def Test_cmdmod_silent_restored() 2742 var lines =<< trim END 2743 vim9script 2744 def Func() 2745 g:result = 'none' 2746 silent! g:result += 3 2747 g:result = 'none' 2748 g:result += 3 2749 enddef 2750 Func() 2751 END 2752 # can't use CheckScriptFailure, it ignores the :silent! 2753 var fname = 'Xdefsilent' 2754 writefile(lines, fname) 2755 var caught = 'no' 2756 try 2757 exe 'source ' .. fname 2758 catch /E1030:/ 2759 caught = 'yes' 2760 assert_match('Func, line 4', v:throwpoint) 2761 endtry 2762 assert_equal('yes', caught) 2763 delete(fname) 2764enddef 2765 2766def Test_cmdmod_silent_nested() 2767 var lines =<< trim END 2768 vim9script 2769 var result = '' 2770 2771 def Error() 2772 result ..= 'Eb' 2773 eval [][0] 2774 result ..= 'Ea' 2775 enddef 2776 2777 def Crash() 2778 result ..= 'Cb' 2779 sil! Error() 2780 result ..= 'Ca' 2781 enddef 2782 2783 Crash() 2784 assert_equal('CbEbEaCa', result) 2785 END 2786 CheckScriptSuccess(lines) 2787enddef 2788 2789def Test_dict_member_with_silent() 2790 var lines =<< trim END 2791 vim9script 2792 g:result = 'none' 2793 var d: dict<any> 2794 def Func() 2795 try 2796 g:result = map([], (_, v) => ({}[v]))->join() .. d[''] 2797 catch 2798 endtry 2799 enddef 2800 silent! Func() 2801 assert_equal('0', g:result) 2802 unlet g:result 2803 END 2804 CheckScriptSuccess(lines) 2805enddef 2806 2807def Test_skip_cmds_with_silent() 2808 var lines =<< trim END 2809 vim9script 2810 2811 def Func(b: bool) 2812 Crash() 2813 enddef 2814 2815 def Crash() 2816 sil! :/not found/d _ 2817 sil! :/not found/put _ 2818 enddef 2819 2820 Func(true) 2821 END 2822 CheckScriptSuccess(lines) 2823enddef 2824 2825def Test_opfunc() 2826 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@ 2827 def g:Opfunc(_: any): string 2828 setline(1, 'ASDF') 2829 return '' 2830 enddef 2831 new 2832 setline(1, 'asdf') 2833 feedkeys("\<F3>$", 'x') 2834 assert_equal('ASDF', getline(1)) 2835 2836 bwipe! 2837 nunmap <F3> 2838enddef 2839 2840" this was crashing on exit 2841def Test_nested_lambda_in_closure() 2842 var lines =<< trim END 2843 vim9script 2844 command WriteDone writefile(['Done'], 'XnestedDone') 2845 def Outer() 2846 def g:Inner() 2847 echo map([1, 2, 3], {_, v -> v + 1}) 2848 enddef 2849 g:Inner() 2850 enddef 2851 defcompile 2852 # not reached 2853 END 2854 if !RunVim([], lines, '--clean -c WriteDone -c quit') 2855 return 2856 endif 2857 assert_equal(['Done'], readfile('XnestedDone')) 2858 delete('XnestedDone') 2859enddef 2860 2861def Test_check_func_arg_types() 2862 var lines =<< trim END 2863 vim9script 2864 def F1(x: string): string 2865 return x 2866 enddef 2867 2868 def F2(x: number): number 2869 return x + 1 2870 enddef 2871 2872 def G(g: func): dict<func> 2873 return {f: g} 2874 enddef 2875 2876 def H(d: dict<func>): string 2877 return d.f('a') 2878 enddef 2879 END 2880 2881 CheckScriptSuccess(lines + ['echo H(G(F1))']) 2882 CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:') 2883enddef 2884 2885def Test_compile_error() 2886 var lines =<< trim END 2887 def g:Broken() 2888 echo 'a' + {} 2889 enddef 2890 call g:Broken() 2891 END 2892 # First call: compilation error 2893 CheckScriptFailure(lines, 'E1051: Wrong argument type for +') 2894 2895 # Second call won't try compiling again 2896 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2897 delfunc g:Broken 2898 2899 # No error when compiling with :silent! 2900 lines =<< trim END 2901 def g:Broken() 2902 echo 'a' + [] 2903 enddef 2904 silent! defcompile 2905 END 2906 CheckScriptSuccess(lines) 2907 2908 # Calling the function won't try compiling again 2909 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2910 delfunc g:Broken 2911enddef 2912 2913def Test_ignored_argument() 2914 var lines =<< trim END 2915 vim9script 2916 def Ignore(_, _): string 2917 return 'yes' 2918 enddef 2919 assert_equal('yes', Ignore(1, 2)) 2920 2921 func Ok(_) 2922 return a:_ 2923 endfunc 2924 assert_equal('ok', Ok('ok')) 2925 2926 func Oktoo() 2927 let _ = 'too' 2928 return _ 2929 endfunc 2930 assert_equal('too', Oktoo()) 2931 2932 assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1))) 2933 END 2934 CheckScriptSuccess(lines) 2935 2936 lines =<< trim END 2937 def Ignore(_: string): string 2938 return _ 2939 enddef 2940 defcompile 2941 END 2942 CheckScriptFailure(lines, 'E1181:', 1) 2943 2944 lines =<< trim END 2945 var _ = 1 2946 END 2947 CheckDefAndScriptFailure(lines, 'E1181:', 1) 2948 2949 lines =<< trim END 2950 var x = _ 2951 END 2952 CheckDefAndScriptFailure(lines, 'E1181:', 1) 2953enddef 2954 2955def Test_too_many_arguments() 2956 var lines =<< trim END 2957 echo [0, 1, 2]->map(() => 123) 2958 END 2959 CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1) 2960 2961 lines =<< trim END 2962 echo [0, 1, 2]->map((_) => 123) 2963 END 2964 CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1) 2965enddef 2966 2967def Test_closing_brace_at_start_of_line() 2968 var lines =<< trim END 2969 def Func() 2970 enddef 2971 Func( 2972 ) 2973 END 2974 call CheckDefAndScriptSuccess(lines) 2975enddef 2976 2977if has('python3') 2978 def Test_python3_heredoc() 2979 py3 << trim EOF 2980 import vim 2981 vim.vars['didit'] = 'yes' 2982 EOF 2983 assert_equal('yes', g:didit) 2984 2985 python3 << trim EOF 2986 import vim 2987 vim.vars['didit'] = 'again' 2988 EOF 2989 assert_equal('again', g:didit) 2990 enddef 2991endif 2992 2993" This messes up syntax highlight, keep near the end. 2994if has('lua') 2995 def Test_lua_heredoc() 2996 g:d = {} 2997 lua << trim EOF 2998 x = vim.eval('g:d') 2999 x['key'] = 'val' 3000 EOF 3001 assert_equal('val', g:d.key) 3002 enddef 3003endif 3004 3005 3006" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3007