blob: 8a6c3d607ae5e6c2929e21e0edc07ea1fc46f649 [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:')
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +020099 call CheckScriptFailure(['def Func(arg: number = "text")', 'enddef'], 'E1013: argument 1: type mismatch, expected number but got string')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200100enddef
101
102func Test_call_default_args_from_func()
103 call assert_equal('string', MyDefaultArgs())
104 call assert_equal('one', MyDefaultArgs('one'))
105 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
106endfunc
107
108func TakesOneArg(arg)
109 echo a:arg
110endfunc
111
112def Test_call_wrong_args()
113 call CheckDefFailure(['TakesOneArg()'], 'E119:')
114 call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
115 call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
116enddef
117
118" Default arg and varargs
119def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
120 let res = one .. ',' .. two
121 for s in rest
122 res ..= ',' .. s
123 endfor
124 return res
125enddef
126
127def Test_call_def_varargs()
128 call assert_fails('call MyDefVarargs()', 'E119:')
129 assert_equal('one,foo', MyDefVarargs('one'))
130 assert_equal('one,two', MyDefVarargs('one', 'two'))
131 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +0200132 call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200133enddef
134
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200135let s:value = ''
136
137def FuncOneDefArg(opt = 'text')
138 s:value = opt
139enddef
140
141def FuncTwoDefArg(nr = 123, opt = 'text'): string
142 return nr .. opt
143enddef
144
145def FuncVarargs(...arg: list<string>): string
146 return join(arg, ',')
147enddef
148
149def Test_func_type_varargs()
150 let RefDefArg: func(?string)
151 RefDefArg = FuncOneDefArg
152 RefDefArg()
153 assert_equal('text', s:value)
154 RefDefArg('some')
155 assert_equal('some', s:value)
156
157 let RefDef2Arg: func(?number, ?string): string
158 RefDef2Arg = FuncTwoDefArg
159 assert_equal('123text', RefDef2Arg())
160 assert_equal('99text', RefDef2Arg(99))
161 assert_equal('77some', RefDef2Arg(77, 'some'))
162
163 call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:')
164 call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:')
165
166 let RefVarargs: func(...list<string>): string
167 RefVarargs = FuncVarargs
168 assert_equal('', RefVarargs())
169 assert_equal('one', RefVarargs('one'))
170 assert_equal('one,two', RefVarargs('one', 'two'))
171
172 call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:')
173 call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:')
174enddef
175
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200176" Only varargs
177def MyVarargsOnly(...args: list<string>): string
178 return join(args, ',')
179enddef
180
181def Test_call_varargs_only()
182 assert_equal('', MyVarargsOnly())
183 assert_equal('one', MyVarargsOnly('one'))
184 assert_equal('one,two', MyVarargsOnly('one', 'two'))
185 call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
186 call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
187enddef
188
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200189def Test_using_var_as_arg()
190 call writefile(['def Func(x: number)', 'let x = 234', 'enddef'], 'Xdef')
191 call assert_fails('so Xdef', 'E1006:')
192 call delete('Xdef')
193enddef
194
195def Test_call_func_defined_later()
196 call assert_equal('one', DefinedLater('one'))
197 call assert_fails('call NotDefined("one")', 'E117:')
198enddef
199
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +0200200def CombineFuncrefTypes()
201 " same arguments, different return type
202 let Ref1: func(bool): string
203 let Ref2: func(bool): number
204 let Ref3: func(bool): any
205 Ref3 = g:cond ? Ref1 : Ref2
206
207 " different number of arguments
208 let Refa1: func(bool): number
209 let Refa2: func(bool, number): number
210 let Refa3: func: number
211 Refa3 = g:cond ? Refa1 : Refa2
212
213 " different argument types
214 let Refb1: func(bool, string): number
215 let Refb2: func(string, number): number
216 let Refb3: func(any, any): number
217 Refb3 = g:cond ? Refb1 : Refb2
218enddef
219
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200220func DefinedLater(arg)
221 return a:arg
222endfunc
223
224def FuncWithForwardCall()
225 return DefinedEvenLater("yes")
226enddef
227
228def DefinedEvenLater(arg: string): string
229 return arg
230enddef
231
232def Test_error_in_nested_function()
233 " Error in called function requires unwinding the call stack.
234 assert_fails('call FuncWithForwardCall()', 'E1029')
235enddef
236
237def Test_return_type_wrong()
238 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
239 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
240 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
241 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
242
243 CheckScriptFailure(['def Func(): number', 'return', 'enddef'], 'E1003:')
244
245 CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
246 CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200247 CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200248enddef
249
250def Test_arg_type_wrong()
251 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200252 CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
Bram Moolenaar6e949782020-04-13 17:21:00 +0200253 CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200254enddef
255
256def Test_vim9script_call()
257 let lines =<< trim END
258 vim9script
259 let var = ''
260 def MyFunc(arg: string)
261 var = arg
262 enddef
263 MyFunc('foobar')
264 assert_equal('foobar', var)
265
266 let str = 'barfoo'
267 str->MyFunc()
268 assert_equal('barfoo', var)
269
270 let g:value = 'value'
271 g:value->MyFunc()
272 assert_equal('value', var)
273
274 let listvar = []
275 def ListFunc(arg: list<number>)
276 listvar = arg
277 enddef
278 [1, 2, 3]->ListFunc()
279 assert_equal([1, 2, 3], listvar)
280
281 let dictvar = {}
282 def DictFunc(arg: dict<number>)
283 dictvar = arg
284 enddef
285 {'a': 1, 'b': 2}->DictFunc()
286 assert_equal(#{a: 1, b: 2}, dictvar)
287 def CompiledDict()
288 {'a': 3, 'b': 4}->DictFunc()
289 enddef
290 CompiledDict()
291 assert_equal(#{a: 3, b: 4}, dictvar)
292
293 #{a: 3, b: 4}->DictFunc()
294 assert_equal(#{a: 3, b: 4}, dictvar)
295
296 ('text')->MyFunc()
297 assert_equal('text', var)
298 ("some")->MyFunc()
299 assert_equal('some', var)
300 END
301 writefile(lines, 'Xcall.vim')
302 source Xcall.vim
303 delete('Xcall.vim')
304enddef
305
306def Test_vim9script_call_fail_decl()
307 let lines =<< trim END
308 vim9script
309 let var = ''
310 def MyFunc(arg: string)
311 let var = 123
312 enddef
313 END
314 writefile(lines, 'Xcall_decl.vim')
315 assert_fails('source Xcall_decl.vim', 'E1054:')
316 delete('Xcall_decl.vim')
317enddef
318
319def Test_vim9script_call_fail_const()
320 let lines =<< trim END
321 vim9script
322 const var = ''
323 def MyFunc(arg: string)
324 var = 'asdf'
325 enddef
326 END
327 writefile(lines, 'Xcall_const.vim')
328 assert_fails('source Xcall_const.vim', 'E46:')
329 delete('Xcall_const.vim')
330enddef
331
332" Test that inside :function a Python function can be defined, :def is not
333" recognized.
334func Test_function_python()
335 CheckFeature python3
336 let py = 'python3'
337 execute py "<< EOF"
338def do_something():
339 return 1
340EOF
341endfunc
342
343def Test_delfunc()
344 let lines =<< trim END
345 vim9script
346 def GoneSoon()
347 echo 'hello'
348 enddef
349
350 def CallGoneSoon()
351 GoneSoon()
352 enddef
353
354 delfunc GoneSoon
355 CallGoneSoon()
356 END
357 writefile(lines, 'XToDelFunc')
358 assert_fails('so XToDelFunc', 'E933')
359 assert_fails('so XToDelFunc', 'E933')
360
361 delete('XToDelFunc')
362enddef
363
364def Test_redef_failure()
365 call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef')
366 so Xdef
367 call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef')
368 so Xdef
369 call writefile(['def! Func0(): string', 'enddef'], 'Xdef')
370 call assert_fails('so Xdef', 'E1027:')
371 call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef')
372 so Xdef
373 call delete('Xdef')
374
375 call assert_equal(0, Func0())
376 call assert_equal('Func1', Func1())
377 call assert_equal('Func2', Func2())
378
379 delfunc! Func0
380 delfunc! Func1
381 delfunc! Func2
382enddef
383
384" Test for internal functions returning different types
385func Test_InternalFuncRetType()
386 let lines =<< trim END
387 def RetFloat(): float
388 return ceil(1.456)
389 enddef
390
391 def RetListAny(): list<any>
392 return items({'k' : 'v'})
393 enddef
394
395 def RetListString(): list<string>
396 return split('a:b:c', ':')
397 enddef
398
399 def RetListDictAny(): list<dict<any>>
400 return getbufinfo()
401 enddef
402
403 def RetDictNumber(): dict<number>
404 return wordcount()
405 enddef
406
407 def RetDictString(): dict<string>
408 return environ()
409 enddef
410 END
411 call writefile(lines, 'Xscript')
412 source Xscript
413
414 call assert_equal(2.0, RetFloat())
415 call assert_equal([['k', 'v']], RetListAny())
416 call assert_equal(['a', 'b', 'c'], RetListString())
417 call assert_notequal([], RetListDictAny())
418 call assert_notequal({}, RetDictNumber())
419 call assert_notequal({}, RetDictString())
420 call delete('Xscript')
421endfunc
422
423" Test for passing too many or too few arguments to internal functions
424func Test_internalfunc_arg_error()
425 let l =<< trim END
426 def! FArgErr(): float
427 return ceil(1.1, 2)
428 enddef
429 END
430 call writefile(l, 'Xinvalidarg')
431 call assert_fails('so Xinvalidarg', 'E118:')
432 let l =<< trim END
433 def! FArgErr(): float
434 return ceil()
435 enddef
436 END
437 call writefile(l, 'Xinvalidarg')
438 call assert_fails('so Xinvalidarg', 'E119:')
439 call delete('Xinvalidarg')
440endfunc
441
442let s:funcResult = 0
443
444def FuncNoArgNoRet()
445 funcResult = 11
446enddef
447
448def FuncNoArgRetNumber(): number
449 funcResult = 22
450 return 1234
451enddef
452
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200453def FuncNoArgRetString(): string
454 funcResult = 45
455 return 'text'
456enddef
457
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200458def FuncOneArgNoRet(arg: number)
459 funcResult = arg
460enddef
461
462def FuncOneArgRetNumber(arg: number): number
463 funcResult = arg
464 return arg
465enddef
466
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200467def FuncTwoArgNoRet(one: bool, two: number)
468 funcResult = two
469enddef
470
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200471def FuncOneArgRetString(arg: string): string
472 return arg
473enddef
474
Bram Moolenaar89228602020-04-05 22:14:54 +0200475def FuncOneArgRetAny(arg: any): any
476 return arg
477enddef
478
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200479def Test_func_type()
480 let Ref1: func()
481 funcResult = 0
482 Ref1 = FuncNoArgNoRet
483 Ref1()
484 assert_equal(11, funcResult)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200485
486 let Ref2: func
487 funcResult = 0
488 Ref2 = FuncNoArgNoRet
489 Ref2()
490 assert_equal(11, funcResult)
491
492 funcResult = 0
493 Ref2 = FuncOneArgNoRet
494 Ref2(12)
495 assert_equal(12, funcResult)
496
497 funcResult = 0
498 Ref2 = FuncNoArgRetNumber
499 assert_equal(1234, Ref2())
500 assert_equal(22, funcResult)
501
502 funcResult = 0
503 Ref2 = FuncOneArgRetNumber
504 assert_equal(13, Ref2(13))
505 assert_equal(13, funcResult)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200506enddef
507
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200508def Test_func_type_part()
509 let RefVoid: func: void
510 RefVoid = FuncNoArgNoRet
511 RefVoid = FuncOneArgNoRet
512 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
513 CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
514
515 let RefAny: func(): any
516 RefAny = FuncNoArgRetNumber
517 RefAny = FuncNoArgRetString
518 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
519 CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
520
521 let RefNr: func: number
522 RefNr = FuncNoArgRetNumber
523 RefNr = FuncOneArgRetNumber
524 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
525 CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
526
527 let RefStr: func: string
528 RefStr = FuncNoArgRetString
529 RefStr = FuncOneArgRetString
530 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
531 CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
532enddef
533
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200534def Test_func_type_fails()
535 CheckDefFailure(['let ref1: func()'], 'E704:')
536
537 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
538 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
539 CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
Bram Moolenaar08938ee2020-04-11 23:17:17 +0200540 CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
541 CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
542 CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
543
544 call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
545 call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
546 call CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E740:')
547 call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200548enddef
549
Bram Moolenaar89228602020-04-05 22:14:54 +0200550def Test_func_return_type()
551 let nr: number
552 nr = FuncNoArgRetNumber()
553 assert_equal(1234, nr)
554
555 nr = FuncOneArgRetAny(122)
556 assert_equal(122, nr)
557
558 let str: string
559 str = FuncOneArgRetAny('yes')
560 assert_equal('yes', str)
561
562 CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
563enddef
564
Bram Moolenaar5e774c72020-04-12 21:53:00 +0200565def MultiLine(
566 arg1: string,
567 arg2 = 1234,
568 ...rest: list<string>
569 ): string
570 return arg1 .. arg2 .. join(rest, '-')
571enddef
572
Bram Moolenaar2c330432020-04-13 14:41:35 +0200573def MultiLineComment(
574 arg1: string, # comment
575 arg2 = 1234, # comment
576 ...rest: list<string> # comment
577 ): string # comment
578 return arg1 .. arg2 .. join(rest, '-')
579enddef
580
Bram Moolenaar5e774c72020-04-12 21:53:00 +0200581def Test_multiline()
582 assert_equal('text1234', MultiLine('text'))
583 assert_equal('text777', MultiLine('text', 777))
584 assert_equal('text777one', MultiLine('text', 777, 'one'))
585 assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
586enddef
587
Bram Moolenaar23e03252020-04-12 22:22:31 +0200588func Test_multiline_not_vim9()
589 call assert_equal('text1234', MultiLine('text'))
590 call assert_equal('text777', MultiLine('text', 777))
591 call assert_equal('text777one', MultiLine('text', 777, 'one'))
592 call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
593endfunc
594
Bram Moolenaar5e774c72020-04-12 21:53:00 +0200595
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200596" When using CheckScriptFailure() for the below test, E1010 is generated instead
597" of E1056.
598func Test_E1056_1059()
599 let caught_1056 = 0
600 try
601 def F():
602 return 1
603 enddef
604 catch /E1056:/
605 let caught_1056 = 1
606 endtry
607 call assert_equal(1, caught_1056)
608
609 let caught_1059 = 0
610 try
611 def F5(items : list)
612 echo 'a'
613 enddef
614 catch /E1059:/
615 let caught_1059 = 1
616 endtry
617 call assert_equal(1, caught_1059)
618endfunc
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200619
620" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker