blob: 5554b2d7e1649468cb2a11dbb524ba99c8da2034 [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
376def FuncOneArgNoRet(arg: number)
377 funcResult = arg
378enddef
379
380def FuncOneArgRetNumber(arg: number): number
381 funcResult = arg
382 return arg
383enddef
384
Bram Moolenaar89228602020-04-05 22:14:54 +0200385def FuncOneArgRetAny(arg: any): any
386 return arg
387enddef
388
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200389def Test_func_type()
390 let Ref1: func()
391 funcResult = 0
392 Ref1 = FuncNoArgNoRet
393 Ref1()
394 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200395
396 let Ref2: func
397 funcResult = 0
398 Ref2 = FuncNoArgNoRet
399 Ref2()
400 assert_equal(11, funcResult)
401
402 funcResult = 0
403 Ref2 = FuncOneArgNoRet
404 Ref2(12)
405 assert_equal(12, funcResult)
406
407 funcResult = 0
408 Ref2 = FuncNoArgRetNumber
409 assert_equal(1234, Ref2())
410 assert_equal(22, funcResult)
411
412 funcResult = 0
413 Ref2 = FuncOneArgRetNumber
414 assert_equal(13, Ref2(13))
415 assert_equal(13, funcResult)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200416enddef
417
418def Test_func_type_fails()
419 CheckDefFailure(['let ref1: func()'], 'E704:')
420
421 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
422 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
423 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
424enddef
425
Bram Moolenaar89228602020-04-05 22:14:54 +0200426def Test_func_return_type()
427 let nr: number
428 nr = FuncNoArgRetNumber()
429 assert_equal(1234, nr)
430
431 nr = FuncOneArgRetAny(122)
432 assert_equal(122, nr)
433
434 let str: string
435 str = FuncOneArgRetAny('yes')
436 assert_equal('yes', str)
437
438 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
439enddef
440
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200441" When using CheckScriptFailure() for the below test, E1010 is generated instead
442" of E1056.
443func Test_E1056_1059()
444 let caught_1056 = 0
445 try
446 def F():
447 return 1
448 enddef
449 catch /E1056:/
450 let caught_1056 = 1
451 endtry
452 call assert_equal(1, caught_1056)
453
454 let caught_1059 = 0
455 try
456 def F5(items : list)
457 echo 'a'
458 enddef
459 catch /E1059:/
460 let caught_1059 = 1
461 endtry
462 call assert_equal(1, caught_1059)
463endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200464
465" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker