blob: 6f61254f8646de7c7553cacc3733270c34208e08 [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:')
171enddef
172
173def Test_arg_type_wrong()
174 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
175enddef
176
177def Test_vim9script_call()
178 let lines =<< trim END
179 vim9script
180 let var = ''
181 def MyFunc(arg: string)
182 var = arg
183 enddef
184 MyFunc('foobar')
185 assert_equal('foobar', var)
186
187 let str = 'barfoo'
188 str->MyFunc()
189 assert_equal('barfoo', var)
190
191 let g:value = 'value'
192 g:value->MyFunc()
193 assert_equal('value', var)
194
195 let listvar = []
196 def ListFunc(arg: list<number>)
197 listvar = arg
198 enddef
199 [1, 2, 3]->ListFunc()
200 assert_equal([1, 2, 3], listvar)
201
202 let dictvar = {}
203 def DictFunc(arg: dict<number>)
204 dictvar = arg
205 enddef
206 {'a': 1, 'b': 2}->DictFunc()
207 assert_equal(#{a: 1, b: 2}, dictvar)
208 def CompiledDict()
209 {'a': 3, 'b': 4}->DictFunc()
210 enddef
211 CompiledDict()
212 assert_equal(#{a: 3, b: 4}, dictvar)
213
214 #{a: 3, b: 4}->DictFunc()
215 assert_equal(#{a: 3, b: 4}, dictvar)
216
217 ('text')->MyFunc()
218 assert_equal('text', var)
219 ("some")->MyFunc()
220 assert_equal('some', var)
221 END
222 writefile(lines, 'Xcall.vim')
223 source Xcall.vim
224 delete('Xcall.vim')
225enddef
226
227def Test_vim9script_call_fail_decl()
228 let lines =<< trim END
229 vim9script
230 let var = ''
231 def MyFunc(arg: string)
232 let var = 123
233 enddef
234 END
235 writefile(lines, 'Xcall_decl.vim')
236 assert_fails('source Xcall_decl.vim', 'E1054:')
237 delete('Xcall_decl.vim')
238enddef
239
240def Test_vim9script_call_fail_const()
241 let lines =<< trim END
242 vim9script
243 const var = ''
244 def MyFunc(arg: string)
245 var = 'asdf'
246 enddef
247 END
248 writefile(lines, 'Xcall_const.vim')
249 assert_fails('source Xcall_const.vim', 'E46:')
250 delete('Xcall_const.vim')
251enddef
252
253" Test that inside :function a Python function can be defined, :def is not
254" recognized.
255func Test_function_python()
256 CheckFeature python3
257 let py = 'python3'
258 execute py "<< EOF"
259def do_something():
260 return 1
261EOF
262endfunc
263
264def Test_delfunc()
265 let lines =<< trim END
266 vim9script
267 def GoneSoon()
268 echo 'hello'
269 enddef
270
271 def CallGoneSoon()
272 GoneSoon()
273 enddef
274
275 delfunc GoneSoon
276 CallGoneSoon()
277 END
278 writefile(lines, 'XToDelFunc')
279 assert_fails('so XToDelFunc', 'E933')
280 assert_fails('so XToDelFunc', 'E933')
281
282 delete('XToDelFunc')
283enddef
284
285def Test_redef_failure()
286 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef')
287 so Xdef
288 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef')
289 so Xdef
290 call writefile(['def! Func0(): string', 'enddef'], 'Xdef')
291 call assert_fails('so Xdef', 'E1027:')
292 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef')
293 so Xdef
294 call delete('Xdef')
295
296 call assert_equal(0, Func0())
297 call assert_equal('Func1', Func1())
298 call assert_equal('Func2', Func2())
299
300 delfunc! Func0
301 delfunc! Func1
302 delfunc! Func2
303enddef
304
305" Test for internal functions returning different types
306func Test_InternalFuncRetType()
307 let lines =<< trim END
308 def RetFloat(): float
309 return ceil(1.456)
310 enddef
311
312 def RetListAny(): list<any>
313 return items({'k' : 'v'})
314 enddef
315
316 def RetListString(): list<string>
317 return split('a:b:c', ':')
318 enddef
319
320 def RetListDictAny(): list<dict<any>>
321 return getbufinfo()
322 enddef
323
324 def RetDictNumber(): dict<number>
325 return wordcount()
326 enddef
327
328 def RetDictString(): dict<string>
329 return environ()
330 enddef
331 END
332 call writefile(lines, 'Xscript')
333 source Xscript
334
335 call assert_equal(2.0, RetFloat())
336 call assert_equal([['k', 'v']], RetListAny())
337 call assert_equal(['a', 'b', 'c'], RetListString())
338 call assert_notequal([], RetListDictAny())
339 call assert_notequal({}, RetDictNumber())
340 call assert_notequal({}, RetDictString())
341 call delete('Xscript')
342endfunc
343
344" Test for passing too many or too few arguments to internal functions
345func Test_internalfunc_arg_error()
346 let l =<< trim END
347 def! FArgErr(): float
348 return ceil(1.1, 2)
349 enddef
350 END
351 call writefile(l, 'Xinvalidarg')
352 call assert_fails('so Xinvalidarg', 'E118:')
353 let l =<< trim END
354 def! FArgErr(): float
355 return ceil()
356 enddef
357 END
358 call writefile(l, 'Xinvalidarg')
359 call assert_fails('so Xinvalidarg', 'E119:')
360 call delete('Xinvalidarg')
361endfunc
362
363let s:funcResult = 0
364
365def FuncNoArgNoRet()
366 funcResult = 11
367enddef
368
369def FuncNoArgRetNumber(): number
370 funcResult = 22
371 return 1234
372enddef
373
374def FuncOneArgNoRet(arg: number)
375 funcResult = arg
376enddef
377
378def FuncOneArgRetNumber(arg: number): number
379 funcResult = arg
380 return arg
381enddef
382
383def Test_func_type()
384 let Ref1: func()
385 funcResult = 0
386 Ref1 = FuncNoArgNoRet
387 Ref1()
388 assert_equal(11, funcResult)
389enddef
390
391def Test_func_type_fails()
392 CheckDefFailure(['let ref1: func()'], 'E704:')
393
394 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
395 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
396 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
397enddef
398
399
400" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker