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 ...') 253enddef 254 255def Test_vim9script_call() 256 let lines =<< trim END 257 vim9script 258 let var = '' 259 def MyFunc(arg: string) 260 var = arg 261 enddef 262 MyFunc('foobar') 263 assert_equal('foobar', var) 264 265 let str = 'barfoo' 266 str->MyFunc() 267 assert_equal('barfoo', var) 268 269 let g:value = 'value' 270 g:value->MyFunc() 271 assert_equal('value', var) 272 273 let listvar = [] 274 def ListFunc(arg: list<number>) 275 listvar = arg 276 enddef 277 [1, 2, 3]->ListFunc() 278 assert_equal([1, 2, 3], listvar) 279 280 let dictvar = {} 281 def DictFunc(arg: dict<number>) 282 dictvar = arg 283 enddef 284 {'a': 1, 'b': 2}->DictFunc() 285 assert_equal(#{a: 1, b: 2}, dictvar) 286 def CompiledDict() 287 {'a': 3, 'b': 4}->DictFunc() 288 enddef 289 CompiledDict() 290 assert_equal(#{a: 3, b: 4}, dictvar) 291 292 #{a: 3, b: 4}->DictFunc() 293 assert_equal(#{a: 3, b: 4}, dictvar) 294 295 ('text')->MyFunc() 296 assert_equal('text', var) 297 ("some")->MyFunc() 298 assert_equal('some', var) 299 END 300 writefile(lines, 'Xcall.vim') 301 source Xcall.vim 302 delete('Xcall.vim') 303enddef 304 305def Test_vim9script_call_fail_decl() 306 let lines =<< trim END 307 vim9script 308 let var = '' 309 def MyFunc(arg: string) 310 let var = 123 311 enddef 312 END 313 writefile(lines, 'Xcall_decl.vim') 314 assert_fails('source Xcall_decl.vim', 'E1054:') 315 delete('Xcall_decl.vim') 316enddef 317 318def Test_vim9script_call_fail_const() 319 let lines =<< trim END 320 vim9script 321 const var = '' 322 def MyFunc(arg: string) 323 var = 'asdf' 324 enddef 325 END 326 writefile(lines, 'Xcall_const.vim') 327 assert_fails('source Xcall_const.vim', 'E46:') 328 delete('Xcall_const.vim') 329enddef 330 331" Test that inside :function a Python function can be defined, :def is not 332" recognized. 333func Test_function_python() 334 CheckFeature python3 335 let py = 'python3' 336 execute py "<< EOF" 337def do_something(): 338 return 1 339EOF 340endfunc 341 342def Test_delfunc() 343 let lines =<< trim END 344 vim9script 345 def GoneSoon() 346 echo 'hello' 347 enddef 348 349 def CallGoneSoon() 350 GoneSoon() 351 enddef 352 353 delfunc GoneSoon 354 CallGoneSoon() 355 END 356 writefile(lines, 'XToDelFunc') 357 assert_fails('so XToDelFunc', 'E933') 358 assert_fails('so XToDelFunc', 'E933') 359 360 delete('XToDelFunc') 361enddef 362 363def Test_redef_failure() 364 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 365 so Xdef 366 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 367 so Xdef 368 call writefile(['def! Func0(): string', 'enddef'], 'Xdef') 369 call assert_fails('so Xdef', 'E1027:') 370 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 371 so Xdef 372 call delete('Xdef') 373 374 call assert_equal(0, Func0()) 375 call assert_equal('Func1', Func1()) 376 call assert_equal('Func2', Func2()) 377 378 delfunc! Func0 379 delfunc! Func1 380 delfunc! Func2 381enddef 382 383" Test for internal functions returning different types 384func Test_InternalFuncRetType() 385 let lines =<< trim END 386 def RetFloat(): float 387 return ceil(1.456) 388 enddef 389 390 def RetListAny(): list<any> 391 return items({'k' : 'v'}) 392 enddef 393 394 def RetListString(): list<string> 395 return split('a:b:c', ':') 396 enddef 397 398 def RetListDictAny(): list<dict<any>> 399 return getbufinfo() 400 enddef 401 402 def RetDictNumber(): dict<number> 403 return wordcount() 404 enddef 405 406 def RetDictString(): dict<string> 407 return environ() 408 enddef 409 END 410 call writefile(lines, 'Xscript') 411 source Xscript 412 413 call assert_equal(2.0, RetFloat()) 414 call assert_equal([['k', 'v']], RetListAny()) 415 call assert_equal(['a', 'b', 'c'], RetListString()) 416 call assert_notequal([], RetListDictAny()) 417 call assert_notequal({}, RetDictNumber()) 418 call assert_notequal({}, RetDictString()) 419 call delete('Xscript') 420endfunc 421 422" Test for passing too many or too few arguments to internal functions 423func Test_internalfunc_arg_error() 424 let l =<< trim END 425 def! FArgErr(): float 426 return ceil(1.1, 2) 427 enddef 428 END 429 call writefile(l, 'Xinvalidarg') 430 call assert_fails('so Xinvalidarg', 'E118:') 431 let l =<< trim END 432 def! FArgErr(): float 433 return ceil() 434 enddef 435 END 436 call writefile(l, 'Xinvalidarg') 437 call assert_fails('so Xinvalidarg', 'E119:') 438 call delete('Xinvalidarg') 439endfunc 440 441let s:funcResult = 0 442 443def FuncNoArgNoRet() 444 funcResult = 11 445enddef 446 447def FuncNoArgRetNumber(): number 448 funcResult = 22 449 return 1234 450enddef 451 452def FuncNoArgRetString(): string 453 funcResult = 45 454 return 'text' 455enddef 456 457def FuncOneArgNoRet(arg: number) 458 funcResult = arg 459enddef 460 461def FuncOneArgRetNumber(arg: number): number 462 funcResult = arg 463 return arg 464enddef 465 466def FuncTwoArgNoRet(one: bool, two: number) 467 funcResult = two 468enddef 469 470def FuncOneArgRetString(arg: string): string 471 return arg 472enddef 473 474def FuncOneArgRetAny(arg: any): any 475 return arg 476enddef 477 478def Test_func_type() 479 let Ref1: func() 480 funcResult = 0 481 Ref1 = FuncNoArgNoRet 482 Ref1() 483 assert_equal(11, funcResult) 484 485 let Ref2: func 486 funcResult = 0 487 Ref2 = FuncNoArgNoRet 488 Ref2() 489 assert_equal(11, funcResult) 490 491 funcResult = 0 492 Ref2 = FuncOneArgNoRet 493 Ref2(12) 494 assert_equal(12, funcResult) 495 496 funcResult = 0 497 Ref2 = FuncNoArgRetNumber 498 assert_equal(1234, Ref2()) 499 assert_equal(22, funcResult) 500 501 funcResult = 0 502 Ref2 = FuncOneArgRetNumber 503 assert_equal(13, Ref2(13)) 504 assert_equal(13, funcResult) 505enddef 506 507def Test_func_type_part() 508 let RefVoid: func: void 509 RefVoid = FuncNoArgNoRet 510 RefVoid = FuncOneArgNoRet 511 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 512 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 513 514 let RefAny: func(): any 515 RefAny = FuncNoArgRetNumber 516 RefAny = FuncNoArgRetString 517 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 518 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 519 520 let RefNr: func: number 521 RefNr = FuncNoArgRetNumber 522 RefNr = FuncOneArgRetNumber 523 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 524 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 525 526 let RefStr: func: string 527 RefStr = FuncNoArgRetString 528 RefStr = FuncOneArgRetString 529 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 530 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 531enddef 532 533def Test_func_type_fails() 534 CheckDefFailure(['let ref1: func()'], 'E704:') 535 536 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 537 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 538 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 539 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, 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 543 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:') 544 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:') 545 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:') 546 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:') 547enddef 548 549def Test_func_return_type() 550 let nr: number 551 nr = FuncNoArgRetNumber() 552 assert_equal(1234, nr) 553 554 nr = FuncOneArgRetAny(122) 555 assert_equal(122, nr) 556 557 let str: string 558 str = FuncOneArgRetAny('yes') 559 assert_equal('yes', str) 560 561 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 562enddef 563 564" When using CheckScriptFailure() for the below test, E1010 is generated instead 565" of E1056. 566func Test_E1056_1059() 567 let caught_1056 = 0 568 try 569 def F(): 570 return 1 571 enddef 572 catch /E1056:/ 573 let caught_1056 = 1 574 endtry 575 call assert_equal(1, caught_1056) 576 577 let caught_1059 = 0 578 try 579 def F5(items : list) 580 echo 'a' 581 enddef 582 catch /E1059:/ 583 let caught_1059 = 1 584 endtry 585 call assert_equal(1, caught_1059) 586endfunc 587 588" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 589