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