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