blob: 6f9aa0cca4846eeb19a3fc0fdd8c75709d9ec88f [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 Moolenaar0b76b422020-04-07 22:05:08 +0200134" Only varargs
135def MyVarargsOnly(...args: list<string>): string
136 return join(args, ',')
137enddef
138
139def Test_call_varargs_only()
140 assert_equal('', MyVarargsOnly())
141 assert_equal('one', MyVarargsOnly('one'))
142 assert_equal('one,two', MyVarargsOnly('one', 'two'))
143 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
144 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
145enddef
146
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200147def Test_using_var_as_arg()
148 call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef')
149 call assert_fails('so Xdef', 'E1006:')
150 call delete('Xdef')
151enddef
152
153def Test_call_func_defined_later()
154 call assert_equal('one', DefinedLater('one'))
155 call assert_fails('call NotDefined("one")', 'E117:')
156enddef
157
158func DefinedLater(arg)
159 return a:arg
160endfunc
161
162def FuncWithForwardCall()
163 return DefinedEvenLater("yes")
164enddef
165
166def DefinedEvenLater(arg: string): string
167 return arg
168enddef
169
170def Test_error_in_nested_function()
171 " Error in called function requires unwinding the call stack.
172 assert_fails('call FuncWithForwardCall()', 'E1029')
173enddef
174
175def Test_return_type_wrong()
176 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
177 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
178 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
179 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
180
181 CheckScriptFailure(['def Func(): number', 'return', 'enddef'], 'E1003:')
182
183 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
184 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200185 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200186enddef
187
188def Test_arg_type_wrong()
189 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200190 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200191enddef
192
193def Test_vim9script_call()
194 let lines =<< trim END
195 vim9script
196 let var = ''
197 def MyFunc(arg: string)
198 var = arg
199 enddef
200 MyFunc('foobar')
201 assert_equal('foobar', var)
202
203 let str = 'barfoo'
204 str->MyFunc()
205 assert_equal('barfoo', var)
206
207 let g:value = 'value'
208 g:value->MyFunc()
209 assert_equal('value', var)
210
211 let listvar = []
212 def ListFunc(arg: list<number>)
213 listvar = arg
214 enddef
215 [1, 2, 3]->ListFunc()
216 assert_equal([1, 2, 3], listvar)
217
218 let dictvar = {}
219 def DictFunc(arg: dict<number>)
220 dictvar = arg
221 enddef
222 {'a': 1, 'b': 2}->DictFunc()
223 assert_equal(#{a: 1, b: 2}, dictvar)
224 def CompiledDict()
225 {'a': 3, 'b': 4}->DictFunc()
226 enddef
227 CompiledDict()
228 assert_equal(#{a: 3, b: 4}, dictvar)
229
230 #{a: 3, b: 4}->DictFunc()
231 assert_equal(#{a: 3, b: 4}, dictvar)
232
233 ('text')->MyFunc()
234 assert_equal('text', var)
235 ("some")->MyFunc()
236 assert_equal('some', var)
237 END
238 writefile(lines, 'Xcall.vim')
239 source Xcall.vim
240 delete('Xcall.vim')
241enddef
242
243def Test_vim9script_call_fail_decl()
244 let lines =<< trim END
245 vim9script
246 let var = ''
247 def MyFunc(arg: string)
248 let var = 123
249 enddef
250 END
251 writefile(lines, 'Xcall_decl.vim')
252 assert_fails('source Xcall_decl.vim', 'E1054:')
253 delete('Xcall_decl.vim')
254enddef
255
256def Test_vim9script_call_fail_const()
257 let lines =<< trim END
258 vim9script
259 const var = ''
260 def MyFunc(arg: string)
261 var = 'asdf'
262 enddef
263 END
264 writefile(lines, 'Xcall_const.vim')
265 assert_fails('source Xcall_const.vim', 'E46:')
266 delete('Xcall_const.vim')
267enddef
268
269" Test that inside :function a Python function can be defined, :def is not
270" recognized.
271func Test_function_python()
272 CheckFeature python3
273 let py = 'python3'
274 execute py "<< EOF"
275def do_something():
276 return 1
277EOF
278endfunc
279
280def Test_delfunc()
281 let lines =<< trim END
282 vim9script
283 def GoneSoon()
284 echo 'hello'
285 enddef
286
287 def CallGoneSoon()
288 GoneSoon()
289 enddef
290
291 delfunc GoneSoon
292 CallGoneSoon()
293 END
294 writefile(lines, 'XToDelFunc')
295 assert_fails('so XToDelFunc', 'E933')
296 assert_fails('so XToDelFunc', 'E933')
297
298 delete('XToDelFunc')
299enddef
300
301def Test_redef_failure()
302 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef')
303 so Xdef
304 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef')
305 so Xdef
306 call writefile(['def! Func0(): string', 'enddef'], 'Xdef')
307 call assert_fails('so Xdef', 'E1027:')
308 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef')
309 so Xdef
310 call delete('Xdef')
311
312 call assert_equal(0, Func0())
313 call assert_equal('Func1', Func1())
314 call assert_equal('Func2', Func2())
315
316 delfunc! Func0
317 delfunc! Func1
318 delfunc! Func2
319enddef
320
321" Test for internal functions returning different types
322func Test_InternalFuncRetType()
323 let lines =<< trim END
324 def RetFloat(): float
325 return ceil(1.456)
326 enddef
327
328 def RetListAny(): list<any>
329 return items({'k' : 'v'})
330 enddef
331
332 def RetListString(): list<string>
333 return split('a:b:c', ':')
334 enddef
335
336 def RetListDictAny(): list<dict<any>>
337 return getbufinfo()
338 enddef
339
340 def RetDictNumber(): dict<number>
341 return wordcount()
342 enddef
343
344 def RetDictString(): dict<string>
345 return environ()
346 enddef
347 END
348 call writefile(lines, 'Xscript')
349 source Xscript
350
351 call assert_equal(2.0, RetFloat())
352 call assert_equal([['k', 'v']], RetListAny())
353 call assert_equal(['a', 'b', 'c'], RetListString())
354 call assert_notequal([], RetListDictAny())
355 call assert_notequal({}, RetDictNumber())
356 call assert_notequal({}, RetDictString())
357 call delete('Xscript')
358endfunc
359
360" Test for passing too many or too few arguments to internal functions
361func Test_internalfunc_arg_error()
362 let l =<< trim END
363 def! FArgErr(): float
364 return ceil(1.1, 2)
365 enddef
366 END
367 call writefile(l, 'Xinvalidarg')
368 call assert_fails('so Xinvalidarg', 'E118:')
369 let l =<< trim END
370 def! FArgErr(): float
371 return ceil()
372 enddef
373 END
374 call writefile(l, 'Xinvalidarg')
375 call assert_fails('so Xinvalidarg', 'E119:')
376 call delete('Xinvalidarg')
377endfunc
378
379let s:funcResult = 0
380
381def FuncNoArgNoRet()
382 funcResult = 11
383enddef
384
385def FuncNoArgRetNumber(): number
386 funcResult = 22
387 return 1234
388enddef
389
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200390def FuncNoArgRetString(): string
391 funcResult = 45
392 return 'text'
393enddef
394
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200395def FuncOneArgNoRet(arg: number)
396 funcResult = arg
397enddef
398
399def FuncOneArgRetNumber(arg: number): number
400 funcResult = arg
401 return arg
402enddef
403
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200404def FuncOneArgRetString(arg: string): string
405 return arg
406enddef
407
Bram Moolenaar89228602020-04-05 22:14:54 +0200408def FuncOneArgRetAny(arg: any): any
409 return arg
410enddef
411
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200412def Test_func_type()
413 let Ref1: func()
414 funcResult = 0
415 Ref1 = FuncNoArgNoRet
416 Ref1()
417 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200418
419 let Ref2: func
420 funcResult = 0
421 Ref2 = FuncNoArgNoRet
422 Ref2()
423 assert_equal(11, funcResult)
424
425 funcResult = 0
426 Ref2 = FuncOneArgNoRet
427 Ref2(12)
428 assert_equal(12, funcResult)
429
430 funcResult = 0
431 Ref2 = FuncNoArgRetNumber
432 assert_equal(1234, Ref2())
433 assert_equal(22, funcResult)
434
435 funcResult = 0
436 Ref2 = FuncOneArgRetNumber
437 assert_equal(13, Ref2(13))
438 assert_equal(13, funcResult)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200439enddef
440
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200441def Test_func_type_part()
442 let RefVoid: func: void
443 RefVoid = FuncNoArgNoRet
444 RefVoid = FuncOneArgNoRet
445 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
446 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
447
448 let RefAny: func(): any
449 RefAny = FuncNoArgRetNumber
450 RefAny = FuncNoArgRetString
451 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
452 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
453
454 let RefNr: func: number
455 RefNr = FuncNoArgRetNumber
456 RefNr = FuncOneArgRetNumber
457 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
458 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
459
460 let RefStr: func: string
461 RefStr = FuncNoArgRetString
462 RefStr = FuncOneArgRetString
463 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
464 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
465enddef
466
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200467def Test_func_type_fails()
468 CheckDefFailure(['let ref1: func()'], 'E704:')
469
470 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
471 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
472 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
473enddef
474
Bram Moolenaar89228602020-04-05 22:14:54 +0200475def Test_func_return_type()
476 let nr: number
477 nr = FuncNoArgRetNumber()
478 assert_equal(1234, nr)
479
480 nr = FuncOneArgRetAny(122)
481 assert_equal(122, nr)
482
483 let str: string
484 str = FuncOneArgRetAny('yes')
485 assert_equal('yes', str)
486
487 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
488enddef
489
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200490" When using CheckScriptFailure() for the below test, E1010 is generated instead
491" of E1056.
492func Test_E1056_1059()
493 let caught_1056 = 0
494 try
495 def F():
496 return 1
497 enddef
498 catch /E1056:/
499 let caught_1056 = 1
500 endtry
501 call assert_equal(1, caught_1056)
502
503 let caught_1059 = 0
504 try
505 def F5(items : list)
506 echo 'a'
507 enddef
508 catch /E1059:/
509 let caught_1059 = 1
510 endtry
511 call assert_equal(1, caught_1059)
512endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200513
514" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker