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