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