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:') 99enddef 100 101func Test_call_default_args_from_func() 102 call assert_equal('string', MyDefaultArgs()) 103 call assert_equal('one', MyDefaultArgs('one')) 104 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') 105endfunc 106 107func TakesOneArg(arg) 108 echo a:arg 109endfunc 110 111def Test_call_wrong_args() 112 call CheckDefFailure(['TakesOneArg()'], 'E119:') 113 call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') 114 call CheckDefFailure(['bufnr(xxx)'], 'E1001:') 115enddef 116 117" Default arg and varargs 118def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string 119 let res = one .. ',' .. two 120 for s in rest 121 res ..= ',' .. s 122 endfor 123 return res 124enddef 125 126def Test_call_def_varargs() 127 call assert_fails('call MyDefVarargs()', 'E119:') 128 assert_equal('one,foo', MyDefVarargs('one')) 129 assert_equal('one,two', MyDefVarargs('one', 'two')) 130 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) 131 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number') 132enddef 133 134let s:value = '' 135 136def FuncOneDefArg(opt = 'text') 137 s:value = opt 138enddef 139 140def FuncTwoDefArg(nr = 123, opt = 'text'): string 141 return nr .. opt 142enddef 143 144def FuncVarargs(...arg: list<string>): string 145 return join(arg, ',') 146enddef 147 148def Test_func_type_varargs() 149 let RefDefArg: func(?string) 150 RefDefArg = FuncOneDefArg 151 RefDefArg() 152 assert_equal('text', s:value) 153 RefDefArg('some') 154 assert_equal('some', s:value) 155 156 let RefDef2Arg: func(?number, ?string): string 157 RefDef2Arg = FuncTwoDefArg 158 assert_equal('123text', RefDef2Arg()) 159 assert_equal('99text', RefDef2Arg(99)) 160 assert_equal('77some', RefDef2Arg(77, 'some')) 161 162 call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:') 163 call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:') 164 165 let RefVarargs: func(...list<string>): string 166 RefVarargs = FuncVarargs 167 assert_equal('', RefVarargs()) 168 assert_equal('one', RefVarargs('one')) 169 assert_equal('one,two', RefVarargs('one', 'two')) 170 171 call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:') 172 call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:') 173enddef 174 175" Only varargs 176def MyVarargsOnly(...args: list<string>): string 177 return join(args, ',') 178enddef 179 180def Test_call_varargs_only() 181 assert_equal('', MyVarargsOnly()) 182 assert_equal('one', MyVarargsOnly('one')) 183 assert_equal('one,two', MyVarargsOnly('one', 'two')) 184 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number') 185 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number') 186enddef 187 188def Test_using_var_as_arg() 189 call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef') 190 call assert_fails('so Xdef', 'E1006:') 191 call delete('Xdef') 192enddef 193 194def Test_call_func_defined_later() 195 call assert_equal('one', DefinedLater('one')) 196 call assert_fails('call NotDefined("one")', 'E117:') 197enddef 198 199func DefinedLater(arg) 200 return a:arg 201endfunc 202 203def FuncWithForwardCall() 204 return DefinedEvenLater("yes") 205enddef 206 207def DefinedEvenLater(arg: string): string 208 return arg 209enddef 210 211def Test_error_in_nested_function() 212 " Error in called function requires unwinding the call stack. 213 assert_fails('call FuncWithForwardCall()', 'E1029') 214enddef 215 216def Test_return_type_wrong() 217 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') 218 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') 219 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') 220 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') 221 222 CheckScriptFailure(['def Func(): number', 'return', 'enddef'], 'E1003:') 223 224 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') 225 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') 226 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') 227enddef 228 229def Test_arg_type_wrong() 230 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') 231 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...') 232enddef 233 234def Test_vim9script_call() 235 let lines =<< trim END 236 vim9script 237 let var = '' 238 def MyFunc(arg: string) 239 var = arg 240 enddef 241 MyFunc('foobar') 242 assert_equal('foobar', var) 243 244 let str = 'barfoo' 245 str->MyFunc() 246 assert_equal('barfoo', var) 247 248 let g:value = 'value' 249 g:value->MyFunc() 250 assert_equal('value', var) 251 252 let listvar = [] 253 def ListFunc(arg: list<number>) 254 listvar = arg 255 enddef 256 [1, 2, 3]->ListFunc() 257 assert_equal([1, 2, 3], listvar) 258 259 let dictvar = {} 260 def DictFunc(arg: dict<number>) 261 dictvar = arg 262 enddef 263 {'a': 1, 'b': 2}->DictFunc() 264 assert_equal(#{a: 1, b: 2}, dictvar) 265 def CompiledDict() 266 {'a': 3, 'b': 4}->DictFunc() 267 enddef 268 CompiledDict() 269 assert_equal(#{a: 3, b: 4}, dictvar) 270 271 #{a: 3, b: 4}->DictFunc() 272 assert_equal(#{a: 3, b: 4}, dictvar) 273 274 ('text')->MyFunc() 275 assert_equal('text', var) 276 ("some")->MyFunc() 277 assert_equal('some', var) 278 END 279 writefile(lines, 'Xcall.vim') 280 source Xcall.vim 281 delete('Xcall.vim') 282enddef 283 284def Test_vim9script_call_fail_decl() 285 let lines =<< trim END 286 vim9script 287 let var = '' 288 def MyFunc(arg: string) 289 let var = 123 290 enddef 291 END 292 writefile(lines, 'Xcall_decl.vim') 293 assert_fails('source Xcall_decl.vim', 'E1054:') 294 delete('Xcall_decl.vim') 295enddef 296 297def Test_vim9script_call_fail_const() 298 let lines =<< trim END 299 vim9script 300 const var = '' 301 def MyFunc(arg: string) 302 var = 'asdf' 303 enddef 304 END 305 writefile(lines, 'Xcall_const.vim') 306 assert_fails('source Xcall_const.vim', 'E46:') 307 delete('Xcall_const.vim') 308enddef 309 310" Test that inside :function a Python function can be defined, :def is not 311" recognized. 312func Test_function_python() 313 CheckFeature python3 314 let py = 'python3' 315 execute py "<< EOF" 316def do_something(): 317 return 1 318EOF 319endfunc 320 321def Test_delfunc() 322 let lines =<< trim END 323 vim9script 324 def GoneSoon() 325 echo 'hello' 326 enddef 327 328 def CallGoneSoon() 329 GoneSoon() 330 enddef 331 332 delfunc GoneSoon 333 CallGoneSoon() 334 END 335 writefile(lines, 'XToDelFunc') 336 assert_fails('so XToDelFunc', 'E933') 337 assert_fails('so XToDelFunc', 'E933') 338 339 delete('XToDelFunc') 340enddef 341 342def Test_redef_failure() 343 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef') 344 so Xdef 345 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef') 346 so Xdef 347 call writefile(['def! Func0(): string', 'enddef'], 'Xdef') 348 call assert_fails('so Xdef', 'E1027:') 349 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef') 350 so Xdef 351 call delete('Xdef') 352 353 call assert_equal(0, Func0()) 354 call assert_equal('Func1', Func1()) 355 call assert_equal('Func2', Func2()) 356 357 delfunc! Func0 358 delfunc! Func1 359 delfunc! Func2 360enddef 361 362" Test for internal functions returning different types 363func Test_InternalFuncRetType() 364 let lines =<< trim END 365 def RetFloat(): float 366 return ceil(1.456) 367 enddef 368 369 def RetListAny(): list<any> 370 return items({'k' : 'v'}) 371 enddef 372 373 def RetListString(): list<string> 374 return split('a:b:c', ':') 375 enddef 376 377 def RetListDictAny(): list<dict<any>> 378 return getbufinfo() 379 enddef 380 381 def RetDictNumber(): dict<number> 382 return wordcount() 383 enddef 384 385 def RetDictString(): dict<string> 386 return environ() 387 enddef 388 END 389 call writefile(lines, 'Xscript') 390 source Xscript 391 392 call assert_equal(2.0, RetFloat()) 393 call assert_equal([['k', 'v']], RetListAny()) 394 call assert_equal(['a', 'b', 'c'], RetListString()) 395 call assert_notequal([], RetListDictAny()) 396 call assert_notequal({}, RetDictNumber()) 397 call assert_notequal({}, RetDictString()) 398 call delete('Xscript') 399endfunc 400 401" Test for passing too many or too few arguments to internal functions 402func Test_internalfunc_arg_error() 403 let l =<< trim END 404 def! FArgErr(): float 405 return ceil(1.1, 2) 406 enddef 407 END 408 call writefile(l, 'Xinvalidarg') 409 call assert_fails('so Xinvalidarg', 'E118:') 410 let l =<< trim END 411 def! FArgErr(): float 412 return ceil() 413 enddef 414 END 415 call writefile(l, 'Xinvalidarg') 416 call assert_fails('so Xinvalidarg', 'E119:') 417 call delete('Xinvalidarg') 418endfunc 419 420let s:funcResult = 0 421 422def FuncNoArgNoRet() 423 funcResult = 11 424enddef 425 426def FuncNoArgRetNumber(): number 427 funcResult = 22 428 return 1234 429enddef 430 431def FuncNoArgRetString(): string 432 funcResult = 45 433 return 'text' 434enddef 435 436def FuncOneArgNoRet(arg: number) 437 funcResult = arg 438enddef 439 440def FuncOneArgRetNumber(arg: number): number 441 funcResult = arg 442 return arg 443enddef 444 445def FuncOneArgRetString(arg: string): string 446 return arg 447enddef 448 449def FuncOneArgRetAny(arg: any): any 450 return arg 451enddef 452 453def Test_func_type() 454 let Ref1: func() 455 funcResult = 0 456 Ref1 = FuncNoArgNoRet 457 Ref1() 458 assert_equal(11, funcResult) 459 460 let Ref2: func 461 funcResult = 0 462 Ref2 = FuncNoArgNoRet 463 Ref2() 464 assert_equal(11, funcResult) 465 466 funcResult = 0 467 Ref2 = FuncOneArgNoRet 468 Ref2(12) 469 assert_equal(12, funcResult) 470 471 funcResult = 0 472 Ref2 = FuncNoArgRetNumber 473 assert_equal(1234, Ref2()) 474 assert_equal(22, funcResult) 475 476 funcResult = 0 477 Ref2 = FuncOneArgRetNumber 478 assert_equal(13, Ref2(13)) 479 assert_equal(13, funcResult) 480enddef 481 482def Test_func_type_part() 483 let RefVoid: func: void 484 RefVoid = FuncNoArgNoRet 485 RefVoid = FuncOneArgNoRet 486 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 487 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') 488 489 let RefAny: func(): any 490 RefAny = FuncNoArgRetNumber 491 RefAny = FuncNoArgRetString 492 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') 493 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') 494 495 let RefNr: func: number 496 RefNr = FuncNoArgRetNumber 497 RefNr = FuncOneArgRetNumber 498 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') 499 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') 500 501 let RefStr: func: string 502 RefStr = FuncNoArgRetString 503 RefStr = FuncOneArgRetString 504 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') 505 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') 506enddef 507 508def Test_func_type_fails() 509 CheckDefFailure(['let ref1: func()'], 'E704:') 510 511 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') 512 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)') 513 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number') 514enddef 515 516def Test_func_return_type() 517 let nr: number 518 nr = FuncNoArgRetNumber() 519 assert_equal(1234, nr) 520 521 nr = FuncOneArgRetAny(122) 522 assert_equal(122, nr) 523 524 let str: string 525 str = FuncOneArgRetAny('yes') 526 assert_equal('yes', str) 527 528 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number') 529enddef 530 531" When using CheckScriptFailure() for the below test, E1010 is generated instead 532" of E1056. 533func Test_E1056_1059() 534 let caught_1056 = 0 535 try 536 def F(): 537 return 1 538 enddef 539 catch /E1056:/ 540 let caught_1056 = 1 541 endtry 542 call assert_equal(1, caught_1056) 543 544 let caught_1059 = 0 545 try 546 def F5(items : list) 547 echo 'a' 548 enddef 549 catch /E1059:/ 550 let caught_1059 = 1 551 endtry 552 call assert_equal(1, caught_1059) 553endfunc 554 555" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 556