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