1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source view_util.vim 5source vim9.vim 6source screendump.vim 7 8func Test_def_basic() 9 def SomeFunc(): string 10 return 'yes' 11 enddef 12 call assert_equal('yes', SomeFunc()) 13endfunc 14 15def ReturnString(): string 16 return 'string' 17enddef 18 19def ReturnNumber(): number 20 return 123 21enddef 22 23let g:notNumber = 'string' 24 25def ReturnGlobal(): number 26 return g:notNumber 27enddef 28 29def Test_return_something() 30 assert_equal('string', ReturnString()) 31 assert_equal(123, ReturnNumber()) 32 assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string') 33enddef 34 35def Test_missing_return() 36 CheckDefFailure(['def Missing(): number', 37 ' if g:cond', 38 ' echo "no return"', 39 ' else', 40 ' return 0', 41 ' endif' 42 'enddef'], 'E1027:') 43 CheckDefFailure(['def Missing(): number', 44 ' if g:cond', 45 ' return 1', 46 ' else', 47 ' echo "no return"', 48 ' endif' 49 'enddef'], 'E1027:') 50 CheckDefFailure(['def Missing(): number', 51 ' if g:cond', 52 ' return 1', 53 ' else', 54 ' return 2', 55 ' endif' 56 ' return 3' 57 'enddef'], 'E1095:') 58enddef 59 60let s:nothing = 0 61def ReturnNothing() 62 s:nothing = 1 63 if true 64 return 65 endif 66 s:nothing = 2 67enddef 68 69def Test_return_nothing() 70 ReturnNothing() 71 assert_equal(1, s:nothing) 72enddef 73 74func Increment() 75 let g:counter += 1 76endfunc 77 78def Test_call_ufunc_count() 79 g:counter = 1 80 Increment() 81 Increment() 82 Increment() 83 # works with and without :call 84 assert_equal(4, g:counter) 85 call assert_equal(4, g:counter) 86 unlet g:counter 87enddef 88 89def MyVarargs(arg: string, ...rest: list<string>): string 90 let res = arg 91 for s in rest 92 res ..= ',' .. s 93 endfor 94 return res 95enddef 96 97def Test_call_varargs() 98 assert_equal('one', MyVarargs('one')) 99 assert_equal('one,two', MyVarargs('one', 'two')) 100 assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) 101enddef 102 103def MyDefaultArgs(name = 'string'): string 104 return name 105enddef 106 107def MyDefaultSecond(name: string, second: bool = true): string 108 return second ? name : 'none' 109enddef 110 111def Test_call_default_args() 112 assert_equal('string', MyDefaultArgs()) 113 assert_equal('one', MyDefaultArgs('one')) 114 assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 115 116 assert_equal('test', MyDefaultSecond('test')) 117 assert_equal('test', MyDefaultSecond('test', true)) 118 assert_equal('none', MyDefaultSecond('test', false)) 119 120 CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:') 121 CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: argument 1: type mismatch, expected number but got string') 122enddef 123 124def Test_nested_function() 125 def Nested(arg: string): string 126 return 'nested ' .. arg 127 enddef 128 assert_equal('nested function', Nested('function')) 129 130 CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:') 131 CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:') 132 133 CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') 134 CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:') 135 CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:') 136enddef 137 138func Test_call_default_args_from_func() 139 call assert_equal('string', MyDefaultArgs()) 140 call assert_equal('one', MyDefaultArgs('one')) 141 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 142endfunc 143 144def Test_nested_global_function() 145 let lines =<< trim END 146 vim9script 147 def Outer() 148 def g:Inner(): string 149 return 'inner' 150 enddef 151 enddef 152 defcompile 153 Outer() 154 assert_equal('inner', g:Inner()) 155 delfunc g:Inner 156 Outer() 157 assert_equal('inner', g:Inner()) 158 delfunc g:Inner 159 Outer() 160 assert_equal('inner', g:Inner()) 161 delfunc g:Inner 162 END 163 CheckScriptSuccess(lines) 164 165 lines =<< trim END 166 vim9script 167 def Outer() 168 def g:Inner(): string 169 return 'inner' 170 enddef 171 enddef 172 defcompile 173 Outer() 174 Outer() 175 END 176 CheckScriptFailure(lines, "E122:") 177 178 lines =<< trim END 179 vim9script 180 def Func() 181 echo 'script' 182 enddef 183 def Outer() 184 def Func() 185 echo 'inner' 186 enddef 187 enddef 188 defcompile 189 END 190 CheckScriptFailure(lines, "E1073:") 191enddef 192 193def Test_global_local_function() 194 let lines =<< trim END 195 vim9script 196 def g:Func(): string 197 return 'global' 198 enddef 199 def Func(): string 200 return 'local' 201 enddef 202 assert_equal('global', g:Func()) 203 assert_equal('local', Func()) 204 END 205 CheckScriptSuccess(lines) 206 207 lines =<< trim END 208 vim9script 209 def g:Funcy() 210 echo 'funcy' 211 enddef 212 s:Funcy() 213 END 214 CheckScriptFailure(lines, 'E117:') 215enddef 216 217func TakesOneArg(arg) 218 echo a:arg 219endfunc 220 221def Test_call_wrong_args() 222 call CheckDefFailure(['TakesOneArg()'], 'E119:') 223 call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') 224 call CheckDefFailure(['bufnr(xxx)'], 'E1001:') 225 call CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:') 226enddef 227 228" Default arg and varargs 229def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 230 let res = one .. ',' .. two 231 for s in rest 232 res ..= ',' .. s 233 endfor 234 return res 235enddef 236 237def Test_call_def_varargs() 238 call assert_fails('call MyDefVarargs()', 'E119:') 239 assert_equal('one,foo', MyDefVarargs('one')) 240 assert_equal('one,two', MyDefVarargs('one', 'two')) 241 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) 242 CheckDefFailure(['MyDefVarargs("one", 22)'], 243 'E1013: argument 2: type mismatch, expected string but got number') 244 CheckDefFailure(['MyDefVarargs("one", "two", 123)'], 245 'E1013: argument 3: type mismatch, expected string but got number') 246 247 let lines =<< trim END 248 vim9script 249 def Func(...l: list<string>) 250 echo l 251 enddef 252 Func('a', 'b', 'c') 253 END 254 CheckScriptSuccess(lines) 255 256 lines =<< trim END 257 vim9script 258 def Func(...l: list<string>) 259 echo l 260 enddef 261 Func() 262 END 263 CheckScriptSuccess(lines) 264 265 lines =<< trim END 266 vim9script 267 def Func(...l: list<string>) 268 echo l 269 enddef 270 Func(1, 2, 3) 271 END 272 CheckScriptFailure(lines, 'E1013:') 273 274 lines =<< trim END 275 vim9script 276 def Func(...l: list<string>) 277 echo l 278 enddef 279 Func('a', 9) 280 END 281 CheckScriptFailure(lines, 'E1013:') 282 283 lines =<< trim END 284 vim9script 285 def Func(...l: list<string>) 286 echo l 287 enddef 288 Func(1, 'a') 289 END 290 CheckScriptFailure(lines, 'E1013:') 291enddef 292 293def Test_call_call() 294 let l = [3, 2, 1] 295 call('reverse', [l]) 296 assert_equal([1, 2, 3], l) 297enddef 298 299let s:value = '' 300 301def FuncOneDefArg(opt = 'text') 302 s:value = opt 303enddef 304 305def FuncTwoDefArg(nr = 123, opt = 'text'): string 306 return nr .. opt 307enddef 308 309def FuncVarargs(...arg: list<string>): string 310 return join(arg, ',') 311enddef 312 313def Test_func_type_varargs() 314 let RefDefArg: func(?string) 315 RefDefArg = FuncOneDefArg 316 RefDefArg() 317 assert_equal('text', s:value) 318 RefDefArg('some') 319 assert_equal('some', s:value) 320 321 let RefDef2Arg: func(?number, ?string): string 322 RefDef2Arg = FuncTwoDefArg 323 assert_equal('123text', RefDef2Arg()) 324 assert_equal('99text', RefDef2Arg(99)) 325 assert_equal('77some', RefDef2Arg(77, 'some')) 326 327 call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:') 328 call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:') 329 330 let RefVarargs: func(...list<string>): string 331 RefVarargs = FuncVarargs 332 assert_equal('', RefVarargs()) 333 assert_equal('one', RefVarargs('one')) 334 assert_equal('one,two', RefVarargs('one', 'two')) 335 336 call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:') 337 call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:') 338enddef 339 340" Only varargs 341def MyVarargsOnly(...args: list<string>): string 342 return join(args, ',') 343enddef 344 345def Test_call_varargs_only() 346 assert_equal('', MyVarargsOnly()) 347 assert_equal('one', MyVarargsOnly('one')) 348 assert_equal('one,two', MyVarargsOnly('one', 'two')) 349 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') 350 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') 351enddef 352 353def Test_using_var_as_arg() 354 call writefile(['def Func(x: number)', 'let x = 234', 'enddef', 'defcompile'], 'Xdef') 355 call assert_fails('so Xdef', 'E1006:') 356 call delete('Xdef') 357enddef 358 359def DictArg(arg: dict<string>) 360 arg['key'] = 'value' 361enddef 362 363def ListArg(arg: list<string>) 364 arg[0] = 'value' 365enddef 366 367def Test_assign_to_argument() 368 # works for dict and list 369 let d: dict<string> = {} 370 DictArg(d) 371 assert_equal('value', d['key']) 372 let l: list<string> = [] 373 ListArg(l) 374 assert_equal('value', l[0]) 375 376 call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:') 377enddef 378 379def Test_call_func_defined_later() 380 call assert_equal('one', g:DefinedLater('one')) 381 call assert_fails('call NotDefined("one")', 'E117:') 382enddef 383 384func DefinedLater(arg) 385 return a:arg 386endfunc 387 388def Test_call_funcref() 389 assert_equal(3, g:SomeFunc('abc')) 390 assert_fails('NotAFunc()', 'E117:') # comment after call 391 assert_fails('g:NotAFunc()', 'E117:') 392 393 let lines =<< trim END 394 vim9script 395 def RetNumber(): number 396 return 123 397 enddef 398 let Funcref: func: number = function('RetNumber') 399 assert_equal(123, Funcref()) 400 END 401 CheckScriptSuccess(lines) 402 403 lines =<< trim END 404 vim9script 405 def RetNumber(): number 406 return 123 407 enddef 408 def Bar(F: func: number): number 409 return F() 410 enddef 411 let Funcref = function('RetNumber') 412 assert_equal(123, Bar(Funcref)) 413 END 414 CheckScriptSuccess(lines) 415 416 lines =<< trim END 417 vim9script 418 def UseNumber(nr: number) 419 echo nr 420 enddef 421 let Funcref: func(number) = function('UseNumber') 422 Funcref(123) 423 END 424 CheckScriptSuccess(lines) 425 426 lines =<< trim END 427 vim9script 428 def UseNumber(nr: number) 429 echo nr 430 enddef 431 let Funcref: func(string) = function('UseNumber') 432 END 433 CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)') 434 435 lines =<< trim END 436 vim9script 437 def EchoNr(nr = 34) 438 g:echo = nr 439 enddef 440 let Funcref: func(?number) = function('EchoNr') 441 Funcref() 442 assert_equal(34, g:echo) 443 Funcref(123) 444 assert_equal(123, g:echo) 445 END 446 CheckScriptSuccess(lines) 447 448 lines =<< trim END 449 vim9script 450 def EchoList(...l: list<number>) 451 g:echo = l 452 enddef 453 let Funcref: func(...list<number>) = function('EchoList') 454 Funcref() 455 assert_equal([], g:echo) 456 Funcref(1, 2, 3) 457 assert_equal([1, 2, 3], g:echo) 458 END 459 CheckScriptSuccess(lines) 460 461 lines =<< trim END 462 vim9script 463 def OptAndVar(nr: number, opt = 12, ...l: list<number>): number 464 g:optarg = opt 465 g:listarg = l 466 return nr 467 enddef 468 let Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar') 469 assert_equal(10, Funcref(10)) 470 assert_equal(12, g:optarg) 471 assert_equal([], g:listarg) 472 473 assert_equal(11, Funcref(11, 22)) 474 assert_equal(22, g:optarg) 475 assert_equal([], g:listarg) 476 477 assert_equal(17, Funcref(17, 18, 1, 2, 3)) 478 assert_equal(18, g:optarg) 479 assert_equal([1, 2, 3], g:listarg) 480 END 481 CheckScriptSuccess(lines) 482enddef 483 484let SomeFunc = function('len') 485let NotAFunc = 'text' 486 487def CombineFuncrefTypes() 488 # same arguments, different return type 489 let Ref1: func(bool): string 490 let Ref2: func(bool): number 491 let Ref3: func(bool): any 492 Ref3 = g:cond ? Ref1 : Ref2 493 494 # different number of arguments 495 let Refa1: func(bool): number 496 let Refa2: func(bool, number): number 497 let Refa3: func: number 498 Refa3 = g:cond ? Refa1 : Refa2 499 500 # different argument types 501 let Refb1: func(bool, string): number 502 let Refb2: func(string, number): number 503 let Refb3: func(any, any): number 504 Refb3 = g:cond ? Refb1 : Refb2 505enddef 506 507def FuncWithForwardCall() 508 return g:DefinedEvenLater("yes") 509enddef 510 511def DefinedEvenLater(arg: string): string 512 return arg 513enddef 514 515def Test_error_in_nested_function() 516 # Error in called function requires unwinding the call stack. 517 assert_fails('call FuncWithForwardCall()', 'E1096') 518enddef 519 520def Test_return_type_wrong() 521 CheckScriptFailure([ 522 'def Func(): number', 523 'return "a"', 524 'enddef', 525 'defcompile'], 'expected number but got string') 526 CheckScriptFailure([ 527 'def Func(): string', 528 'return 1', 529 'enddef', 530 'defcompile'], 'expected string but got number') 531 CheckScriptFailure([ 532 'def Func(): void', 533 'return "a"', 534 'enddef', 535 'defcompile'], 536 'E1096: Returning a value in a function without a return type') 537 CheckScriptFailure([ 538 'def Func()', 539 'return "a"', 540 'enddef', 541 'defcompile'], 542 'E1096: Returning a value in a function without a return type') 543 544 CheckScriptFailure([ 545 'def Func(): number', 546 'return', 547 'enddef', 548 'defcompile'], 'E1003:') 549 550 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 551 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 552 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 553 554 CheckScriptFailure([ 555 'vim9script', 556 'def FuncB()', 557 ' return 123', 558 'enddef', 559 'def FuncA()', 560 ' FuncB()', 561 'enddef', 562 'defcompile'], 'E1096:') 563enddef 564 565def Test_arg_type_wrong() 566 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 567 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 568 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 569 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 570enddef 571 572def Test_vim9script_call() 573 let lines =<< trim END 574 vim9script 575 let var = '' 576 def MyFunc(arg: string) 577 var = arg 578 enddef 579 MyFunc('foobar') 580 assert_equal('foobar', var) 581 582 let str = 'barfoo' 583 str->MyFunc() 584 assert_equal('barfoo', var) 585 586 g:value = 'value' 587 g:value->MyFunc() 588 assert_equal('value', var) 589 590 let listvar = [] 591 def ListFunc(arg: list<number>) 592 listvar = arg 593 enddef 594 [1, 2, 3]->ListFunc() 595 assert_equal([1, 2, 3], listvar) 596 597 let dictvar = {} 598 def DictFunc(arg: dict<number>) 599 dictvar = arg 600 enddef 601 {'a': 1, 'b': 2}->DictFunc() 602 assert_equal(#{a: 1, b: 2}, dictvar) 603 def CompiledDict() 604 {'a': 3, 'b': 4}->DictFunc() 605 enddef 606 CompiledDict() 607 assert_equal(#{a: 3, b: 4}, dictvar) 608 609 #{a: 3, b: 4}->DictFunc() 610 assert_equal(#{a: 3, b: 4}, dictvar) 611 612 ('text')->MyFunc() 613 assert_equal('text', var) 614 ("some")->MyFunc() 615 assert_equal('some', var) 616 617 # line starting with single quote is not a mark 618 # line starting with double quote can be a method call 619 'asdfasdf'->MyFunc() 620 assert_equal('asdfasdf', var) 621 "xyz"->MyFunc() 622 assert_equal('xyz', var) 623 624 def UseString() 625 'xyork'->MyFunc() 626 enddef 627 UseString() 628 assert_equal('xyork', var) 629 630 def UseString2() 631 "knife"->MyFunc() 632 enddef 633 UseString2() 634 assert_equal('knife', var) 635 636 # prepending a colon makes it a mark 637 new 638 setline(1, ['aaa', 'bbb', 'ccc']) 639 normal! 3Gmt1G 640 :'t 641 assert_equal(3, getcurpos()[1]) 642 bwipe! 643 644 MyFunc( 645 'continued' 646 ) 647 assert_equal('continued', 648 var 649 ) 650 651 call MyFunc( 652 'more' 653 .. 654 'lines' 655 ) 656 assert_equal( 657 'morelines', 658 var) 659 END 660 writefile(lines, 'Xcall.vim') 661 source Xcall.vim 662 delete('Xcall.vim') 663enddef 664 665def Test_vim9script_call_fail_decl() 666 let lines =<< trim END 667 vim9script 668 let var = '' 669 def MyFunc(arg: string) 670 let var = 123 671 enddef 672 defcompile 673 END 674 CheckScriptFailure(lines, 'E1054:') 675enddef 676 677def Test_vim9script_call_fail_type() 678 let lines =<< trim END 679 vim9script 680 def MyFunc(arg: string) 681 echo arg 682 enddef 683 MyFunc(1234) 684 END 685 CheckScriptFailure(lines, 'E1013: type mismatch, expected string but got number') 686enddef 687 688def Test_vim9script_call_fail_const() 689 let lines =<< trim END 690 vim9script 691 const var = '' 692 def MyFunc(arg: string) 693 var = 'asdf' 694 enddef 695 defcompile 696 END 697 writefile(lines, 'Xcall_const.vim') 698 assert_fails('source Xcall_const.vim', 'E46:') 699 delete('Xcall_const.vim') 700enddef 701 702" Test that inside :function a Python function can be defined, :def is not 703" recognized. 704func Test_function_python() 705 CheckFeature python3 706 let py = 'python3' 707 execute py "<< EOF" 708def do_something(): 709 return 1 710EOF 711endfunc 712 713def Test_delfunc() 714 let lines =<< trim END 715 vim9script 716 def g:GoneSoon() 717 echo 'hello' 718 enddef 719 720 def CallGoneSoon() 721 GoneSoon() 722 enddef 723 defcompile 724 725 delfunc g:GoneSoon 726 CallGoneSoon() 727 END 728 writefile(lines, 'XToDelFunc') 729 assert_fails('so XToDelFunc', 'E933') 730 assert_fails('so XToDelFunc', 'E933') 731 732 delete('XToDelFunc') 733enddef 734 735def Test_redef_failure() 736 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 737 so Xdef 738 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 739 so Xdef 740 call writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef') 741 call assert_fails('so Xdef', 'E1027:') 742 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 743 so Xdef 744 call delete('Xdef') 745 746 call assert_equal(0, g:Func0()) 747 call assert_equal('Func1', g:Func1()) 748 call assert_equal('Func2', g:Func2()) 749 750 delfunc! Func0 751 delfunc! Func1 752 delfunc! Func2 753enddef 754 755def Test_vim9script_func() 756 let lines =<< trim END 757 vim9script 758 func Func(arg) 759 echo a:arg 760 endfunc 761 Func('text') 762 END 763 writefile(lines, 'XVim9Func') 764 so XVim9Func 765 766 delete('XVim9Func') 767enddef 768 769" Test for internal functions returning different types 770func Test_InternalFuncRetType() 771 let lines =<< trim END 772 def RetFloat(): float 773 return ceil(1.456) 774 enddef 775 776 def RetListAny(): list<any> 777 return items({'k': 'v'}) 778 enddef 779 780 def RetListString(): list<string> 781 return split('a:b:c', ':') 782 enddef 783 784 def RetListDictAny(): list<dict<any>> 785 return getbufinfo() 786 enddef 787 788 def RetDictNumber(): dict<number> 789 return wordcount() 790 enddef 791 792 def RetDictString(): dict<string> 793 return environ() 794 enddef 795 END 796 call writefile(lines, 'Xscript') 797 source Xscript 798 799 call assert_equal(2.0, RetFloat()) 800 call assert_equal([['k', 'v']], RetListAny()) 801 call assert_equal(['a', 'b', 'c'], RetListString()) 802 call assert_notequal([], RetListDictAny()) 803 call assert_notequal({}, RetDictNumber()) 804 call assert_notequal({}, RetDictString()) 805 call delete('Xscript') 806endfunc 807 808" Test for passing too many or too few arguments to internal functions 809func Test_internalfunc_arg_error() 810 let l =<< trim END 811 def! FArgErr(): float 812 return ceil(1.1, 2) 813 enddef 814 defcompile 815 END 816 call writefile(l, 'Xinvalidarg') 817 call assert_fails('so Xinvalidarg', 'E118:') 818 let l =<< trim END 819 def! FArgErr(): float 820 return ceil() 821 enddef 822 defcompile 823 END 824 call writefile(l, 'Xinvalidarg') 825 call assert_fails('so Xinvalidarg', 'E119:') 826 call delete('Xinvalidarg') 827endfunc 828 829let s:funcResult = 0 830 831def FuncNoArgNoRet() 832 funcResult = 11 833enddef 834 835def FuncNoArgRetNumber(): number 836 funcResult = 22 837 return 1234 838enddef 839 840def FuncNoArgRetString(): string 841 funcResult = 45 842 return 'text' 843enddef 844 845def FuncOneArgNoRet(arg: number) 846 funcResult = arg 847enddef 848 849def FuncOneArgRetNumber(arg: number): number 850 funcResult = arg 851 return arg 852enddef 853 854def FuncTwoArgNoRet(one: bool, two: number) 855 funcResult = two 856enddef 857 858def FuncOneArgRetString(arg: string): string 859 return arg 860enddef 861 862def FuncOneArgRetAny(arg: any): any 863 return arg 864enddef 865 866def Test_func_type() 867 let Ref1: func() 868 funcResult = 0 869 Ref1 = FuncNoArgNoRet 870 Ref1() 871 assert_equal(11, funcResult) 872 873 let Ref2: func 874 funcResult = 0 875 Ref2 = FuncNoArgNoRet 876 Ref2() 877 assert_equal(11, funcResult) 878 879 funcResult = 0 880 Ref2 = FuncOneArgNoRet 881 Ref2(12) 882 assert_equal(12, funcResult) 883 884 funcResult = 0 885 Ref2 = FuncNoArgRetNumber 886 assert_equal(1234, Ref2()) 887 assert_equal(22, funcResult) 888 889 funcResult = 0 890 Ref2 = FuncOneArgRetNumber 891 assert_equal(13, Ref2(13)) 892 assert_equal(13, funcResult) 893enddef 894 895def Test_repeat_return_type() 896 let res = 0 897 for n in repeat([1], 3) 898 res += n 899 endfor 900 assert_equal(3, res) 901 902 res = 0 903 for n in add([1, 2], 3) 904 res += n 905 endfor 906 assert_equal(6, res) 907enddef 908 909def Test_argv_return_type() 910 next fileone filetwo 911 let res = '' 912 for name in argv() 913 res ..= name 914 endfor 915 assert_equal('fileonefiletwo', res) 916enddef 917 918def Test_func_type_part() 919 let RefVoid: func: void 920 RefVoid = FuncNoArgNoRet 921 RefVoid = FuncOneArgNoRet 922 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 923 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 924 925 let RefAny: func(): any 926 RefAny = FuncNoArgRetNumber 927 RefAny = FuncNoArgRetString 928 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 929 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 930 931 let RefNr: func: number 932 RefNr = FuncNoArgRetNumber 933 RefNr = FuncOneArgRetNumber 934 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 935 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 936 937 let RefStr: func: string 938 RefStr = FuncNoArgRetString 939 RefStr = FuncOneArgRetString 940 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 941 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 942enddef 943 944def Test_func_type_fails() 945 CheckDefFailure(['let ref1: func()'], 'E704:') 946 947 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 948 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 949 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 950 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)') 951 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)') 952 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)') 953 954 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:') 955 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:') 956 call CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E740:') 957 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:') 958enddef 959 960def Test_func_return_type() 961 let nr: number 962 nr = FuncNoArgRetNumber() 963 assert_equal(1234, nr) 964 965 nr = FuncOneArgRetAny(122) 966 assert_equal(122, nr) 967 968 let str: string 969 str = FuncOneArgRetAny('yes') 970 assert_equal('yes', str) 971 972 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 973enddef 974 975def MultiLine( 976 arg1: string, 977 arg2 = 1234, 978 ...rest: list<string> 979 ): string 980 return arg1 .. arg2 .. join(rest, '-') 981enddef 982 983def MultiLineComment( 984 arg1: string, # comment 985 arg2 = 1234, # comment 986 ...rest: list<string> # comment 987 ): string # comment 988 return arg1 .. arg2 .. join(rest, '-') 989enddef 990 991def Test_multiline() 992 assert_equal('text1234', MultiLine('text')) 993 assert_equal('text777', MultiLine('text', 777)) 994 assert_equal('text777one', MultiLine('text', 777, 'one')) 995 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 996enddef 997 998func Test_multiline_not_vim9() 999 call assert_equal('text1234', MultiLine('text')) 1000 call assert_equal('text777', MultiLine('text', 777)) 1001 call assert_equal('text777one', MultiLine('text', 777, 'one')) 1002 call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 1003endfunc 1004 1005 1006" When using CheckScriptFailure() for the below test, E1010 is generated instead 1007" of E1056. 1008func Test_E1056_1059() 1009 let caught_1056 = 0 1010 try 1011 def F(): 1012 return 1 1013 enddef 1014 catch /E1056:/ 1015 let caught_1056 = 1 1016 endtry 1017 call assert_equal(1, caught_1056) 1018 1019 let caught_1059 = 0 1020 try 1021 def F5(items : list) 1022 echo 'a' 1023 enddef 1024 catch /E1059:/ 1025 let caught_1059 = 1 1026 endtry 1027 call assert_equal(1, caught_1059) 1028endfunc 1029 1030func DelMe() 1031 echo 'DelMe' 1032endfunc 1033 1034def Test_error_reporting() 1035 # comment lines at the start of the function 1036 let lines =<< trim END 1037 " comment 1038 def Func() 1039 # comment 1040 # comment 1041 invalid 1042 enddef 1043 defcompile 1044 END 1045 call writefile(lines, 'Xdef') 1046 try 1047 source Xdef 1048 catch /E476:/ 1049 assert_match('Invalid command: invalid', v:exception) 1050 assert_match(', line 3$', v:throwpoint) 1051 endtry 1052 1053 # comment lines after the start of the function 1054 lines =<< trim END 1055 " comment 1056 def Func() 1057 let x = 1234 1058 # comment 1059 # comment 1060 invalid 1061 enddef 1062 defcompile 1063 END 1064 call writefile(lines, 'Xdef') 1065 try 1066 source Xdef 1067 catch /E476:/ 1068 assert_match('Invalid command: invalid', v:exception) 1069 assert_match(', line 4$', v:throwpoint) 1070 endtry 1071 1072 call delete('Xdef') 1073enddef 1074 1075def Test_deleted_function() 1076 CheckDefExecFailure([ 1077 'let RefMe: func = function("g:DelMe")', 1078 'delfunc g:DelMe', 1079 'echo RefMe()'], 'E117:') 1080enddef 1081 1082def Test_unknown_function() 1083 CheckDefExecFailure([ 1084 'let Ref: func = function("NotExist")', 1085 'delfunc g:NotExist'], 'E700:') 1086enddef 1087 1088def RefFunc(Ref: func(string): string): string 1089 return Ref('more') 1090enddef 1091 1092def Test_closure_simple() 1093 let local = 'some ' 1094 assert_equal('some more', RefFunc({s -> local .. s})) 1095enddef 1096 1097def MakeRef() 1098 let local = 'some ' 1099 g:Ref = {s -> local .. s} 1100enddef 1101 1102def Test_closure_ref_after_return() 1103 MakeRef() 1104 assert_equal('some thing', g:Ref('thing')) 1105 unlet g:Ref 1106enddef 1107 1108def MakeTwoRefs() 1109 let local = ['some'] 1110 g:Extend = {s -> local->add(s)} 1111 g:Read = {-> local} 1112enddef 1113 1114def Test_closure_two_refs() 1115 MakeTwoRefs() 1116 assert_equal('some', join(g:Read(), ' ')) 1117 g:Extend('more') 1118 assert_equal('some more', join(g:Read(), ' ')) 1119 g:Extend('even') 1120 assert_equal('some more even', join(g:Read(), ' ')) 1121 1122 unlet g:Extend 1123 unlet g:Read 1124enddef 1125 1126def ReadRef(Ref: func(): list<string>): string 1127 return join(Ref(), ' ') 1128enddef 1129 1130def ExtendRef(Ref: func(string), add: string) 1131 Ref(add) 1132enddef 1133 1134def Test_closure_two_indirect_refs() 1135 MakeTwoRefs() 1136 assert_equal('some', ReadRef(g:Read)) 1137 ExtendRef(g:Extend, 'more') 1138 assert_equal('some more', ReadRef(g:Read)) 1139 ExtendRef(g:Extend, 'even') 1140 assert_equal('some more even', ReadRef(g:Read)) 1141 1142 unlet g:Extend 1143 unlet g:Read 1144enddef 1145 1146def MakeArgRefs(theArg: string) 1147 let local = 'loc_val' 1148 g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s} 1149enddef 1150 1151def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 1152 let local = 'the_loc' 1153 g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)} 1154enddef 1155 1156def Test_closure_using_argument() 1157 MakeArgRefs('arg_val') 1158 assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val')) 1159 1160 MakeArgRefsVarargs('arg_val', 'one', 'two') 1161 assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val')) 1162 1163 unlet g:UseArg 1164 unlet g:UseVararg 1165enddef 1166 1167def MakeGetAndAppendRefs() 1168 let local = 'a' 1169 1170 def Append(arg: string) 1171 local ..= arg 1172 enddef 1173 g:Append = Append 1174 1175 def Get(): string 1176 return local 1177 enddef 1178 g:Get = Get 1179enddef 1180 1181def Test_closure_append_get() 1182 MakeGetAndAppendRefs() 1183 assert_equal('a', g:Get()) 1184 g:Append('-b') 1185 assert_equal('a-b', g:Get()) 1186 g:Append('-c') 1187 assert_equal('a-b-c', g:Get()) 1188 1189 unlet g:Append 1190 unlet g:Get 1191enddef 1192 1193def Test_nested_closure() 1194 let local = 'text' 1195 def Closure(arg: string): string 1196 return local .. arg 1197 enddef 1198 assert_equal('text!!!', Closure('!!!')) 1199enddef 1200 1201func GetResult(Ref) 1202 return a:Ref('some') 1203endfunc 1204 1205def Test_call_closure_not_compiled() 1206 let text = 'text' 1207 g:Ref = {s -> s .. text} 1208 assert_equal('sometext', GetResult(g:Ref)) 1209enddef 1210 1211def Test_sort_return_type() 1212 let res: list<number> 1213 res = [1, 2, 3]->sort() 1214enddef 1215 1216def Test_getqflist_return_type() 1217 let l = getqflist() 1218 assert_equal([], l) 1219 1220 let d = getqflist(#{items: 0}) 1221 assert_equal(#{items: []}, d) 1222enddef 1223 1224def Test_getloclist_return_type() 1225 let l = getloclist(1) 1226 assert_equal([], l) 1227 1228 let d = getloclist(1, #{items: 0}) 1229 assert_equal(#{items: []}, d) 1230enddef 1231 1232def Test_copy_return_type() 1233 let l = copy([1, 2, 3]) 1234 let res = 0 1235 for n in l 1236 res += n 1237 endfor 1238 assert_equal(6, res) 1239 1240 let dl = deepcopy([1, 2, 3]) 1241 res = 0 1242 for n in dl 1243 res += n 1244 endfor 1245 assert_equal(6, res) 1246enddef 1247 1248def Test_extend_return_type() 1249 let l = extend([1, 2], [3]) 1250 let res = 0 1251 for n in l 1252 res += n 1253 endfor 1254 assert_equal(6, res) 1255enddef 1256 1257def Test_insert_return_type() 1258 let l = insert([2, 1], 3) 1259 let res = 0 1260 for n in l 1261 res += n 1262 endfor 1263 assert_equal(6, res) 1264enddef 1265 1266def Test_reverse_return_type() 1267 let l = reverse([1, 2, 3]) 1268 let res = 0 1269 for n in l 1270 res += n 1271 endfor 1272 assert_equal(6, res) 1273enddef 1274 1275def Test_remove_return_type() 1276 let l = remove(#{one: [1, 2], two: [3, 4]}, 'one') 1277 let res = 0 1278 for n in l 1279 res += n 1280 endfor 1281 assert_equal(3, res) 1282enddef 1283 1284def Test_filter_return_type() 1285 let l = filter([1, 2, 3], {-> 1}) 1286 let res = 0 1287 for n in l 1288 res += n 1289 endfor 1290 assert_equal(6, res) 1291enddef 1292 1293def Test_getreg_return_type() 1294 let s1: string = getreg('"') 1295 let s2: string = getreg('"', 1) 1296 let s3: list<string> = getreg('"', 1, 1) 1297enddef 1298 1299def Wrong_dict_key_type(items: list<number>): list<number> 1300 return filter(items, {_, val -> get({val: 1}, 'x')}) 1301enddef 1302 1303def Test_wrong_dict_key_type() 1304 assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1029:') 1305enddef 1306 1307def Line_continuation_in_def(dir: string = ''): string 1308 let path: string = empty(dir) 1309 \ ? 'empty' 1310 \ : 'full' 1311 return path 1312enddef 1313 1314def Test_line_continuation_in_def() 1315 assert_equal('full', Line_continuation_in_def('.')) 1316enddef 1317 1318def Line_continuation_in_lambda(): list<number> 1319 let x = range(97, 100) 1320 ->map({_, v -> nr2char(v) 1321 ->toupper()}) 1322 ->reverse() 1323 return x 1324enddef 1325 1326def Test_line_continuation_in_lambda() 1327 assert_equal(['D', 'C', 'B', 'A'], Line_continuation_in_lambda()) 1328enddef 1329 1330func Test_silent_echo() 1331 CheckScreendump 1332 1333 let lines =<< trim END 1334 vim9script 1335 def EchoNothing() 1336 silent echo '' 1337 enddef 1338 defcompile 1339 END 1340 call writefile(lines, 'XTest_silent_echo') 1341 1342 " Check that the balloon shows up after a mouse move 1343 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 1344 call term_sendkeys(buf, ":abc") 1345 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 1346 1347 " clean up 1348 call StopVimInTerminal(buf) 1349 call delete('XTest_silent_echo') 1350endfunc 1351 1352def Fibonacci(n: number): number 1353 if n < 2 1354 return n 1355 else 1356 return Fibonacci(n - 1) + Fibonacci(n - 2) 1357 endif 1358enddef 1359 1360def Test_recursive_call() 1361 assert_equal(6765, Fibonacci(20)) 1362enddef 1363 1364def TreeWalk(dir: string): list<any> 1365 return readdir(dir)->map({_, val -> 1366 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 1367 ? {val: TreeWalk(dir .. '/' .. val)} 1368 : val 1369 }) 1370enddef 1371 1372def Test_closure_in_map() 1373 mkdir('XclosureDir/tdir', 'p') 1374 writefile(['111'], 'XclosureDir/file1') 1375 writefile(['222'], 'XclosureDir/file2') 1376 writefile(['333'], 'XclosureDir/tdir/file3') 1377 1378 assert_equal(['file1', 'file2', {'tdir': ['file3']}], TreeWalk('XclosureDir')) 1379 1380 delete('XclosureDir', 'rf') 1381enddef 1382 1383def Test_partial_call() 1384 let Xsetlist = function('setloclist', [0]) 1385 Xsetlist([], ' ', {'title': 'test'}) 1386 assert_equal({'title': 'test'}, getloclist(0, {'title': 1})) 1387 1388 Xsetlist = function('setloclist', [0, [], ' ']) 1389 Xsetlist({'title': 'test'}) 1390 assert_equal({'title': 'test'}, getloclist(0, {'title': 1})) 1391 1392 Xsetlist = function('setqflist') 1393 Xsetlist([], ' ', {'title': 'test'}) 1394 assert_equal({'title': 'test'}, getqflist({'title': 1})) 1395 1396 Xsetlist = function('setqflist', [[], ' ']) 1397 Xsetlist({'title': 'test'}) 1398 assert_equal({'title': 'test'}, getqflist({'title': 1})) 1399enddef 1400 1401def Test_cmd_modifier() 1402 tab echo '0' 1403 call CheckDefFailure(['5tab echo 3'], 'E16:') 1404enddef 1405 1406def Test_restore_modifiers() 1407 # check that when compiling a :def function command modifiers are not messed 1408 # up. 1409 let lines =<< trim END 1410 vim9script 1411 set eventignore= 1412 autocmd QuickFixCmdPost * copen 1413 def AutocmdsDisabled() 1414 eval 0 1415 enddef 1416 func Func() 1417 noautocmd call s:AutocmdsDisabled() 1418 let g:ei_after = &eventignore 1419 endfunc 1420 Func() 1421 END 1422 CheckScriptSuccess(lines) 1423 assert_equal('', g:ei_after) 1424enddef 1425 1426 1427" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 1428