blob: 57ecf51ff40efc2764cb52bbc213859a4fb6625a [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:')
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'))
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +0200131 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200132enddef
133
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200134let 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
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200175" 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200188def 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:')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200226 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200227enddef
228
229def Test_arg_type_wrong()
230 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200231 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200232enddef
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
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200431def FuncNoArgRetString(): string
432 funcResult = 45
433 return 'text'
434enddef
435
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200436def FuncOneArgNoRet(arg: number)
437 funcResult = arg
438enddef
439
440def FuncOneArgRetNumber(arg: number): number
441 funcResult = arg
442 return arg
443enddef
444
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200445def FuncTwoArgNoRet(one: bool, two: number)
446 funcResult = two
447enddef
448
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200449def FuncOneArgRetString(arg: string): string
450 return arg
451enddef
452
Bram Moolenaar89228602020-04-05 22:14:54 +0200453def FuncOneArgRetAny(arg: any): any
454 return arg
455enddef
456
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200457def Test_func_type()
458 let Ref1: func()
459 funcResult = 0
460 Ref1 = FuncNoArgNoRet
461 Ref1()
462 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200463
464 let Ref2: func
465 funcResult = 0
466 Ref2 = FuncNoArgNoRet
467 Ref2()
468 assert_equal(11, funcResult)
469
470 funcResult = 0
471 Ref2 = FuncOneArgNoRet
472 Ref2(12)
473 assert_equal(12, funcResult)
474
475 funcResult = 0
476 Ref2 = FuncNoArgRetNumber
477 assert_equal(1234, Ref2())
478 assert_equal(22, funcResult)
479
480 funcResult = 0
481 Ref2 = FuncOneArgRetNumber
482 assert_equal(13, Ref2(13))
483 assert_equal(13, funcResult)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200484enddef
485
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200486def Test_func_type_part()
487 let RefVoid: func: void
488 RefVoid = FuncNoArgNoRet
489 RefVoid = FuncOneArgNoRet
490 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
491 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
492
493 let RefAny: func(): any
494 RefAny = FuncNoArgRetNumber
495 RefAny = FuncNoArgRetString
496 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
497 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
498
499 let RefNr: func: number
500 RefNr = FuncNoArgRetNumber
501 RefNr = FuncOneArgRetNumber
502 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
503 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
504
505 let RefStr: func: string
506 RefStr = FuncNoArgRetString
507 RefStr = FuncOneArgRetString
508 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
509 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
510enddef
511
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200512def Test_func_type_fails()
513 CheckDefFailure(['let ref1: func()'], 'E704:')
514
515 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
516 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
517 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200518 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
519 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
520 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
521
522 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
523 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
524 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:')
525 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200526enddef
527
Bram Moolenaar89228602020-04-05 22:14:54 +0200528def Test_func_return_type()
529 let nr: number
530 nr = FuncNoArgRetNumber()
531 assert_equal(1234, nr)
532
533 nr = FuncOneArgRetAny(122)
534 assert_equal(122, nr)
535
536 let str: string
537 str = FuncOneArgRetAny('yes')
538 assert_equal('yes', str)
539
540 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
541enddef
542
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200543" When using CheckScriptFailure() for the below test, E1010 is generated instead
544" of E1056.
545func Test_E1056_1059()
546 let caught_1056 = 0
547 try
548 def F():
549 return 1
550 enddef
551 catch /E1056:/
552 let caught_1056 = 1
553 endtry
554 call assert_equal(1, caught_1056)
555
556 let caught_1059 = 0
557 try
558 def F5(items : list)
559 echo 'a'
560 enddef
561 catch /E1059:/
562 let caught_1059 = 1
563 endtry
564 call assert_equal(1, caught_1059)
565endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200566
567" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker