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