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