1" Test various aspects of the Vim9 script language. 2 3source check.vim 4source view_util.vim 5 6" Check that "lines" inside ":def" results in an "error" message. 7func CheckDefFailure(lines, error) 8 call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef') 9 call assert_fails('so Xdef', a:error, a:lines) 10 call delete('Xdef') 11endfunc 12 13func CheckScriptFailure(lines, error) 14 call writefile(a:lines, 'Xdef') 15 call assert_fails('so Xdef', a:error, a:lines) 16 call delete('Xdef') 17endfunc 18 19func Test_def_basic() 20 def SomeFunc(): string 21 return 'yes' 22 enddef 23 call assert_equal('yes', SomeFunc()) 24endfunc 25 26def ReturnString(): string 27 return 'string' 28enddef 29 30def ReturnNumber(): number 31 return 123 32enddef 33 34let g:notNumber = 'string' 35 36def ReturnGlobal(): number 37 return g:notNumber 38enddef 39 40def Test_return_something() 41 assert_equal('string', ReturnString()) 42 assert_equal(123, ReturnNumber()) 43 assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string') 44enddef 45 46let s:nothing = 0 47def ReturnNothing() 48 s:nothing = 1 49 if true 50 return 51 endif 52 s:nothing = 2 53enddef 54 55def Test_return_nothing() 56 ReturnNothing() 57 assert_equal(1, s:nothing) 58enddef 59 60func Increment() 61 let g:counter += 1 62endfunc 63 64def Test_call_ufunc_count() 65 g:counter = 1 66 Increment() 67 Increment() 68 Increment() 69 " works with and without :call 70 assert_equal(4, g:counter) 71 call assert_equal(4, g:counter) 72 unlet g:counter 73enddef 74 75def MyVarargs(arg: string, ...rest: list<string>): string 76 let res = arg 77 for s in rest 78 res ..= ',' .. s 79 endfor 80 return res 81enddef 82 83def Test_call_varargs() 84 assert_equal('one', MyVarargs('one')) 85 assert_equal('one,two', MyVarargs('one', 'two')) 86 assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) 87enddef 88 89def MyDefaultArgs(name = 'string'): string 90 return name 91enddef 92 93def Test_call_default_args() 94 assert_equal('string', MyDefaultArgs()) 95 assert_equal('one', MyDefaultArgs('one')) 96 assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 97 98 call CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef'], 'E1001:') 99 call CheckScriptFailure(['def Func(arg: number = "text")', 'enddef'], 'E1013: argument 1: type mismatch, expected number but got string') 100enddef 101 102func Test_call_default_args_from_func() 103 call assert_equal('string', MyDefaultArgs()) 104 call assert_equal('one', MyDefaultArgs('one')) 105 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 106endfunc 107 108func TakesOneArg(arg) 109 echo a:arg 110endfunc 111 112def Test_call_wrong_args() 113 call CheckDefFailure(['TakesOneArg()'], 'E119:') 114 call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') 115 call CheckDefFailure(['bufnr(xxx)'], 'E1001:') 116enddef 117 118" Default arg and varargs 119def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 120 let res = one .. ',' .. two 121 for s in rest 122 res ..= ',' .. s 123 endfor 124 return res 125enddef 126 127def Test_call_def_varargs() 128 call assert_fails('call MyDefVarargs()', 'E119:') 129 assert_equal('one,foo', MyDefVarargs('one')) 130 assert_equal('one,two', MyDefVarargs('one', 'two')) 131 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) 132 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number') 133enddef 134 135let s:value = '' 136 137def FuncOneDefArg(opt = 'text') 138 s:value = opt 139enddef 140 141def FuncTwoDefArg(nr = 123, opt = 'text'): string 142 return nr .. opt 143enddef 144 145def FuncVarargs(...arg: list<string>): string 146 return join(arg, ',') 147enddef 148 149def Test_func_type_varargs() 150 let RefDefArg: func(?string) 151 RefDefArg = FuncOneDefArg 152 RefDefArg() 153 assert_equal('text', s:value) 154 RefDefArg('some') 155 assert_equal('some', s:value) 156 157 let RefDef2Arg: func(?number, ?string): string 158 RefDef2Arg = FuncTwoDefArg 159 assert_equal('123text', RefDef2Arg()) 160 assert_equal('99text', RefDef2Arg(99)) 161 assert_equal('77some', RefDef2Arg(77, 'some')) 162 163 call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:') 164 call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:') 165 166 let RefVarargs: func(...list<string>): string 167 RefVarargs = FuncVarargs 168 assert_equal('', RefVarargs()) 169 assert_equal('one', RefVarargs('one')) 170 assert_equal('one,two', RefVarargs('one', 'two')) 171 172 call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:') 173 call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:') 174enddef 175 176" Only varargs 177def MyVarargsOnly(...args: list<string>): string 178 return join(args, ',') 179enddef 180 181def Test_call_varargs_only() 182 assert_equal('', MyVarargsOnly()) 183 assert_equal('one', MyVarargsOnly('one')) 184 assert_equal('one,two', MyVarargsOnly('one', 'two')) 185 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') 186 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') 187enddef 188 189def Test_using_var_as_arg() 190 call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef') 191 call assert_fails('so Xdef', 'E1006:') 192 call delete('Xdef') 193enddef 194 195def Test_call_func_defined_later() 196 call assert_equal('one', g:DefinedLater('one')) 197 call assert_fails('call NotDefined("one")', 'E117:') 198enddef 199 200func DefinedLater(arg) 201 return a:arg 202endfunc 203 204def Test_call_funcref() 205 assert_equal(3, g:SomeFunc('abc')) 206 assert_fails('NotAFunc()', 'E117:') 207 assert_fails('g:NotAFunc()', 'E117:') 208enddef 209 210let SomeFunc = function('len') 211let NotAFunc = 'text' 212 213def CombineFuncrefTypes() 214 " same arguments, different return type 215 let Ref1: func(bool): string 216 let Ref2: func(bool): number 217 let Ref3: func(bool): any 218 Ref3 = g:cond ? Ref1 : Ref2 219 220 " different number of arguments 221 let Refa1: func(bool): number 222 let Refa2: func(bool, number): number 223 let Refa3: func: number 224 Refa3 = g:cond ? Refa1 : Refa2 225 226 " different argument types 227 let Refb1: func(bool, string): number 228 let Refb2: func(string, number): number 229 let Refb3: func(any, any): number 230 Refb3 = g:cond ? Refb1 : Refb2 231enddef 232 233def FuncWithForwardCall() 234 return g:DefinedEvenLater("yes") 235enddef 236 237def DefinedEvenLater(arg: string): string 238 return arg 239enddef 240 241def Test_error_in_nested_function() 242 " Error in called function requires unwinding the call stack. 243 assert_fails('call FuncWithForwardCall()', 'E1029') 244enddef 245 246def Test_return_type_wrong() 247 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') 248 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') 249 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') 250 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') 251 252 CheckScriptFailure(['def Func(): number', 'return', 'enddef'], 'E1003:') 253 254 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 255 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 256 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 257enddef 258 259def Test_arg_type_wrong() 260 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 261 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 262 CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:') 263 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 264enddef 265 266def Test_vim9script_call() 267 let lines =<< trim END 268 vim9script 269 let var = '' 270 def MyFunc(arg: string) 271 var = arg 272 enddef 273 MyFunc('foobar') 274 assert_equal('foobar', var) 275 276 let str = 'barfoo' 277 str->MyFunc() 278 assert_equal('barfoo', var) 279 280 let g:value = 'value' 281 g:value->MyFunc() 282 assert_equal('value', var) 283 284 let listvar = [] 285 def ListFunc(arg: list<number>) 286 listvar = arg 287 enddef 288 [1, 2, 3]->ListFunc() 289 assert_equal([1, 2, 3], listvar) 290 291 let dictvar = {} 292 def DictFunc(arg: dict<number>) 293 dictvar = arg 294 enddef 295 {'a': 1, 'b': 2}->DictFunc() 296 assert_equal(#{a: 1, b: 2}, dictvar) 297 def CompiledDict() 298 {'a': 3, 'b': 4}->DictFunc() 299 enddef 300 CompiledDict() 301 assert_equal(#{a: 3, b: 4}, dictvar) 302 303 #{a: 3, b: 4}->DictFunc() 304 assert_equal(#{a: 3, b: 4}, dictvar) 305 306 ('text')->MyFunc() 307 assert_equal('text', var) 308 ("some")->MyFunc() 309 assert_equal('some', var) 310 END 311 writefile(lines, 'Xcall.vim') 312 source Xcall.vim 313 delete('Xcall.vim') 314enddef 315 316def Test_vim9script_call_fail_decl() 317 let lines =<< trim END 318 vim9script 319 let var = '' 320 def MyFunc(arg: string) 321 let var = 123 322 enddef 323 END 324 writefile(lines, 'Xcall_decl.vim') 325 assert_fails('source Xcall_decl.vim', 'E1054:') 326 delete('Xcall_decl.vim') 327enddef 328 329def Test_vim9script_call_fail_const() 330 let lines =<< trim END 331 vim9script 332 const var = '' 333 def MyFunc(arg: string) 334 var = 'asdf' 335 enddef 336 END 337 writefile(lines, 'Xcall_const.vim') 338 assert_fails('source Xcall_const.vim', 'E46:') 339 delete('Xcall_const.vim') 340enddef 341 342" Test that inside :function a Python function can be defined, :def is not 343" recognized. 344func Test_function_python() 345 CheckFeature python3 346 let py = 'python3' 347 execute py "<< EOF" 348def do_something(): 349 return 1 350EOF 351endfunc 352 353def Test_delfunc() 354 let lines =<< trim END 355 vim9script 356 def g:GoneSoon() 357 echo 'hello' 358 enddef 359 360 def CallGoneSoon() 361 GoneSoon() 362 enddef 363 364 delfunc g:GoneSoon 365 CallGoneSoon() 366 END 367 writefile(lines, 'XToDelFunc') 368 assert_fails('so XToDelFunc', 'E933') 369 assert_fails('so XToDelFunc', 'E933') 370 371 delete('XToDelFunc') 372enddef 373 374def Test_redef_failure() 375 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 376 so Xdef 377 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 378 so Xdef 379 call writefile(['def! Func0(): string', 'enddef'], 'Xdef') 380 call assert_fails('so Xdef', 'E1027:') 381 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 382 so Xdef 383 call delete('Xdef') 384 385 call assert_equal(0, g:Func0()) 386 call assert_equal('Func1', g:Func1()) 387 call assert_equal('Func2', g:Func2()) 388 389 delfunc! Func0 390 delfunc! Func1 391 delfunc! Func2 392enddef 393 394def Test_vim9script_func() 395 let lines =<< trim END 396 vim9script 397 func Func(arg) 398 echo a:arg 399 endfunc 400 Func('text') 401 END 402 writefile(lines, 'XVim9Func') 403 so XVim9Func 404 405 delete('XVim9Func') 406enddef 407 408" Test for internal functions returning different types 409func Test_InternalFuncRetType() 410 let lines =<< trim END 411 def RetFloat(): float 412 return ceil(1.456) 413 enddef 414 415 def RetListAny(): list<any> 416 return items({'k' : 'v'}) 417 enddef 418 419 def RetListString(): list<string> 420 return split('a:b:c', ':') 421 enddef 422 423 def RetListDictAny(): list<dict<any>> 424 return getbufinfo() 425 enddef 426 427 def RetDictNumber(): dict<number> 428 return wordcount() 429 enddef 430 431 def RetDictString(): dict<string> 432 return environ() 433 enddef 434 END 435 call writefile(lines, 'Xscript') 436 source Xscript 437 438 call assert_equal(2.0, RetFloat()) 439 call assert_equal([['k', 'v']], RetListAny()) 440 call assert_equal(['a', 'b', 'c'], RetListString()) 441 call assert_notequal([], RetListDictAny()) 442 call assert_notequal({}, RetDictNumber()) 443 call assert_notequal({}, RetDictString()) 444 call delete('Xscript') 445endfunc 446 447" Test for passing too many or too few arguments to internal functions 448func Test_internalfunc_arg_error() 449 let l =<< trim END 450 def! FArgErr(): float 451 return ceil(1.1, 2) 452 enddef 453 END 454 call writefile(l, 'Xinvalidarg') 455 call assert_fails('so Xinvalidarg', 'E118:') 456 let l =<< trim END 457 def! FArgErr(): float 458 return ceil() 459 enddef 460 END 461 call writefile(l, 'Xinvalidarg') 462 call assert_fails('so Xinvalidarg', 'E119:') 463 call delete('Xinvalidarg') 464endfunc 465 466let s:funcResult = 0 467 468def FuncNoArgNoRet() 469 funcResult = 11 470enddef 471 472def FuncNoArgRetNumber(): number 473 funcResult = 22 474 return 1234 475enddef 476 477def FuncNoArgRetString(): string 478 funcResult = 45 479 return 'text' 480enddef 481 482def FuncOneArgNoRet(arg: number) 483 funcResult = arg 484enddef 485 486def FuncOneArgRetNumber(arg: number): number 487 funcResult = arg 488 return arg 489enddef 490 491def FuncTwoArgNoRet(one: bool, two: number) 492 funcResult = two 493enddef 494 495def FuncOneArgRetString(arg: string): string 496 return arg 497enddef 498 499def FuncOneArgRetAny(arg: any): any 500 return arg 501enddef 502 503def Test_func_type() 504 let Ref1: func() 505 funcResult = 0 506 Ref1 = FuncNoArgNoRet 507 Ref1() 508 assert_equal(11, funcResult) 509 510 let Ref2: func 511 funcResult = 0 512 Ref2 = FuncNoArgNoRet 513 Ref2() 514 assert_equal(11, funcResult) 515 516 funcResult = 0 517 Ref2 = FuncOneArgNoRet 518 Ref2(12) 519 assert_equal(12, funcResult) 520 521 funcResult = 0 522 Ref2 = FuncNoArgRetNumber 523 assert_equal(1234, Ref2()) 524 assert_equal(22, funcResult) 525 526 funcResult = 0 527 Ref2 = FuncOneArgRetNumber 528 assert_equal(13, Ref2(13)) 529 assert_equal(13, funcResult) 530enddef 531 532def Test_func_type_part() 533 let RefVoid: func: void 534 RefVoid = FuncNoArgNoRet 535 RefVoid = FuncOneArgNoRet 536 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 537 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 538 539 let RefAny: func(): any 540 RefAny = FuncNoArgRetNumber 541 RefAny = FuncNoArgRetString 542 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 543 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 544 545 let RefNr: func: number 546 RefNr = FuncNoArgRetNumber 547 RefNr = FuncOneArgRetNumber 548 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 549 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 550 551 let RefStr: func: string 552 RefStr = FuncNoArgRetString 553 RefStr = FuncOneArgRetString 554 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 555 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 556enddef 557 558def Test_func_type_fails() 559 CheckDefFailure(['let ref1: func()'], 'E704:') 560 561 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 562 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 563 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 564 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)') 565 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)') 566 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)') 567 568 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:') 569 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:') 570 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:') 571 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:') 572enddef 573 574def Test_func_return_type() 575 let nr: number 576 nr = FuncNoArgRetNumber() 577 assert_equal(1234, nr) 578 579 nr = FuncOneArgRetAny(122) 580 assert_equal(122, nr) 581 582 let str: string 583 str = FuncOneArgRetAny('yes') 584 assert_equal('yes', str) 585 586 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 587enddef 588 589def MultiLine( 590 arg1: string, 591 arg2 = 1234, 592 ...rest: list<string> 593 ): string 594 return arg1 .. arg2 .. join(rest, '-') 595enddef 596 597def MultiLineComment( 598 arg1: string, # comment 599 arg2 = 1234, # comment 600 ...rest: list<string> # comment 601 ): string # comment 602 return arg1 .. arg2 .. join(rest, '-') 603enddef 604 605def Test_multiline() 606 assert_equal('text1234', MultiLine('text')) 607 assert_equal('text777', MultiLine('text', 777)) 608 assert_equal('text777one', MultiLine('text', 777, 'one')) 609 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 610enddef 611 612func Test_multiline_not_vim9() 613 call assert_equal('text1234', MultiLine('text')) 614 call assert_equal('text777', MultiLine('text', 777)) 615 call assert_equal('text777one', MultiLine('text', 777, 'one')) 616 call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 617endfunc 618 619 620" When using CheckScriptFailure() for the below test, E1010 is generated instead 621" of E1056. 622func Test_E1056_1059() 623 let caught_1056 = 0 624 try 625 def F(): 626 return 1 627 enddef 628 catch /E1056:/ 629 let caught_1056 = 1 630 endtry 631 call assert_equal(1, caught_1056) 632 633 let caught_1059 = 0 634 try 635 def F5(items : list) 636 echo 'a' 637 enddef 638 catch /E1059:/ 639 let caught_1059 = 1 640 endtry 641 call assert_equal(1, caught_1059) 642endfunc 643 644" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 645