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