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', DefinedLater('one')) 197 call assert_fails('call NotDefined("one")', 'E117:') 198enddef 199 200def CombineFuncrefTypes() 201 " same arguments, different return type 202 let Ref1: func(bool): string 203 let Ref2: func(bool): number 204 let Ref3: func(bool): any 205 Ref3 = g:cond ? Ref1 : Ref2 206 207 " different number of arguments 208 let Refa1: func(bool): number 209 let Refa2: func(bool, number): number 210 let Refa3: func: number 211 Refa3 = g:cond ? Refa1 : Refa2 212 213 " different argument types 214 let Refb1: func(bool, string): number 215 let Refb2: func(string, number): number 216 let Refb3: func(any, any): number 217 Refb3 = g:cond ? Refb1 : Refb2 218enddef 219 220func DefinedLater(arg) 221 return a:arg 222endfunc 223 224def FuncWithForwardCall() 225 return DefinedEvenLater("yes") 226enddef 227 228def DefinedEvenLater(arg: string): string 229 return arg 230enddef 231 232def Test_error_in_nested_function() 233 " Error in called function requires unwinding the call stack. 234 assert_fails('call FuncWithForwardCall()', 'E1029') 235enddef 236 237def Test_return_type_wrong() 238 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') 239 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') 240 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') 241 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') 242 243 CheckScriptFailure(['def Func(): number', 'return', 'enddef'], 'E1003:') 244 245 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 246 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 247 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 248enddef 249 250def Test_arg_type_wrong() 251 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 252 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 253 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:') 254enddef 255 256def Test_vim9script_call() 257 let lines =<< trim END 258 vim9script 259 let var = '' 260 def MyFunc(arg: string) 261 var = arg 262 enddef 263 MyFunc('foobar') 264 assert_equal('foobar', var) 265 266 let str = 'barfoo' 267 str->MyFunc() 268 assert_equal('barfoo', var) 269 270 let g:value = 'value' 271 g:value->MyFunc() 272 assert_equal('value', var) 273 274 let listvar = [] 275 def ListFunc(arg: list<number>) 276 listvar = arg 277 enddef 278 [1, 2, 3]->ListFunc() 279 assert_equal([1, 2, 3], listvar) 280 281 let dictvar = {} 282 def DictFunc(arg: dict<number>) 283 dictvar = arg 284 enddef 285 {'a': 1, 'b': 2}->DictFunc() 286 assert_equal(#{a: 1, b: 2}, dictvar) 287 def CompiledDict() 288 {'a': 3, 'b': 4}->DictFunc() 289 enddef 290 CompiledDict() 291 assert_equal(#{a: 3, b: 4}, dictvar) 292 293 #{a: 3, b: 4}->DictFunc() 294 assert_equal(#{a: 3, b: 4}, dictvar) 295 296 ('text')->MyFunc() 297 assert_equal('text', var) 298 ("some")->MyFunc() 299 assert_equal('some', var) 300 END 301 writefile(lines, 'Xcall.vim') 302 source Xcall.vim 303 delete('Xcall.vim') 304enddef 305 306def Test_vim9script_call_fail_decl() 307 let lines =<< trim END 308 vim9script 309 let var = '' 310 def MyFunc(arg: string) 311 let var = 123 312 enddef 313 END 314 writefile(lines, 'Xcall_decl.vim') 315 assert_fails('source Xcall_decl.vim', 'E1054:') 316 delete('Xcall_decl.vim') 317enddef 318 319def Test_vim9script_call_fail_const() 320 let lines =<< trim END 321 vim9script 322 const var = '' 323 def MyFunc(arg: string) 324 var = 'asdf' 325 enddef 326 END 327 writefile(lines, 'Xcall_const.vim') 328 assert_fails('source Xcall_const.vim', 'E46:') 329 delete('Xcall_const.vim') 330enddef 331 332" Test that inside :function a Python function can be defined, :def is not 333" recognized. 334func Test_function_python() 335 CheckFeature python3 336 let py = 'python3' 337 execute py "<< EOF" 338def do_something(): 339 return 1 340EOF 341endfunc 342 343def Test_delfunc() 344 let lines =<< trim END 345 vim9script 346 def GoneSoon() 347 echo 'hello' 348 enddef 349 350 def CallGoneSoon() 351 GoneSoon() 352 enddef 353 354 delfunc GoneSoon 355 CallGoneSoon() 356 END 357 writefile(lines, 'XToDelFunc') 358 assert_fails('so XToDelFunc', 'E933') 359 assert_fails('so XToDelFunc', 'E933') 360 361 delete('XToDelFunc') 362enddef 363 364def Test_redef_failure() 365 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 366 so Xdef 367 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 368 so Xdef 369 call writefile(['def! Func0(): string', 'enddef'], 'Xdef') 370 call assert_fails('so Xdef', 'E1027:') 371 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 372 so Xdef 373 call delete('Xdef') 374 375 call assert_equal(0, Func0()) 376 call assert_equal('Func1', Func1()) 377 call assert_equal('Func2', Func2()) 378 379 delfunc! Func0 380 delfunc! Func1 381 delfunc! Func2 382enddef 383 384" Test for internal functions returning different types 385func Test_InternalFuncRetType() 386 let lines =<< trim END 387 def RetFloat(): float 388 return ceil(1.456) 389 enddef 390 391 def RetListAny(): list<any> 392 return items({'k' : 'v'}) 393 enddef 394 395 def RetListString(): list<string> 396 return split('a:b:c', ':') 397 enddef 398 399 def RetListDictAny(): list<dict<any>> 400 return getbufinfo() 401 enddef 402 403 def RetDictNumber(): dict<number> 404 return wordcount() 405 enddef 406 407 def RetDictString(): dict<string> 408 return environ() 409 enddef 410 END 411 call writefile(lines, 'Xscript') 412 source Xscript 413 414 call assert_equal(2.0, RetFloat()) 415 call assert_equal([['k', 'v']], RetListAny()) 416 call assert_equal(['a', 'b', 'c'], RetListString()) 417 call assert_notequal([], RetListDictAny()) 418 call assert_notequal({}, RetDictNumber()) 419 call assert_notequal({}, RetDictString()) 420 call delete('Xscript') 421endfunc 422 423" Test for passing too many or too few arguments to internal functions 424func Test_internalfunc_arg_error() 425 let l =<< trim END 426 def! FArgErr(): float 427 return ceil(1.1, 2) 428 enddef 429 END 430 call writefile(l, 'Xinvalidarg') 431 call assert_fails('so Xinvalidarg', 'E118:') 432 let l =<< trim END 433 def! FArgErr(): float 434 return ceil() 435 enddef 436 END 437 call writefile(l, 'Xinvalidarg') 438 call assert_fails('so Xinvalidarg', 'E119:') 439 call delete('Xinvalidarg') 440endfunc 441 442let s:funcResult = 0 443 444def FuncNoArgNoRet() 445 funcResult = 11 446enddef 447 448def FuncNoArgRetNumber(): number 449 funcResult = 22 450 return 1234 451enddef 452 453def FuncNoArgRetString(): string 454 funcResult = 45 455 return 'text' 456enddef 457 458def FuncOneArgNoRet(arg: number) 459 funcResult = arg 460enddef 461 462def FuncOneArgRetNumber(arg: number): number 463 funcResult = arg 464 return arg 465enddef 466 467def FuncTwoArgNoRet(one: bool, two: number) 468 funcResult = two 469enddef 470 471def FuncOneArgRetString(arg: string): string 472 return arg 473enddef 474 475def FuncOneArgRetAny(arg: any): any 476 return arg 477enddef 478 479def Test_func_type() 480 let Ref1: func() 481 funcResult = 0 482 Ref1 = FuncNoArgNoRet 483 Ref1() 484 assert_equal(11, funcResult) 485 486 let Ref2: func 487 funcResult = 0 488 Ref2 = FuncNoArgNoRet 489 Ref2() 490 assert_equal(11, funcResult) 491 492 funcResult = 0 493 Ref2 = FuncOneArgNoRet 494 Ref2(12) 495 assert_equal(12, funcResult) 496 497 funcResult = 0 498 Ref2 = FuncNoArgRetNumber 499 assert_equal(1234, Ref2()) 500 assert_equal(22, funcResult) 501 502 funcResult = 0 503 Ref2 = FuncOneArgRetNumber 504 assert_equal(13, Ref2(13)) 505 assert_equal(13, funcResult) 506enddef 507 508def Test_func_type_part() 509 let RefVoid: func: void 510 RefVoid = FuncNoArgNoRet 511 RefVoid = FuncOneArgNoRet 512 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 513 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 514 515 let RefAny: func(): any 516 RefAny = FuncNoArgRetNumber 517 RefAny = FuncNoArgRetString 518 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 519 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 520 521 let RefNr: func: number 522 RefNr = FuncNoArgRetNumber 523 RefNr = FuncOneArgRetNumber 524 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 525 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 526 527 let RefStr: func: string 528 RefStr = FuncNoArgRetString 529 RefStr = FuncOneArgRetString 530 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 531 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 532enddef 533 534def Test_func_type_fails() 535 CheckDefFailure(['let ref1: func()'], 'E704:') 536 537 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 538 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 539 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 540 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)') 541 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)') 542 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)') 543 544 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:') 545 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:') 546 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:') 547 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:') 548enddef 549 550def Test_func_return_type() 551 let nr: number 552 nr = FuncNoArgRetNumber() 553 assert_equal(1234, nr) 554 555 nr = FuncOneArgRetAny(122) 556 assert_equal(122, nr) 557 558 let str: string 559 str = FuncOneArgRetAny('yes') 560 assert_equal('yes', str) 561 562 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 563enddef 564 565def MultiLine( 566 arg1: string, 567 arg2 = 1234, 568 ...rest: list<string> 569 ): string 570 return arg1 .. arg2 .. join(rest, '-') 571enddef 572 573def MultiLineComment( 574 arg1: string, # comment 575 arg2 = 1234, # comment 576 ...rest: list<string> # comment 577 ): string # comment 578 return arg1 .. arg2 .. join(rest, '-') 579enddef 580 581def Test_multiline() 582 assert_equal('text1234', MultiLine('text')) 583 assert_equal('text777', MultiLine('text', 777)) 584 assert_equal('text777one', MultiLine('text', 777, 'one')) 585 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 586enddef 587 588func Test_multiline_not_vim9() 589 call assert_equal('text1234', MultiLine('text')) 590 call assert_equal('text777', MultiLine('text', 777)) 591 call assert_equal('text777one', MultiLine('text', 777, 'one')) 592 call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) 593endfunc 594 595 596" When using CheckScriptFailure() for the below test, E1010 is generated instead 597" of E1056. 598func Test_E1056_1059() 599 let caught_1056 = 0 600 try 601 def F(): 602 return 1 603 enddef 604 catch /E1056:/ 605 let caught_1056 = 1 606 endtry 607 call assert_equal(1, caught_1056) 608 609 let caught_1059 = 0 610 try 611 def F5(items : list) 612 echo 'a' 613 enddef 614 catch /E1059:/ 615 let caught_1059 = 1 616 endtry 617 call assert_equal(1, caught_1059) 618endfunc 619 620" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 621