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