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