blob: 38d7c5a5a026a213de745744d9c67d4a414e14bd [file] [log] [blame]
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001" 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:')
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +020099 call CheckScriptFailure(['def Func(arg: number = "text")', 'enddef'], 'E1013: argument 1: type mismatch, expected number but got string')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200100enddef
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'))
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +0200132 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200133enddef
134
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200135let 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
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200176" 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200189def 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
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +0200200def 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200220func 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:')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200247 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200248enddef
249
250def Test_arg_type_wrong()
251 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200252 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200253enddef
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
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200452def FuncNoArgRetString(): string
453 funcResult = 45
454 return 'text'
455enddef
456
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200457def FuncOneArgNoRet(arg: number)
458 funcResult = arg
459enddef
460
461def FuncOneArgRetNumber(arg: number): number
462 funcResult = arg
463 return arg
464enddef
465
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200466def FuncTwoArgNoRet(one: bool, two: number)
467 funcResult = two
468enddef
469
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200470def FuncOneArgRetString(arg: string): string
471 return arg
472enddef
473
Bram Moolenaar89228602020-04-05 22:14:54 +0200474def FuncOneArgRetAny(arg: any): any
475 return arg
476enddef
477
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200478def Test_func_type()
479 let Ref1: func()
480 funcResult = 0
481 Ref1 = FuncNoArgNoRet
482 Ref1()
483 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200484
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)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200505enddef
506
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200507def 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200533def 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')
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200539 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:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200547enddef
548
Bram Moolenaar89228602020-04-05 22:14:54 +0200549def 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
Bram Moolenaar5e774c72020-04-12 21:53:00 +0200564def MultiLine(
565 arg1: string,
566 arg2 = 1234,
567 ...rest: list<string>
568 ): string
569 return arg1 .. arg2 .. join(rest, '-')
570enddef
571
572def Test_multiline()
573 assert_equal('text1234', MultiLine('text'))
574 assert_equal('text777', MultiLine('text', 777))
575 assert_equal('text777one', MultiLine('text', 777, 'one'))
576 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
577enddef
578
579
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200580" When using CheckScriptFailure() for the below test, E1010 is generated instead
581" of E1056.
582func Test_E1056_1059()
583 let caught_1056 = 0
584 try
585 def F():
586 return 1
587 enddef
588 catch /E1056:/
589 let caught_1056 = 1
590 endtry
591 call assert_equal(1, caught_1056)
592
593 let caught_1059 = 0
594 try
595 def F5(items : list)
596 echo 'a'
597 enddef
598 catch /E1059:/
599 let caught_1059 = 1
600 endtry
601 call assert_equal(1, caught_1059)
602endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200603
604" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker