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