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