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