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') 1025 1026 lines =<< trim END 1027 const g:Aconst = 77 1028 def Change() 1029 # comment 1030 g:Aconst = 99 1031 enddef 1032 call Change() 1033 unlet g:Aconst 1034 END 1035 CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) 1036enddef 1037 1038" Test that inside :function a Python function can be defined, :def is not 1039" recognized. 1040func Test_function_python() 1041 CheckFeature python3 1042 let py = 'python3' 1043 execute py "<< EOF" 1044def do_something(): 1045 return 1 1046EOF 1047endfunc 1048 1049def Test_delfunc() 1050 var lines =<< trim END 1051 vim9script 1052 def g:GoneSoon() 1053 echo 'hello' 1054 enddef 1055 1056 def CallGoneSoon() 1057 GoneSoon() 1058 enddef 1059 defcompile 1060 1061 delfunc g:GoneSoon 1062 CallGoneSoon() 1063 END 1064 writefile(lines, 'XToDelFunc') 1065 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1066 assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon') 1067 1068 delete('XToDelFunc') 1069enddef 1070 1071def Test_redef_failure() 1072 writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 1073 so Xdef 1074 writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 1075 so Xdef 1076 writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 1077 assert_fails('so Xdef', 'E1027:', '', 1, 'Func0') 1078 writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 1079 so Xdef 1080 delete('Xdef') 1081 1082 g:Func0()->assert_equal(0) 1083 g:Func1()->assert_equal('Func1') 1084 g:Func2()->assert_equal('Func2') 1085 1086 delfunc! Func0 1087 delfunc! Func1 1088 delfunc! Func2 1089enddef 1090 1091def Test_vim9script_func() 1092 var lines =<< trim END 1093 vim9script 1094 func Func(arg) 1095 echo a:arg 1096 endfunc 1097 Func('text') 1098 END 1099 writefile(lines, 'XVim9Func') 1100 so XVim9Func 1101 1102 delete('XVim9Func') 1103enddef 1104 1105let s:funcResult = 0 1106 1107def FuncNoArgNoRet() 1108 s:funcResult = 11 1109enddef 1110 1111def FuncNoArgRetNumber(): number 1112 s:funcResult = 22 1113 return 1234 1114enddef 1115 1116def FuncNoArgRetString(): string 1117 s:funcResult = 45 1118 return 'text' 1119enddef 1120 1121def FuncOneArgNoRet(arg: number) 1122 s:funcResult = arg 1123enddef 1124 1125def FuncOneArgRetNumber(arg: number): number 1126 s:funcResult = arg 1127 return arg 1128enddef 1129 1130def FuncTwoArgNoRet(one: bool, two: number) 1131 s:funcResult = two 1132enddef 1133 1134def FuncOneArgRetString(arg: string): string 1135 return arg 1136enddef 1137 1138def FuncOneArgRetAny(arg: any): any 1139 return arg 1140enddef 1141 1142def Test_func_type() 1143 var Ref1: func() 1144 s:funcResult = 0 1145 Ref1 = FuncNoArgNoRet 1146 Ref1() 1147 s:funcResult->assert_equal(11) 1148 1149 var Ref2: func 1150 s:funcResult = 0 1151 Ref2 = FuncNoArgNoRet 1152 Ref2() 1153 s:funcResult->assert_equal(11) 1154 1155 s:funcResult = 0 1156 Ref2 = FuncOneArgNoRet 1157 Ref2(12) 1158 s:funcResult->assert_equal(12) 1159 1160 s:funcResult = 0 1161 Ref2 = FuncNoArgRetNumber 1162 Ref2()->assert_equal(1234) 1163 s:funcResult->assert_equal(22) 1164 1165 s:funcResult = 0 1166 Ref2 = FuncOneArgRetNumber 1167 Ref2(13)->assert_equal(13) 1168 s:funcResult->assert_equal(13) 1169enddef 1170 1171def Test_repeat_return_type() 1172 var res = 0 1173 for n in repeat([1], 3) 1174 res += n 1175 endfor 1176 res->assert_equal(3) 1177 1178 res = 0 1179 for n in add([1, 2], 3) 1180 res += n 1181 endfor 1182 res->assert_equal(6) 1183enddef 1184 1185def Test_argv_return_type() 1186 next fileone filetwo 1187 var res = '' 1188 for name in argv() 1189 res ..= name 1190 endfor 1191 res->assert_equal('fileonefiletwo') 1192enddef 1193 1194def Test_func_type_part() 1195 var RefVoid: func: void 1196 RefVoid = FuncNoArgNoRet 1197 RefVoid = FuncOneArgNoRet 1198 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number') 1199 CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string') 1200 1201 var RefAny: func(): any 1202 RefAny = FuncNoArgRetNumber 1203 RefAny = FuncNoArgRetString 1204 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()') 1205 CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)') 1206 1207 var RefAnyNoArgs: func: any = RefAny 1208 1209 var RefNr: func: number 1210 RefNr = FuncNoArgRetNumber 1211 RefNr = FuncOneArgRetNumber 1212 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()') 1213 CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string') 1214 1215 var RefStr: func: string 1216 RefStr = FuncNoArgRetString 1217 RefStr = FuncOneArgRetString 1218 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()') 1219 CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number') 1220enddef 1221 1222def Test_func_type_fails() 1223 CheckDefFailure(['var ref1: func()'], 'E704:') 1224 1225 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number') 1226 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)') 1227 CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number') 1228 CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)') 1229 CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)') 1230 CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)') 1231 1232 CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:') 1233 CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:') 1234 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:') 1235 CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:') 1236enddef 1237 1238def Test_func_return_type() 1239 var nr: number 1240 nr = FuncNoArgRetNumber() 1241 nr->assert_equal(1234) 1242 1243 nr = FuncOneArgRetAny(122) 1244 nr->assert_equal(122) 1245 1246 var str: string 1247 str = FuncOneArgRetAny('yes') 1248 str->assert_equal('yes') 1249 1250 CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number') 1251enddef 1252 1253def Test_func_common_type() 1254 def FuncOne(n: number): number 1255 return n 1256 enddef 1257 def FuncTwo(s: string): number 1258 return len(s) 1259 enddef 1260 def FuncThree(n: number, s: string): number 1261 return n + len(s) 1262 enddef 1263 var list = [FuncOne, FuncTwo, FuncThree] 1264 assert_equal(8, list[0](8)) 1265 assert_equal(4, list[1]('word')) 1266 assert_equal(7, list[2](3, 'word')) 1267enddef 1268 1269def MultiLine( 1270 arg1: string, 1271 arg2 = 1234, 1272 ...rest: list<string> 1273 ): string 1274 return arg1 .. arg2 .. join(rest, '-') 1275enddef 1276 1277def MultiLineComment( 1278 arg1: string, # comment 1279 arg2 = 1234, # comment 1280 ...rest: list<string> # comment 1281 ): string # comment 1282 return arg1 .. arg2 .. join(rest, '-') 1283enddef 1284 1285def Test_multiline() 1286 MultiLine('text')->assert_equal('text1234') 1287 MultiLine('text', 777)->assert_equal('text777') 1288 MultiLine('text', 777, 'one')->assert_equal('text777one') 1289 MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1290enddef 1291 1292func Test_multiline_not_vim9() 1293 call MultiLine('text')->assert_equal('text1234') 1294 call MultiLine('text', 777)->assert_equal('text777') 1295 call MultiLine('text', 777, 'one')->assert_equal('text777one') 1296 call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two') 1297endfunc 1298 1299 1300" When using CheckScriptFailure() for the below test, E1010 is generated instead 1301" of E1056. 1302func Test_E1056_1059() 1303 let caught_1056 = 0 1304 try 1305 def F(): 1306 return 1 1307 enddef 1308 catch /E1056:/ 1309 let caught_1056 = 1 1310 endtry 1311 eval caught_1056->assert_equal(1) 1312 1313 let caught_1059 = 0 1314 try 1315 def F5(items : list) 1316 echo 'a' 1317 enddef 1318 catch /E1059:/ 1319 let caught_1059 = 1 1320 endtry 1321 eval caught_1059->assert_equal(1) 1322endfunc 1323 1324func DelMe() 1325 echo 'DelMe' 1326endfunc 1327 1328def Test_error_reporting() 1329 # comment lines at the start of the function 1330 var lines =<< trim END 1331 " comment 1332 def Func() 1333 # comment 1334 # comment 1335 invalid 1336 enddef 1337 defcompile 1338 END 1339 writefile(lines, 'Xdef') 1340 try 1341 source Xdef 1342 assert_report('should have failed') 1343 catch /E476:/ 1344 v:exception->assert_match('Invalid command: invalid') 1345 v:throwpoint->assert_match(', line 3$') 1346 endtry 1347 delfunc! g:Func 1348 1349 # comment lines after the start of the function 1350 lines =<< trim END 1351 " comment 1352 def Func() 1353 var x = 1234 1354 # comment 1355 # comment 1356 invalid 1357 enddef 1358 defcompile 1359 END 1360 writefile(lines, 'Xdef') 1361 try 1362 source Xdef 1363 assert_report('should have failed') 1364 catch /E476:/ 1365 v:exception->assert_match('Invalid command: invalid') 1366 v:throwpoint->assert_match(', line 4$') 1367 endtry 1368 delfunc! g:Func 1369 1370 lines =<< trim END 1371 vim9script 1372 def Func() 1373 var db = {foo: 1, bar: 2} 1374 # comment 1375 var x = db.asdf 1376 enddef 1377 defcompile 1378 Func() 1379 END 1380 writefile(lines, 'Xdef') 1381 try 1382 source Xdef 1383 assert_report('should have failed') 1384 catch /E716:/ 1385 v:throwpoint->assert_match('_Func, line 3$') 1386 endtry 1387 delfunc! g:Func 1388 1389 delete('Xdef') 1390enddef 1391 1392def Test_deleted_function() 1393 CheckDefExecFailure([ 1394 'var RefMe: func = function("g:DelMe")', 1395 'delfunc g:DelMe', 1396 'echo RefMe()'], 'E117:') 1397enddef 1398 1399def Test_unknown_function() 1400 CheckDefExecFailure([ 1401 'var Ref: func = function("NotExist")', 1402 'delfunc g:NotExist'], 'E700:') 1403enddef 1404 1405def RefFunc(Ref: func(string): string): string 1406 return Ref('more') 1407enddef 1408 1409def Test_closure_simple() 1410 var local = 'some ' 1411 RefFunc({s -> local .. s})->assert_equal('some more') 1412enddef 1413 1414def MakeRef() 1415 var local = 'some ' 1416 g:Ref = {s -> local .. s} 1417enddef 1418 1419def Test_closure_ref_after_return() 1420 MakeRef() 1421 g:Ref('thing')->assert_equal('some thing') 1422 unlet g:Ref 1423enddef 1424 1425def MakeTwoRefs() 1426 var local = ['some'] 1427 g:Extend = {s -> local->add(s)} 1428 g:Read = {-> local} 1429enddef 1430 1431def Test_closure_two_refs() 1432 MakeTwoRefs() 1433 join(g:Read(), ' ')->assert_equal('some') 1434 g:Extend('more') 1435 join(g:Read(), ' ')->assert_equal('some more') 1436 g:Extend('even') 1437 join(g:Read(), ' ')->assert_equal('some more even') 1438 1439 unlet g:Extend 1440 unlet g:Read 1441enddef 1442 1443def ReadRef(Ref: func(): list<string>): string 1444 return join(Ref(), ' ') 1445enddef 1446 1447def ExtendRef(Ref: func(string): list<string>, add: string) 1448 Ref(add) 1449enddef 1450 1451def Test_closure_two_indirect_refs() 1452 MakeTwoRefs() 1453 ReadRef(g:Read)->assert_equal('some') 1454 ExtendRef(g:Extend, 'more') 1455 ReadRef(g:Read)->assert_equal('some more') 1456 ExtendRef(g:Extend, 'even') 1457 ReadRef(g:Read)->assert_equal('some more even') 1458 1459 unlet g:Extend 1460 unlet g:Read 1461enddef 1462 1463def MakeArgRefs(theArg: string) 1464 var local = 'loc_val' 1465 g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s} 1466enddef 1467 1468def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 1469 var local = 'the_loc' 1470 g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)} 1471enddef 1472 1473def Test_closure_using_argument() 1474 MakeArgRefs('arg_val') 1475 g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val') 1476 1477 MakeArgRefsVarargs('arg_val', 'one', 'two') 1478 g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two') 1479 1480 unlet g:UseArg 1481 unlet g:UseVararg 1482enddef 1483 1484def MakeGetAndAppendRefs() 1485 var local = 'a' 1486 1487 def Append(arg: string) 1488 local ..= arg 1489 enddef 1490 g:Append = Append 1491 1492 def Get(): string 1493 return local 1494 enddef 1495 g:Get = Get 1496enddef 1497 1498def Test_closure_append_get() 1499 MakeGetAndAppendRefs() 1500 g:Get()->assert_equal('a') 1501 g:Append('-b') 1502 g:Get()->assert_equal('a-b') 1503 g:Append('-c') 1504 g:Get()->assert_equal('a-b-c') 1505 1506 unlet g:Append 1507 unlet g:Get 1508enddef 1509 1510def Test_nested_closure() 1511 var local = 'text' 1512 def Closure(arg: string): string 1513 return local .. arg 1514 enddef 1515 Closure('!!!')->assert_equal('text!!!') 1516enddef 1517 1518func GetResult(Ref) 1519 return a:Ref('some') 1520endfunc 1521 1522def Test_call_closure_not_compiled() 1523 var text = 'text' 1524 g:Ref = {s -> s .. text} 1525 GetResult(g:Ref)->assert_equal('sometext') 1526enddef 1527 1528def Test_double_closure_fails() 1529 var lines =<< trim END 1530 vim9script 1531 def Func() 1532 var name = 0 1533 for i in range(2) 1534 timer_start(0, {-> name}) 1535 endfor 1536 enddef 1537 Func() 1538 END 1539 CheckScriptSuccess(lines) 1540enddef 1541 1542def Test_nested_closure_used() 1543 var lines =<< trim END 1544 vim9script 1545 def Func() 1546 var x = 'hello' 1547 var Closure = {-> x} 1548 g:Myclosure = {-> Closure()} 1549 enddef 1550 Func() 1551 assert_equal('hello', g:Myclosure()) 1552 END 1553 CheckScriptSuccess(lines) 1554enddef 1555 1556def Test_nested_closure_fails() 1557 var lines =<< trim END 1558 vim9script 1559 def FuncA() 1560 FuncB(0) 1561 enddef 1562 def FuncB(n: number): list<string> 1563 return map([0], {_, v -> n}) 1564 enddef 1565 FuncA() 1566 END 1567 CheckScriptFailure(lines, 'E1012:') 1568enddef 1569 1570def Test_global_closure() 1571 var lines =<< trim END 1572 vim9script 1573 def ReverseEveryNLines(n: number, line1: number, line2: number) 1574 var mods = 'sil keepj keepp lockm ' 1575 var range = ':' .. line1 .. ',' .. line2 1576 def g:Offset(): number 1577 var offset = (line('.') - line1 + 1) % n 1578 return offset != 0 ? offset : n 1579 enddef 1580 exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()' 1581 enddef 1582 1583 new 1584 repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1) 1585 ReverseEveryNLines(3, 1, 9) 1586 END 1587 CheckScriptSuccess(lines) 1588 var expected = repeat(['ccc', 'bbb', 'aaa'], 3) 1589 assert_equal(expected, getline(1, 9)) 1590 bwipe! 1591enddef 1592 1593def Test_global_closure_called_directly() 1594 var lines =<< trim END 1595 vim9script 1596 def Outer() 1597 var x = 1 1598 def g:Inner() 1599 var y = x 1600 x += 1 1601 assert_equal(1, y) 1602 enddef 1603 g:Inner() 1604 assert_equal(2, x) 1605 enddef 1606 Outer() 1607 END 1608 CheckScriptSuccess(lines) 1609 delfunc g:Inner 1610enddef 1611 1612def Test_failure_in_called_function() 1613 # this was using the frame index as the return value 1614 var lines =<< trim END 1615 vim9script 1616 au TerminalWinOpen * eval [][0] 1617 def PopupTerm(a: any) 1618 # make sure typvals on stack are string 1619 ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join() 1620 FireEvent() 1621 enddef 1622 def FireEvent() 1623 do TerminalWinOpen 1624 enddef 1625 # use try/catch to make eval fail 1626 try 1627 call PopupTerm(0) 1628 catch 1629 endtry 1630 au! TerminalWinOpen 1631 END 1632 CheckScriptSuccess(lines) 1633enddef 1634 1635def Test_nested_lambda() 1636 var lines =<< trim END 1637 vim9script 1638 def Func() 1639 var x = 4 1640 var Lambda1 = {-> 7} 1641 var Lambda2 = {-> [Lambda1(), x]} 1642 var res = Lambda2() 1643 assert_equal([7, 4], res) 1644 enddef 1645 Func() 1646 END 1647 CheckScriptSuccess(lines) 1648enddef 1649 1650def Shadowed(): list<number> 1651 var FuncList: list<func: number> = [{ -> 42}] 1652 return FuncList->map({_, Shadowed -> Shadowed()}) 1653enddef 1654 1655def Test_lambda_arg_shadows_func() 1656 assert_equal([42], Shadowed()) 1657enddef 1658 1659def Line_continuation_in_def(dir: string = ''): string 1660 var path: string = empty(dir) 1661 \ ? 'empty' 1662 \ : 'full' 1663 return path 1664enddef 1665 1666def Test_line_continuation_in_def() 1667 Line_continuation_in_def('.')->assert_equal('full') 1668enddef 1669 1670def Test_script_var_in_lambda() 1671 var lines =<< trim END 1672 vim9script 1673 var script = 'test' 1674 assert_equal(['test'], map(['one'], {-> script})) 1675 END 1676 CheckScriptSuccess(lines) 1677enddef 1678 1679def Line_continuation_in_lambda(): list<string> 1680 var x = range(97, 100) 1681 ->map({_, v -> nr2char(v) 1682 ->toupper()}) 1683 ->reverse() 1684 return x 1685enddef 1686 1687def Test_line_continuation_in_lambda() 1688 Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A']) 1689enddef 1690 1691func Test_silent_echo() 1692 CheckScreendump 1693 1694 let lines =<< trim END 1695 vim9script 1696 def EchoNothing() 1697 silent echo '' 1698 enddef 1699 defcompile 1700 END 1701 call writefile(lines, 'XTest_silent_echo') 1702 1703 " Check that the balloon shows up after a mouse move 1704 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 1705 call term_sendkeys(buf, ":abc") 1706 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 1707 1708 " clean up 1709 call StopVimInTerminal(buf) 1710 call delete('XTest_silent_echo') 1711endfunc 1712 1713def SilentlyError() 1714 execute('silent! invalid') 1715 g:did_it = 'yes' 1716enddef 1717 1718func UserError() 1719 silent! invalid 1720endfunc 1721 1722def SilentlyUserError() 1723 UserError() 1724 g:did_it = 'yes' 1725enddef 1726 1727" This can't be a :def function, because the assert would not be reached. 1728func Test_ignore_silent_error() 1729 let g:did_it = 'no' 1730 call SilentlyError() 1731 call assert_equal('yes', g:did_it) 1732 1733 let g:did_it = 'no' 1734 call SilentlyUserError() 1735 call assert_equal('yes', g:did_it) 1736 1737 unlet g:did_it 1738endfunc 1739 1740def Test_ignore_silent_error_in_filter() 1741 var lines =<< trim END 1742 vim9script 1743 def Filter(winid: number, key: string): bool 1744 if key == 'o' 1745 silent! eval [][0] 1746 return true 1747 endif 1748 return popup_filter_menu(winid, key) 1749 enddef 1750 1751 popup_create('popup', {filter: Filter}) 1752 feedkeys("o\r", 'xnt') 1753 END 1754 CheckScriptSuccess(lines) 1755enddef 1756 1757def Fibonacci(n: number): number 1758 if n < 2 1759 return n 1760 else 1761 return Fibonacci(n - 1) + Fibonacci(n - 2) 1762 endif 1763enddef 1764 1765def Test_recursive_call() 1766 Fibonacci(20)->assert_equal(6765) 1767enddef 1768 1769def TreeWalk(dir: string): list<any> 1770 return readdir(dir)->map({_, val -> 1771 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 1772 ? {[val]: TreeWalk(dir .. '/' .. val)} 1773 : val 1774 }) 1775enddef 1776 1777def Test_closure_in_map() 1778 mkdir('XclosureDir/tdir', 'p') 1779 writefile(['111'], 'XclosureDir/file1') 1780 writefile(['222'], 'XclosureDir/file2') 1781 writefile(['333'], 'XclosureDir/tdir/file3') 1782 1783 TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}]) 1784 1785 delete('XclosureDir', 'rf') 1786enddef 1787 1788def Test_invalid_function_name() 1789 var lines =<< trim END 1790 vim9script 1791 def s: list<string> 1792 END 1793 CheckScriptFailure(lines, 'E129:') 1794 1795 lines =<< trim END 1796 vim9script 1797 def g: list<string> 1798 END 1799 CheckScriptFailure(lines, 'E129:') 1800 1801 lines =<< trim END 1802 vim9script 1803 def <SID>: list<string> 1804 END 1805 CheckScriptFailure(lines, 'E884:') 1806 1807 lines =<< trim END 1808 vim9script 1809 def F list<string> 1810 END 1811 CheckScriptFailure(lines, 'E488:') 1812enddef 1813 1814def Test_partial_call() 1815 var Xsetlist = function('setloclist', [0]) 1816 Xsetlist([], ' ', {title: 'test'}) 1817 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 1818 1819 Xsetlist = function('setloclist', [0, [], ' ']) 1820 Xsetlist({title: 'test'}) 1821 getloclist(0, {title: 1})->assert_equal({title: 'test'}) 1822 1823 Xsetlist = function('setqflist') 1824 Xsetlist([], ' ', {title: 'test'}) 1825 getqflist({title: 1})->assert_equal({title: 'test'}) 1826 1827 Xsetlist = function('setqflist', [[], ' ']) 1828 Xsetlist({title: 'test'}) 1829 getqflist({title: 1})->assert_equal({title: 'test'}) 1830 1831 var Len: func: number = function('len', ['word']) 1832 assert_equal(4, Len()) 1833enddef 1834 1835def Test_cmd_modifier() 1836 tab echo '0' 1837 CheckDefFailure(['5tab echo 3'], 'E16:') 1838enddef 1839 1840def Test_restore_modifiers() 1841 # check that when compiling a :def function command modifiers are not messed 1842 # up. 1843 var lines =<< trim END 1844 vim9script 1845 set eventignore= 1846 autocmd QuickFixCmdPost * copen 1847 def AutocmdsDisabled() 1848 eval 0 1849 enddef 1850 func Func() 1851 noautocmd call s:AutocmdsDisabled() 1852 let g:ei_after = &eventignore 1853 endfunc 1854 Func() 1855 END 1856 CheckScriptSuccess(lines) 1857 g:ei_after->assert_equal('') 1858enddef 1859 1860def StackTop() 1861 eval 1 1862 eval 2 1863 # call not on fourth line 1864 StackBot() 1865enddef 1866 1867def StackBot() 1868 # throw an error 1869 eval [][0] 1870enddef 1871 1872def Test_callstack_def() 1873 try 1874 StackTop() 1875 catch 1876 v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2') 1877 endtry 1878enddef 1879 1880" Re-using spot for variable used in block 1881def Test_block_scoped_var() 1882 var lines =<< trim END 1883 vim9script 1884 def Func() 1885 var x = ['a', 'b', 'c'] 1886 if 1 1887 var y = 'x' 1888 map(x, {-> y}) 1889 endif 1890 var z = x 1891 assert_equal(['x', 'x', 'x'], z) 1892 enddef 1893 Func() 1894 END 1895 CheckScriptSuccess(lines) 1896enddef 1897 1898def Test_reset_did_emsg() 1899 var lines =<< trim END 1900 @s = 'blah' 1901 au BufWinLeave * # 1902 def Func() 1903 var winid = popup_create('popup', {}) 1904 exe '*s' 1905 popup_close(winid) 1906 enddef 1907 Func() 1908 END 1909 CheckScriptFailure(lines, 'E492:', 8) 1910 delfunc! g:Func 1911enddef 1912 1913def Test_did_emsg_reset() 1914 # executing an autocommand resets did_emsg, this should not result in a 1915 # builtin function considered failing 1916 var lines =<< trim END 1917 vim9script 1918 au BufWinLeave * # 1919 def Func() 1920 popup_menu('', {callback: {-> popup_create('', {})->popup_close()}}) 1921 eval [][0] 1922 enddef 1923 nno <F3> <cmd>call <sid>Func()<cr> 1924 feedkeys("\<F3>\e", 'xt') 1925 END 1926 writefile(lines, 'XemsgReset') 1927 assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2) 1928 delete('XemsgReset') 1929 nunmap <F3> 1930 au! BufWinLeave 1931enddef 1932 1933def Test_abort_with_silent_call() 1934 var lines =<< trim END 1935 vim9script 1936 g:result = 'none' 1937 def Func() 1938 g:result += 3 1939 g:result = 'yes' 1940 enddef 1941 # error is silenced, but function aborts on error 1942 silent! Func() 1943 assert_equal('none', g:result) 1944 unlet g:result 1945 END 1946 CheckScriptSuccess(lines) 1947enddef 1948 1949def Test_continues_with_silent_error() 1950 var lines =<< trim END 1951 vim9script 1952 g:result = 'none' 1953 def Func() 1954 silent! g:result += 3 1955 g:result = 'yes' 1956 enddef 1957 # error is silenced, function does not abort 1958 Func() 1959 assert_equal('yes', g:result) 1960 unlet g:result 1961 END 1962 CheckScriptSuccess(lines) 1963enddef 1964 1965def Test_abort_even_with_silent() 1966 var lines =<< trim END 1967 vim9script 1968 g:result = 'none' 1969 def Func() 1970 eval {-> ''}() .. '' .. {}['X'] 1971 g:result = 'yes' 1972 enddef 1973 silent! Func() 1974 assert_equal('none', g:result) 1975 unlet g:result 1976 END 1977 CheckScriptSuccess(lines) 1978enddef 1979 1980def Test_cmdmod_silent_restored() 1981 var lines =<< trim END 1982 vim9script 1983 def Func() 1984 g:result = 'none' 1985 silent! g:result += 3 1986 g:result = 'none' 1987 g:result += 3 1988 enddef 1989 Func() 1990 END 1991 # can't use CheckScriptFailure, it ignores the :silent! 1992 var fname = 'Xdefsilent' 1993 writefile(lines, fname) 1994 var caught = 'no' 1995 try 1996 exe 'source ' .. fname 1997 catch /E1030:/ 1998 caught = 'yes' 1999 assert_match('Func, line 4', v:throwpoint) 2000 endtry 2001 assert_equal('yes', caught) 2002 delete(fname) 2003enddef 2004 2005def Test_dict_member_with_silent() 2006 var lines =<< trim END 2007 vim9script 2008 g:result = 'none' 2009 var d: dict<any> 2010 def Func() 2011 try 2012 g:result = map([], {_, v -> {}[v]})->join() .. d[''] 2013 catch 2014 endtry 2015 enddef 2016 silent! Func() 2017 assert_equal('0', g:result) 2018 unlet g:result 2019 END 2020 CheckScriptSuccess(lines) 2021enddef 2022 2023def Test_opfunc() 2024 nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@ 2025 def g:Opfunc(_: any): string 2026 setline(1, 'ASDF') 2027 return '' 2028 enddef 2029 new 2030 setline(1, 'asdf') 2031 feedkeys("\<F3>$", 'x') 2032 assert_equal('ASDF', getline(1)) 2033 2034 bwipe! 2035 nunmap <F3> 2036enddef 2037 2038" this was crashing on exit 2039def Test_nested_lambda_in_closure() 2040 var lines =<< trim END 2041 vim9script 2042 def Outer() 2043 def g:Inner() 2044 echo map([1, 2, 3], {_, v -> v + 1}) 2045 enddef 2046 g:Inner() 2047 enddef 2048 defcompile 2049 writefile(['Done'], 'XnestedDone') 2050 quit 2051 END 2052 if !RunVim([], lines, '--clean') 2053 return 2054 endif 2055 assert_equal(['Done'], readfile('XnestedDone')) 2056 delete('XnestedDone') 2057enddef 2058 2059 2060 2061" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 2062