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_lambda_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) 2389 2390 lines =<< trim END 2391 vim9script 2392 for i in range(10) 2393 var Ref = () => 0 2394 endfor 2395 assert_equal(0, ((i) => 0)(0)) 2396 END 2397 CheckScriptSuccess(lines) 2398enddef 2399 2400def Test_legacy_lambda() 2401 legacy echo {x -> 'hello ' .. x}('foo') 2402 2403 var lines =<< trim END 2404 echo {x -> 'hello ' .. x}('foo') 2405 END 2406 CheckDefAndScriptFailure(lines, 'E720:') 2407 2408 lines =<< trim END 2409 vim9script 2410 def Func() 2411 echo (() => 'no error')() 2412 enddef 2413 legacy call s:Func() 2414 END 2415 CheckScriptSuccess(lines) 2416enddef 2417 2418def Test_legacy() 2419 var lines =<< trim END 2420 vim9script 2421 func g:LegacyFunction() 2422 let g:legacyvar = 1 2423 endfunc 2424 def Testit() 2425 legacy call g:LegacyFunction() 2426 enddef 2427 Testit() 2428 assert_equal(1, g:legacyvar) 2429 unlet g:legacyvar 2430 delfunc g:LegacyFunction 2431 END 2432 CheckScriptSuccess(lines) 2433enddef 2434 2435def Test_legacy_errors() 2436 for cmd in ['if', 'elseif', 'else', 'endif', 2437 'for', 'endfor', 'continue', 'break', 2438 'while', 'endwhile', 2439 'try', 'catch', 'finally', 'endtry'] 2440 CheckDefFailure(['legacy ' .. cmd .. ' expr'], 'E1189:') 2441 endfor 2442enddef 2443 2444def DoFilterThis(a: string): list<string> 2445 # closure nested inside another closure using argument 2446 var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0) 2447 return ['x', 'y', 'a', 'x2', 'c']->Filter() 2448enddef 2449 2450def Test_nested_closure_using_argument() 2451 assert_equal(['x', 'x2'], DoFilterThis('x')) 2452enddef 2453 2454def Test_triple_nested_closure() 2455 var what = 'x' 2456 var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0 2457 var Filter = (l) => filter(l, (_, v) => Match(v, what)) 2458 assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter()) 2459enddef 2460 2461func Test_silent_echo() 2462 CheckScreendump 2463 2464 let lines =<< trim END 2465 vim9script 2466 def EchoNothing() 2467 silent echo '' 2468 enddef 2469 defcompile 2470 END 2471 call writefile(lines, 'XTest_silent_echo') 2472 2473 " Check that the balloon shows up after a mouse move 2474 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 2475 call term_sendkeys(buf, ":abc") 2476 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 2477 2478 " clean up 2479 call StopVimInTerminal(buf) 2480 call delete('XTest_silent_echo') 2481endfunc 2482 2483def SilentlyError() 2484 execute('silent! invalid') 2485 g:did_it = 'yes' 2486enddef 2487 2488func UserError() 2489 silent! invalid 2490endfunc 2491 2492def SilentlyUserError() 2493 UserError() 2494 g:did_it = 'yes' 2495enddef 2496 2497" This can't be a :def function, because the assert would not be reached. 2498func Test_ignore_silent_error() 2499 let g:did_it = 'no' 2500 call SilentlyError() 2501 call assert_equal('yes', g:did_it) 2502 2503 let g:did_it = 'no' 2504 call SilentlyUserError() 2505 call assert_equal('yes', g:did_it) 2506 2507 unlet g:did_it 2508endfunc 2509 2510def Test_ignore_silent_error_in_filter() 2511 var lines =<< trim END 2512 vim9script 2513 def Filter(winid: number, key: string): bool 2514 if key == 'o' 2515 silent! eval [][0] 2516 return true 2517 endif 2518 return popup_filter_menu(winid, key) 2519 enddef 2520 2521 popup_create('popup', {filter: Filter}) 2522 feedkeys("o\r", 'xnt') 2523 END 2524 CheckScriptSuccess(lines) 2525enddef 2526 2527def Fibonacci(n: number): number 2528 if n < 2 2529 return n 2530 else 2531 return Fibonacci(n - 1) + Fibonacci(n - 2) 2532 endif 2533enddef 2534 2535def Test_recursive_call() 2536 Fibonacci(20)->assert_equal(6765) 2537enddef 2538 2539def TreeWalk(dir: string): list<any> 2540 return readdir(dir)->mapnew((_, val) => 2541 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 2542 ? {[val]: TreeWalk(dir .. '/' .. val)} 2543 : val 2544 ) 2545enddef 2546 2547def Test_closure_in_map() 2548 mkdir('XclosureDir/tdir', 'p') 2549 writefile(['111'], 'XclosureDir/file1') 2550 writefile(['222'], 'XclosureDir/file2') 2551 writefile(['333'], 'XclosureDir/tdir/file3') 2552 2553 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) 2554 2555 delete('XclosureDir', 'rf') 2556enddef 2557 2558def Test_invalid_function_name() 2559 var lines =<< trim END 2560 vim9script 2561 def s: list<string> 2562 END 2563 CheckScriptFailure(lines, 'E129:') 2564 2565 lines =<< trim END 2566 vim9script 2567 def g: list<string> 2568 END 2569 CheckScriptFailure(lines, 'E129:') 2570 2571 lines =<< trim END 2572 vim9script 2573 def <SID>: list<string> 2574 END 2575 CheckScriptFailure(lines, 'E884:') 2576 2577 lines =<< trim END 2578 vim9script 2579 def F list<string> 2580 END 2581 CheckScriptFailure(lines, 'E488:') 2582enddef 2583 2584def Test_partial_call() 2585 var Xsetlist = function('setloclist', [0]) 2586 Xsetlist([], ' ', {title: 'test'}) 2587 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2588 2589 Xsetlist = function('setloclist', [0, [], ' ']) 2590 Xsetlist({title: 'test'}) 2591 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 2592 2593 Xsetlist = function('setqflist') 2594 Xsetlist([], ' ', {title: 'test'}) 2595 getqflist({title: 1})->assert_equal({title: 'test'}) 2596 2597 Xsetlist = function('setqflist', [[], ' ']) 2598 Xsetlist({title: 'test'}) 2599 getqflist({title: 1})->assert_equal({title: 'test'}) 2600 2601 var Len: func: number = function('len', ['word']) 2602 assert_equal(4, Len()) 2603enddef 2604 2605def Test_cmd_modifier() 2606 tab echo '0' 2607 CheckDefFailure(['5tab echo 3'], 'E16:') 2608enddef 2609 2610def Test_restore_modifiers() 2611 # check that when compiling a :def function command modifiers are not messed 2612 # up. 2613 var lines =<< trim END 2614 vim9script 2615 set eventignore= 2616 autocmd QuickFixCmdPost * copen 2617 def AutocmdsDisabled() 2618 eval 1 + 2 2619 enddef 2620 func Func() 2621 noautocmd call s:AutocmdsDisabled() 2622 let g:ei_after = &eventignore 2623 endfunc 2624 Func() 2625 END 2626 CheckScriptSuccess(lines) 2627 g:ei_after->assert_equal('') 2628enddef 2629 2630def StackTop() 2631 eval 1 + 2 2632 eval 2 + 3 2633 # call not on fourth line 2634 StackBot() 2635enddef 2636 2637def StackBot() 2638 # throw an error 2639 eval [][0] 2640enddef 2641 2642def Test_callstack_def() 2643 try 2644 StackTop() 2645 catch 2646 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2') 2647 endtry 2648enddef 2649 2650" Re-using spot for variable used in block 2651def Test_block_scoped_var() 2652 var lines =<< trim END 2653 vim9script 2654 def Func() 2655 var x = ['a', 'b', 'c'] 2656 if 1 2657 var y = 'x' 2658 map(x, (_, _) => y) 2659 endif 2660 var z = x 2661 assert_equal(['x', 'x', 'x'], z) 2662 enddef 2663 Func() 2664 END 2665 CheckScriptSuccess(lines) 2666enddef 2667 2668def Test_reset_did_emsg() 2669 var lines =<< trim END 2670 @s = 'blah' 2671 au BufWinLeave * # 2672 def Func() 2673 var winid = popup_create('popup', {}) 2674 exe '*s' 2675 popup_close(winid) 2676 enddef 2677 Func() 2678 END 2679 CheckScriptFailure(lines, 'E492:', 8) 2680 delfunc! g:Func 2681enddef 2682 2683def Test_did_emsg_reset() 2684 # executing an autocommand resets did_emsg, this should not result in a 2685 # builtin function considered failing 2686 var lines =<< trim END 2687 vim9script 2688 au BufWinLeave * # 2689 def Func() 2690 popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()}) 2691 eval [][0] 2692 enddef 2693 nno <F3> <cmd>call <sid>Func()<cr> 2694 feedkeys("\<F3>\e", 'xt') 2695 END 2696 writefile(lines, 'XemsgReset') 2697 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) 2698 delete('XemsgReset') 2699 nunmap <F3> 2700 au! BufWinLeave 2701enddef 2702 2703def Test_abort_with_silent_call() 2704 var lines =<< trim END 2705 vim9script 2706 g:result = 'none' 2707 def Func() 2708 g:result += 3 2709 g:result = 'yes' 2710 enddef 2711 # error is silenced, but function aborts on error 2712 silent! Func() 2713 assert_equal('none', g:result) 2714 unlet g:result 2715 END 2716 CheckScriptSuccess(lines) 2717enddef 2718 2719def Test_continues_with_silent_error() 2720 var lines =<< trim END 2721 vim9script 2722 g:result = 'none' 2723 def Func() 2724 silent! g:result += 3 2725 g:result = 'yes' 2726 enddef 2727 # error is silenced, function does not abort 2728 Func() 2729 assert_equal('yes', g:result) 2730 unlet g:result 2731 END 2732 CheckScriptSuccess(lines) 2733enddef 2734 2735def Test_abort_even_with_silent() 2736 var lines =<< trim END 2737 vim9script 2738 g:result = 'none' 2739 def Func() 2740 eval {-> ''}() .. '' .. {}['X'] 2741 g:result = 'yes' 2742 enddef 2743 silent! Func() 2744 assert_equal('none', g:result) 2745 unlet g:result 2746 END 2747 CheckScriptSuccess(lines) 2748enddef 2749 2750def Test_cmdmod_silent_restored() 2751 var lines =<< trim END 2752 vim9script 2753 def Func() 2754 g:result = 'none' 2755 silent! g:result += 3 2756 g:result = 'none' 2757 g:result += 3 2758 enddef 2759 Func() 2760 END 2761 # can't use CheckScriptFailure, it ignores the :silent! 2762 var fname = 'Xdefsilent' 2763 writefile(lines, fname) 2764 var caught = 'no' 2765 try 2766 exe 'source ' .. fname 2767 catch /E1030:/ 2768 caught = 'yes' 2769 assert_match('Func, line 4', v:throwpoint) 2770 endtry 2771 assert_equal('yes', caught) 2772 delete(fname) 2773enddef 2774 2775def Test_cmdmod_silent_nested() 2776 var lines =<< trim END 2777 vim9script 2778 var result = '' 2779 2780 def Error() 2781 result ..= 'Eb' 2782 eval [][0] 2783 result ..= 'Ea' 2784 enddef 2785 2786 def Crash() 2787 result ..= 'Cb' 2788 sil! Error() 2789 result ..= 'Ca' 2790 enddef 2791 2792 Crash() 2793 assert_equal('CbEbEaCa', result) 2794 END 2795 CheckScriptSuccess(lines) 2796enddef 2797 2798def Test_dict_member_with_silent() 2799 var lines =<< trim END 2800 vim9script 2801 g:result = 'none' 2802 var d: dict<any> 2803 def Func() 2804 try 2805 g:result = map([], (_, v) => ({}[v]))->join() .. d[''] 2806 catch 2807 endtry 2808 enddef 2809 silent! Func() 2810 assert_equal('0', g:result) 2811 unlet g:result 2812 END 2813 CheckScriptSuccess(lines) 2814enddef 2815 2816def Test_skip_cmds_with_silent() 2817 var lines =<< trim END 2818 vim9script 2819 2820 def Func(b: bool) 2821 Crash() 2822 enddef 2823 2824 def Crash() 2825 sil! :/not found/d _ 2826 sil! :/not found/put _ 2827 enddef 2828 2829 Func(true) 2830 END 2831 CheckScriptSuccess(lines) 2832enddef 2833 2834def Test_opfunc() 2835 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@ 2836 def g:Opfunc(_: any): string 2837 setline(1, 'ASDF') 2838 return '' 2839 enddef 2840 new 2841 setline(1, 'asdf') 2842 feedkeys("\<F3>$", 'x') 2843 assert_equal('ASDF', getline(1)) 2844 2845 bwipe! 2846 nunmap <F3> 2847enddef 2848 2849" this was crashing on exit 2850def Test_nested_lambda_in_closure() 2851 var lines =<< trim END 2852 vim9script 2853 command WriteDone writefile(['Done'], 'XnestedDone') 2854 def Outer() 2855 def g:Inner() 2856 echo map([1, 2, 3], {_, v -> v + 1}) 2857 enddef 2858 g:Inner() 2859 enddef 2860 defcompile 2861 # not reached 2862 END 2863 if !RunVim([], lines, '--clean -c WriteDone -c quit') 2864 return 2865 endif 2866 assert_equal(['Done'], readfile('XnestedDone')) 2867 delete('XnestedDone') 2868enddef 2869 2870def Test_check_func_arg_types() 2871 var lines =<< trim END 2872 vim9script 2873 def F1(x: string): string 2874 return x 2875 enddef 2876 2877 def F2(x: number): number 2878 return x + 1 2879 enddef 2880 2881 def G(g: func): dict<func> 2882 return {f: g} 2883 enddef 2884 2885 def H(d: dict<func>): string 2886 return d.f('a') 2887 enddef 2888 END 2889 2890 CheckScriptSuccess(lines + ['echo H(G(F1))']) 2891 CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:') 2892enddef 2893 2894def Test_compile_error() 2895 var lines =<< trim END 2896 def g:Broken() 2897 echo 'a' + {} 2898 enddef 2899 call g:Broken() 2900 END 2901 # First call: compilation error 2902 CheckScriptFailure(lines, 'E1051: Wrong argument type for +') 2903 2904 # Second call won't try compiling again 2905 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2906 delfunc g:Broken 2907 2908 # No error when compiling with :silent! 2909 lines =<< trim END 2910 def g:Broken() 2911 echo 'a' + [] 2912 enddef 2913 silent! defcompile 2914 END 2915 CheckScriptSuccess(lines) 2916 2917 # Calling the function won't try compiling again 2918 assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken') 2919 delfunc g:Broken 2920enddef 2921 2922def Test_ignored_argument() 2923 var lines =<< trim END 2924 vim9script 2925 def Ignore(_, _): string 2926 return 'yes' 2927 enddef 2928 assert_equal('yes', Ignore(1, 2)) 2929 2930 func Ok(_) 2931 return a:_ 2932 endfunc 2933 assert_equal('ok', Ok('ok')) 2934 2935 func Oktoo() 2936 let _ = 'too' 2937 return _ 2938 endfunc 2939 assert_equal('too', Oktoo()) 2940 2941 assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1))) 2942 END 2943 CheckScriptSuccess(lines) 2944 2945 lines =<< trim END 2946 def Ignore(_: string): string 2947 return _ 2948 enddef 2949 defcompile 2950 END 2951 CheckScriptFailure(lines, 'E1181:', 1) 2952 2953 lines =<< trim END 2954 var _ = 1 2955 END 2956 CheckDefAndScriptFailure(lines, 'E1181:', 1) 2957 2958 lines =<< trim END 2959 var x = _ 2960 END 2961 CheckDefAndScriptFailure(lines, 'E1181:', 1) 2962enddef 2963 2964def Test_too_many_arguments() 2965 var lines =<< trim END 2966 echo [0, 1, 2]->map(() => 123) 2967 END 2968 CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1) 2969 2970 lines =<< trim END 2971 echo [0, 1, 2]->map((_) => 123) 2972 END 2973 CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1) 2974enddef 2975 2976def Test_closing_brace_at_start_of_line() 2977 var lines =<< trim END 2978 def Func() 2979 enddef 2980 Func( 2981 ) 2982 END 2983 call CheckDefAndScriptSuccess(lines) 2984enddef 2985 2986if has('python3') 2987 def Test_python3_heredoc() 2988 py3 << trim EOF 2989 import vim 2990 vim.vars['didit'] = 'yes' 2991 EOF 2992 assert_equal('yes', g:didit) 2993 2994 python3 << trim EOF 2995 import vim 2996 vim.vars['didit'] = 'again' 2997 EOF 2998 assert_equal('again', g:didit) 2999 enddef 3000endif 3001 3002" This messes up syntax highlight, keep near the end. 3003if has('lua') 3004 def Test_lua_heredoc() 3005 g:d = {} 3006 lua << trim EOF 3007 x = vim.eval('g:d') 3008 x['key'] = 'val' 3009 EOF 3010 assert_equal('val', g:d.key) 3011 enddef 3012endif 3013 3014 3015" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 3016