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