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