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