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