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