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, 'E1012:') 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, 'E1012:') 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, 'E1012:') 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, 'E1012: 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, 'E1012: 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'], 'E1012: type mismatch, expected func() but got func(): number') 923 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: 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'], 'E1012: type mismatch, expected func(): any but got func()') 929 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: 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'], 'E1012: type mismatch, expected func(): number but got func()') 935 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: 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'], 'E1012: type mismatch, expected func(): string but got func()') 941 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: 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'], 'E1012: type mismatch, expected func() but got func(): number') 948 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: type mismatch, expected func() but got func(number)') 949 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: type mismatch, expected func() but got func(number): number') 950 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: type mismatch, expected func(bool) but got func(bool, number)') 951 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: type mismatch, expected func(?bool) but got func(bool, number)') 952 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: 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)'], 'E1005:') 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()'], 'E1012: 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 assert_report('should have failed') 1049 catch /E476:/ 1050 assert_match('Invalid command: invalid', v:exception) 1051 assert_match(', line 3$', v:throwpoint) 1052 endtry 1053 1054 # comment lines after the start of the function 1055 lines =<< trim END 1056 " comment 1057 def Func() 1058 let x = 1234 1059 # comment 1060 # comment 1061 invalid 1062 enddef 1063 defcompile 1064 END 1065 call writefile(lines, 'Xdef') 1066 try 1067 source Xdef 1068 assert_report('should have failed') 1069 catch /E476:/ 1070 assert_match('Invalid command: invalid', v:exception) 1071 assert_match(', line 4$', v:throwpoint) 1072 endtry 1073 1074 lines =<< trim END 1075 vim9script 1076 def Func() 1077 let db = #{foo: 1, bar: 2} 1078 # comment 1079 let x = db.asdf 1080 enddef 1081 defcompile 1082 Func() 1083 END 1084 call writefile(lines, 'Xdef') 1085 try 1086 source Xdef 1087 assert_report('should have failed') 1088 catch /E716:/ 1089 assert_match('_Func, line 3$', v:throwpoint) 1090 endtry 1091 1092 call delete('Xdef') 1093enddef 1094 1095def Test_deleted_function() 1096 CheckDefExecFailure([ 1097 'let RefMe: func = function("g:DelMe")', 1098 'delfunc g:DelMe', 1099 'echo RefMe()'], 'E117:') 1100enddef 1101 1102def Test_unknown_function() 1103 CheckDefExecFailure([ 1104 'let Ref: func = function("NotExist")', 1105 'delfunc g:NotExist'], 'E700:') 1106enddef 1107 1108def RefFunc(Ref: func(string): string): string 1109 return Ref('more') 1110enddef 1111 1112def Test_closure_simple() 1113 let local = 'some ' 1114 assert_equal('some more', RefFunc({s -> local .. s})) 1115enddef 1116 1117def MakeRef() 1118 let local = 'some ' 1119 g:Ref = {s -> local .. s} 1120enddef 1121 1122def Test_closure_ref_after_return() 1123 MakeRef() 1124 assert_equal('some thing', g:Ref('thing')) 1125 unlet g:Ref 1126enddef 1127 1128def MakeTwoRefs() 1129 let local = ['some'] 1130 g:Extend = {s -> local->add(s)} 1131 g:Read = {-> local} 1132enddef 1133 1134def Test_closure_two_refs() 1135 MakeTwoRefs() 1136 assert_equal('some', join(g:Read(), ' ')) 1137 g:Extend('more') 1138 assert_equal('some more', join(g:Read(), ' ')) 1139 g:Extend('even') 1140 assert_equal('some more even', join(g:Read(), ' ')) 1141 1142 unlet g:Extend 1143 unlet g:Read 1144enddef 1145 1146def ReadRef(Ref: func(): list<string>): string 1147 return join(Ref(), ' ') 1148enddef 1149 1150def ExtendRef(Ref: func(string), add: string) 1151 Ref(add) 1152enddef 1153 1154def Test_closure_two_indirect_refs() 1155 MakeTwoRefs() 1156 assert_equal('some', ReadRef(g:Read)) 1157 ExtendRef(g:Extend, 'more') 1158 assert_equal('some more', ReadRef(g:Read)) 1159 ExtendRef(g:Extend, 'even') 1160 assert_equal('some more even', ReadRef(g:Read)) 1161 1162 unlet g:Extend 1163 unlet g:Read 1164enddef 1165 1166def MakeArgRefs(theArg: string) 1167 let local = 'loc_val' 1168 g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s} 1169enddef 1170 1171def MakeArgRefsVarargs(theArg: string, ...rest: list<string>) 1172 let local = 'the_loc' 1173 g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)} 1174enddef 1175 1176def Test_closure_using_argument() 1177 MakeArgRefs('arg_val') 1178 assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val')) 1179 1180 MakeArgRefsVarargs('arg_val', 'one', 'two') 1181 assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val')) 1182 1183 unlet g:UseArg 1184 unlet g:UseVararg 1185enddef 1186 1187def MakeGetAndAppendRefs() 1188 let local = 'a' 1189 1190 def Append(arg: string) 1191 local ..= arg 1192 enddef 1193 g:Append = Append 1194 1195 def Get(): string 1196 return local 1197 enddef 1198 g:Get = Get 1199enddef 1200 1201def Test_closure_append_get() 1202 MakeGetAndAppendRefs() 1203 assert_equal('a', g:Get()) 1204 g:Append('-b') 1205 assert_equal('a-b', g:Get()) 1206 g:Append('-c') 1207 assert_equal('a-b-c', g:Get()) 1208 1209 unlet g:Append 1210 unlet g:Get 1211enddef 1212 1213def Test_nested_closure() 1214 let local = 'text' 1215 def Closure(arg: string): string 1216 return local .. arg 1217 enddef 1218 assert_equal('text!!!', Closure('!!!')) 1219enddef 1220 1221func GetResult(Ref) 1222 return a:Ref('some') 1223endfunc 1224 1225def Test_call_closure_not_compiled() 1226 let text = 'text' 1227 g:Ref = {s -> s .. text} 1228 assert_equal('sometext', GetResult(g:Ref)) 1229enddef 1230 1231def Test_sort_return_type() 1232 let res: list<number> 1233 res = [1, 2, 3]->sort() 1234enddef 1235 1236def Test_getqflist_return_type() 1237 let l = getqflist() 1238 assert_equal([], l) 1239 1240 let d = getqflist(#{items: 0}) 1241 assert_equal(#{items: []}, d) 1242enddef 1243 1244def Test_getloclist_return_type() 1245 let l = getloclist(1) 1246 assert_equal([], l) 1247 1248 let d = getloclist(1, #{items: 0}) 1249 assert_equal(#{items: []}, d) 1250enddef 1251 1252def Test_copy_return_type() 1253 let l = copy([1, 2, 3]) 1254 let res = 0 1255 for n in l 1256 res += n 1257 endfor 1258 assert_equal(6, res) 1259 1260 let dl = deepcopy([1, 2, 3]) 1261 res = 0 1262 for n in dl 1263 res += n 1264 endfor 1265 assert_equal(6, res) 1266enddef 1267 1268def Test_extend_return_type() 1269 let l = extend([1, 2], [3]) 1270 let res = 0 1271 for n in l 1272 res += n 1273 endfor 1274 assert_equal(6, res) 1275enddef 1276 1277def Test_insert_return_type() 1278 let l = insert([2, 1], 3) 1279 let res = 0 1280 for n in l 1281 res += n 1282 endfor 1283 assert_equal(6, res) 1284enddef 1285 1286def Test_keys_return_type() 1287 const var: list<string> = #{a: 1, b: 2}->keys() 1288 assert_equal(['a', 'b'], var) 1289enddef 1290 1291def Test_reverse_return_type() 1292 let l = reverse([1, 2, 3]) 1293 let res = 0 1294 for n in l 1295 res += n 1296 endfor 1297 assert_equal(6, res) 1298enddef 1299 1300def Test_remove_return_type() 1301 let l = remove(#{one: [1, 2], two: [3, 4]}, 'one') 1302 let res = 0 1303 for n in l 1304 res += n 1305 endfor 1306 assert_equal(3, res) 1307enddef 1308 1309def Test_filter_return_type() 1310 let l = filter([1, 2, 3], {-> 1}) 1311 let res = 0 1312 for n in l 1313 res += n 1314 endfor 1315 assert_equal(6, res) 1316enddef 1317 1318def Test_bufnr() 1319 let buf = bufnr() 1320 assert_equal(buf, bufnr('%')) 1321enddef 1322 1323def Test_getreg_return_type() 1324 let s1: string = getreg('"') 1325 let s2: string = getreg('"', 1) 1326 let s3: list<string> = getreg('"', 1, 1) 1327enddef 1328 1329def Wrong_dict_key_type(items: list<number>): list<number> 1330 return filter(items, {_, val -> get({val: 1}, 'x')}) 1331enddef 1332 1333def Test_wrong_dict_key_type() 1334 assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1029:') 1335enddef 1336 1337def Line_continuation_in_def(dir: string = ''): string 1338 let path: string = empty(dir) 1339 \ ? 'empty' 1340 \ : 'full' 1341 return path 1342enddef 1343 1344def Test_line_continuation_in_def() 1345 assert_equal('full', Line_continuation_in_def('.')) 1346enddef 1347 1348def Line_continuation_in_lambda(): list<number> 1349 let x = range(97, 100) 1350 ->map({_, v -> nr2char(v) 1351 ->toupper()}) 1352 ->reverse() 1353 return x 1354enddef 1355 1356def Test_line_continuation_in_lambda() 1357 assert_equal(['D', 'C', 'B', 'A'], Line_continuation_in_lambda()) 1358enddef 1359 1360func Test_silent_echo() 1361 CheckScreendump 1362 1363 let lines =<< trim END 1364 vim9script 1365 def EchoNothing() 1366 silent echo '' 1367 enddef 1368 defcompile 1369 END 1370 call writefile(lines, 'XTest_silent_echo') 1371 1372 " Check that the balloon shows up after a mouse move 1373 let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6}) 1374 call term_sendkeys(buf, ":abc") 1375 call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {}) 1376 1377 " clean up 1378 call StopVimInTerminal(buf) 1379 call delete('XTest_silent_echo') 1380endfunc 1381 1382def Test_search() 1383 new 1384 setline(1, ['foo', 'bar']) 1385 let val = 0 1386 assert_equal(2, search('bar', 'W', 0, 0, {-> val == 1})) 1387enddef 1388 1389def Test_readdir() 1390 eval expand('.')->readdir({e -> e[0] !=# '.'}) 1391 eval expand('.')->readdirex({e -> e.name[0] !=# '.'}) 1392enddef 1393 1394def Fibonacci(n: number): number 1395 if n < 2 1396 return n 1397 else 1398 return Fibonacci(n - 1) + Fibonacci(n - 2) 1399 endif 1400enddef 1401 1402def Test_recursive_call() 1403 assert_equal(6765, Fibonacci(20)) 1404enddef 1405 1406def TreeWalk(dir: string): list<any> 1407 return readdir(dir)->map({_, val -> 1408 fnamemodify(dir .. '/' .. val, ':p')->isdirectory() 1409 ? {val: TreeWalk(dir .. '/' .. val)} 1410 : val 1411 }) 1412enddef 1413 1414def Test_closure_in_map() 1415 mkdir('XclosureDir/tdir', 'p') 1416 writefile(['111'], 'XclosureDir/file1') 1417 writefile(['222'], 'XclosureDir/file2') 1418 writefile(['333'], 'XclosureDir/tdir/file3') 1419 1420 assert_equal(['file1', 'file2', {'tdir': ['file3']}], TreeWalk('XclosureDir')) 1421 1422 delete('XclosureDir', 'rf') 1423enddef 1424 1425def Test_partial_call() 1426 let Xsetlist = function('setloclist', [0]) 1427 Xsetlist([], ' ', {'title': 'test'}) 1428 assert_equal({'title': 'test'}, getloclist(0, {'title': 1})) 1429 1430 Xsetlist = function('setloclist', [0, [], ' ']) 1431 Xsetlist({'title': 'test'}) 1432 assert_equal({'title': 'test'}, getloclist(0, {'title': 1})) 1433 1434 Xsetlist = function('setqflist') 1435 Xsetlist([], ' ', {'title': 'test'}) 1436 assert_equal({'title': 'test'}, getqflist({'title': 1})) 1437 1438 Xsetlist = function('setqflist', [[], ' ']) 1439 Xsetlist({'title': 'test'}) 1440 assert_equal({'title': 'test'}, getqflist({'title': 1})) 1441enddef 1442 1443def Test_cmd_modifier() 1444 tab echo '0' 1445 call CheckDefFailure(['5tab echo 3'], 'E16:') 1446enddef 1447 1448def Test_restore_modifiers() 1449 # check that when compiling a :def function command modifiers are not messed 1450 # up. 1451 let lines =<< trim END 1452 vim9script 1453 set eventignore= 1454 autocmd QuickFixCmdPost * copen 1455 def AutocmdsDisabled() 1456 eval 0 1457 enddef 1458 func Func() 1459 noautocmd call s:AutocmdsDisabled() 1460 let g:ei_after = &eventignore 1461 endfunc 1462 Func() 1463 END 1464 CheckScriptSuccess(lines) 1465 assert_equal('', g:ei_after) 1466enddef 1467 1468 1469" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 1470