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