blob: ae33935072c056fa623c4d4af8ae0d62e76d5cf0 [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001" Test various aspects of the Vim9 script language.
2
Bram Moolenaar673660a2020-01-26 16:50:05 +01003source check.vim
4
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005" Check that "lines" inside ":def" results in an "error" message.
6func CheckDefFailure(lines, error)
Bram Moolenaar978d1702020-01-26 17:38:12 +01007 call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008 call assert_fails('so Xdef', a:error, a:lines)
9 call delete('Xdef')
10endfunc
11
12func CheckScriptFailure(lines, error)
13 call writefile(a:lines, 'Xdef')
14 call assert_fails('so Xdef', a:error, a:lines)
15 call delete('Xdef')
16endfunc
17
18def Test_syntax()
19 let var = 234
20 let other: list<string> = ['asdf']
21enddef
22
23func Test_def_basic()
24 def SomeFunc(): string
25 return 'yes'
26 enddef
27 call assert_equal('yes', SomeFunc())
28endfunc
29
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010030let s:appendToMe = 'xxx'
31let s:addToMe = 111
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033def Test_assignment()
34 let bool1: bool = true
35 assert_equal(v:true, bool1)
36 let bool2: bool = false
37 assert_equal(v:false, bool2)
38
39 let list1: list<string> = ['sdf', 'asdf']
40 let list2: list<number> = [1, 2, 3]
41
42 " TODO: does not work yet
43 " let listS: list<string> = []
44 " let listN: list<number> = []
45
46 let dict1: dict<string> = #{key: 'value'}
47 let dict2: dict<number> = #{one: 1, two: 2}
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010048
49 v:char = 'abc'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010050 assert_equal('abc', v:char)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010051
52 $ENVVAR = 'foobar'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010053 assert_equal('foobar', $ENVVAR)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010054 $ENVVAR = ''
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010055
56 appendToMe ..= 'yyy'
57 assert_equal('xxxyyy', appendToMe)
58 addToMe += 222
59 assert_equal(333, addToMe)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010060enddef
61
62func Test_assignment_failure()
63 call CheckDefFailure(['let var=234'], 'E1004:')
64 call CheckDefFailure(['let var =234'], 'E1004:')
65 call CheckDefFailure(['let var= 234'], 'E1004:')
66
67 call CheckDefFailure(['let true = 1'], 'E1034:')
68 call CheckDefFailure(['let false = 1'], 'E1034:')
69
70 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
71 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
72
73 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
74 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
75
76 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
77 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
78endfunc
79
80func Test_const()
81 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
82 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
83 call CheckDefFailure(['const two'], 'E1021:')
84endfunc
85
86def Test_block()
87 let outer = 1
88 {
89 let inner = 2
90 assert_equal(1, outer)
91 assert_equal(2, inner)
92 }
93 assert_equal(1, outer)
94enddef
95
96func Test_block_failure()
97 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
98endfunc
99
100def ReturnString(): string
101 return 'string'
102enddef
103
104def ReturnNumber(): number
105 return 123
106enddef
107
108def Test_return_string()
109 assert_equal('string', ReturnString())
110 assert_equal(123, ReturnNumber())
111enddef
112
113func Increment()
114 let g:counter += 1
115endfunc
116
117def Test_call_ufunc_count()
118 g:counter = 1
119 Increment()
120 Increment()
121 Increment()
122 " works with and without :call
123 assert_equal(4, g:counter)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100124 call assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125 unlet g:counter
126enddef
127
128def MyVarargs(arg: string, ...rest: list<string>): string
129 let res = arg
130 for s in rest
131 res ..= ',' .. s
132 endfor
133 return res
134enddef
135
136def Test_call_varargs()
137 assert_equal('one', MyVarargs('one'))
138 assert_equal('one,two', MyVarargs('one', 'two'))
139 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
140enddef
141
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100142def MyDefaultArgs(name = 'string'): string
143 return name
144enddef
145
146def Test_call_default_args()
147 assert_equal('string', MyDefaultArgs())
148 assert_equal('one', MyDefaultArgs('one'))
149 assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
150enddef
151
152func Test_call_default_args_from_func()
153 call assert_equal('string', MyDefaultArgs())
154 call assert_equal('one', MyDefaultArgs('one'))
155 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
156endfunc
157
158" Default arg and varargs
159def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
160 let res = one .. ',' .. two
161 for s in rest
162 res ..= ',' .. s
163 endfor
164 return res
165enddef
166
167def Test_call_def_varargs()
168 call assert_fails('call MyDefVarargs()', 'E119:')
169 assert_equal('one,foo', MyDefVarargs('one'))
170 assert_equal('one,two', MyDefVarargs('one', 'two'))
171 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
172enddef
173
174
Bram Moolenaar26e117e2020-02-04 21:24:15 +0100175"def Test_call_func_defined_later()
176" call assert_equal('one', DefineLater('one'))
177" call assert_fails('call NotDefined("one")', 'E99:')
178"enddef
179
180func DefineLater(arg)
181 return a:arg
182endfunc
183
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100184def Test_return_type_wrong()
Bram Moolenaar978d1702020-01-26 17:38:12 +0100185 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
186 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
187 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
188 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100189enddef
190
Bram Moolenaarbfe12042020-02-04 21:54:07 +0100191def Test_arg_type_wrong()
192 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
193enddef
194
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100195def Test_try_catch()
196 let l = []
197 try
198 add(l, '1')
199 throw 'wrong'
200 add(l, '2')
201 catch
202 add(l, v:exception)
203 finally
204 add(l, '3')
205 endtry
206 assert_equal(['1', 'wrong', '3'], l)
207enddef
208
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100209def ThrowFromDef()
210 throw 'getout'
211enddef
212
213func CatchInFunc()
214 try
215 call ThrowFromDef()
216 catch
217 let g:thrown_func = v:exception
218 endtry
219endfunc
220
221def CatchInDef()
222 try
223 ThrowFromDef()
224 catch
225 g:thrown_def = v:exception
226 endtry
227enddef
228
229def Test_try_catch_nested()
230 CatchInFunc()
231 assert_equal('getout', g:thrown_func)
232
233 CatchInDef()
234 assert_equal('getout', g:thrown_def)
235enddef
236
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100237let s:export_script_lines =<< trim END
238 vim9script
239 let name: string = 'bob'
240 def Concat(arg: string): string
241 return name .. arg
242 enddef
243 let g:result = Concat('bie')
244 let g:localname = name
245
246 export const CONST = 1234
247 export let exported = 9876
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100248 export let exp_name = 'John'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 export def Exported(): string
250 return 'Exported'
251 enddef
252END
253
254def Test_vim9script()
255 let import_script_lines =<< trim END
256 vim9script
257 import {exported, Exported} from './Xexport.vim'
258 g:imported = exported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100259 exported += 3
260 g:imported_added = exported
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100261 g:imported_func = Exported()
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100262
263 import {exp_name} from './Xexport.vim'
264 g:imported_name = exp_name
265 exp_name ..= ' Doe'
266 g:imported_name_appended = exp_name
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267 END
268
269 writefile(import_script_lines, 'Ximport.vim')
270 writefile(s:export_script_lines, 'Xexport.vim')
271
272 source Ximport.vim
273
274 assert_equal('bobbie', g:result)
275 assert_equal('bob', g:localname)
276 assert_equal(9876, g:imported)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100277 assert_equal(9879, g:imported_added)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100278 assert_equal('Exported', g:imported_func)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100279 assert_equal('John', g:imported_name)
280 assert_equal('John Doe', g:imported_name_appended)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100281 assert_false(exists('g:name'))
282
283 unlet g:result
284 unlet g:localname
285 unlet g:imported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100286 unlet g:imported_added
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100287 unlet g:imported_func
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100288 unlet g:imported_name g:imported_name_appended
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100289 delete('Ximport.vim')
290 delete('Xexport.vim')
291
292 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
293 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
294enddef
295
296def Test_vim9script_call()
297 let lines =<< trim END
298 vim9script
299 let var = ''
300 def MyFunc(arg: string)
301 var = arg
302 enddef
303 MyFunc('foobar')
304 assert_equal('foobar', var)
305
306 let str = 'barfoo'
307 str->MyFunc()
308 assert_equal('barfoo', var)
309
310 let g:value = 'value'
311 g:value->MyFunc()
312 assert_equal('value', var)
313
314 let listvar = []
315 def ListFunc(arg: list<number>)
316 listvar = arg
317 enddef
318 [1, 2, 3]->ListFunc()
319 assert_equal([1, 2, 3], listvar)
320
321 let dictvar = {}
322 def DictFunc(arg: dict<number>)
323 dictvar = arg
324 enddef
325 {'a': 1, 'b': 2}->DictFunc()
326 assert_equal(#{a: 1, b: 2}, dictvar)
327 #{a: 3, b: 4}->DictFunc()
328 assert_equal(#{a: 3, b: 4}, dictvar)
329 END
330 writefile(lines, 'Xcall.vim')
331 source Xcall.vim
332 delete('Xcall.vim')
333enddef
334
335def Test_vim9script_call_fail_decl()
336 let lines =<< trim END
337 vim9script
338 let var = ''
339 def MyFunc(arg: string)
340 let var = 123
341 enddef
342 END
343 writefile(lines, 'Xcall_decl.vim')
344 assert_fails('source Xcall_decl.vim', 'E1054:')
345 delete('Xcall_decl.vim')
346enddef
347
348def Test_vim9script_call_fail_const()
349 let lines =<< trim END
350 vim9script
351 const var = ''
352 def MyFunc(arg: string)
353 var = 'asdf'
354 enddef
355 END
356 writefile(lines, 'Xcall_const.vim')
357 assert_fails('source Xcall_const.vim', 'E46:')
358 delete('Xcall_const.vim')
359enddef
360
361def Test_vim9script_reload()
362 let lines =<< trim END
363 vim9script
364 const var = ''
365 let valone = 1234
366 def MyFunc(arg: string)
367 valone = 5678
368 enddef
369 END
370 let morelines =<< trim END
371 let valtwo = 222
372 export def GetValtwo(): number
373 return valtwo
374 enddef
375 END
376 writefile(lines + morelines, 'Xreload.vim')
377 source Xreload.vim
378 source Xreload.vim
379 source Xreload.vim
380
381 let testlines =<< trim END
382 vim9script
383 def TheFunc()
384 import GetValtwo from './Xreload.vim'
385 assert_equal(222, GetValtwo())
386 enddef
387 TheFunc()
388 END
389 writefile(testlines, 'Ximport.vim')
390 source Ximport.vim
391
392 " test that when not using "morelines" valtwo is still defined
393 " need to source Xreload.vim again, import doesn't reload a script
394 writefile(lines, 'Xreload.vim')
395 source Xreload.vim
396 source Ximport.vim
397
398 " cannot declare a var twice
399 lines =<< trim END
400 vim9script
401 let valone = 1234
402 let valone = 5678
403 END
404 writefile(lines, 'Xreload.vim')
405 assert_fails('source Xreload.vim', 'E1041:')
406
407 delete('Xreload.vim')
408 delete('Ximport.vim')
409enddef
410
411def Test_import_absolute()
412 let import_lines = [
413 \ 'vim9script',
414 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100415 \ 'def UseExported()',
416 \ ' g:imported_abs = exported',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100417 \ ' exported = 8888',
418 \ ' g:imported_after = exported',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100419 \ 'enddef',
420 \ 'UseExported()',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100421 \ 'g:import_disassembled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100422 \ ]
423 writefile(import_lines, 'Ximport_abs.vim')
424 writefile(s:export_script_lines, 'Xexport_abs.vim')
425
426 source Ximport_abs.vim
427
428 assert_equal(9876, g:imported_abs)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100429 assert_equal(8888, g:imported_after)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100430 assert_match('<SNR>\d\+_UseExported.*'
431 \ .. 'g:imported_abs = exported.*'
432 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100433 \ .. '1 STOREG g:imported_abs.*'
434 \ .. 'exported = 8888.*'
435 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
436 \ .. 'g:imported_after = exported.*'
437 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
438 \ .. '5 STOREG g:imported_after.*'
439 \, g:import_disassembled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100440 unlet g:imported_abs
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100441 unlet g:import_disassembled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100442
443 delete('Ximport_abs.vim')
444 delete('Xexport_abs.vim')
445enddef
446
447def Test_import_rtp()
448 let import_lines = [
449 \ 'vim9script',
450 \ 'import exported from "Xexport_rtp.vim"',
451 \ 'g:imported_rtp = exported',
452 \ ]
453 writefile(import_lines, 'Ximport_rtp.vim')
454 mkdir('import')
455 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
456
457 let save_rtp = &rtp
458 &rtp = getcwd()
459 source Ximport_rtp.vim
460 &rtp = save_rtp
461
462 assert_equal(9876, g:imported_rtp)
463 unlet g:imported_rtp
464
465 delete('Ximport_rtp.vim')
466 delete('import/Xexport_rtp.vim')
467 delete('import', 'd')
468enddef
469
470def Test_fixed_size_list()
471 " will be allocated as one piece of memory, check that changes work
472 let l = [1, 2, 3, 4]
473 l->remove(0)
474 l->add(5)
475 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100476 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100477enddef
478
Bram Moolenaar673660a2020-01-26 16:50:05 +0100479" Test that inside :function a Python function can be defined, :def is not
480" recognized.
481func Test_function_python()
482 CheckFeature python3
483 let py = 'python3'
484 execute py "<< EOF"
485def do_something():
486 return 1
487EOF
488endfunc
489
Bram Moolenaar158906c2020-02-06 20:39:45 +0100490def IfElse(what: number): string
491 let res = ''
492 if what == 1
493 res = "one"
494 elseif what == 2
495 res = "two"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100496 else
Bram Moolenaar158906c2020-02-06 20:39:45 +0100497 res = "three"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100498 endif
Bram Moolenaar158906c2020-02-06 20:39:45 +0100499 return res
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100500enddef
501
Bram Moolenaar158906c2020-02-06 20:39:45 +0100502def Test_if_elseif_else()
503 assert_equal('one', IfElse(1))
504 assert_equal('two', IfElse(2))
505 assert_equal('three', IfElse(3))
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100506enddef
507
Bram Moolenaar63ce4842020-02-19 15:46:48 +0100508def Test_delfunc()
509 let lines =<< trim END
510 vim9script
511 def GoneSoon()
512 echo 'hello'
513 enddef
514
515 def CallGoneSoon()
516 GoneSoon()
517 enddef
518
519 delfunc GoneSoon
520 CallGoneSoon()
521 END
522 writefile(lines, 'XToDelFunc')
523 assert_fails('so XToDelFunc', 'E933')
524 assert_fails('so XToDelFunc', 'E933')
525
526 delete('XToDelFunc')
527enddef
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529
530" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker