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