blob: 470e880e0fdd5ee154fd8524f69636fe7cba2cdd [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 Moolenaarec5929d2020-04-07 20:53:39 +0200445def FuncOneArgRetString(arg: string): string
446 return arg
447enddef
448
Bram Moolenaar89228602020-04-05 22:14:54 +0200449def FuncOneArgRetAny(arg: any): any
450 return arg
451enddef
452
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200453def Test_func_type()
454 let Ref1: func()
455 funcResult = 0
456 Ref1 = FuncNoArgNoRet
457 Ref1()
458 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200459
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)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200480enddef
481
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200482def 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200508def 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
Bram Moolenaar89228602020-04-05 22:14:54 +0200516def 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
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200531" 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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200554
555" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker