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