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 GoneSoon() 357 echo 'hello' 358 enddef 359 360 def CallGoneSoon() 361 GoneSoon() 362 enddef 363 364 delfunc 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