blob: 3212c3de20b0f9b4136a867497dbc9455d1ffc6f [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
Bram Moolenaar401d9ff2020-02-19 18:14:44 +010032let g:existing = 'yes'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010033
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010034def Test_assignment()
35 let bool1: bool = true
36 assert_equal(v:true, bool1)
37 let bool2: bool = false
38 assert_equal(v:false, bool2)
39
40 let list1: list<string> = ['sdf', 'asdf']
41 let list2: list<number> = [1, 2, 3]
42
43 " TODO: does not work yet
44 " let listS: list<string> = []
45 " let listN: list<number> = []
46
47 let dict1: dict<string> = #{key: 'value'}
48 let dict2: dict<number> = #{one: 1, two: 2}
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010049
Bram Moolenaar401d9ff2020-02-19 18:14:44 +010050 g:newvar = 'new'
51 assert_equal('new', g:newvar)
52
53 assert_equal('yes', g:existing)
54 g:existing = 'no'
55 assert_equal('no', g:existing)
56
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010057 v:char = 'abc'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010058 assert_equal('abc', v:char)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010059
60 $ENVVAR = 'foobar'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010061 assert_equal('foobar', $ENVVAR)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010062 $ENVVAR = ''
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010063
Bram Moolenaarfd1823e2020-02-19 20:23:11 +010064 s:appendToMe ..= 'yyy'
65 assert_equal('xxxyyy', s:appendToMe)
66 s:addToMe += 222
67 assert_equal(333, s:addToMe)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +010068 s:newVar = 'new'
69 assert_equal('new', s:newVar)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010070enddef
71
72func Test_assignment_failure()
73 call CheckDefFailure(['let var=234'], 'E1004:')
74 call CheckDefFailure(['let var =234'], 'E1004:')
75 call CheckDefFailure(['let var= 234'], 'E1004:')
76
77 call CheckDefFailure(['let true = 1'], 'E1034:')
78 call CheckDefFailure(['let false = 1'], 'E1034:')
79
80 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
81 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
82
83 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
84 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
85
86 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
87 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
88endfunc
89
90func Test_const()
91 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
92 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
93 call CheckDefFailure(['const two'], 'E1021:')
94endfunc
95
96def Test_block()
97 let outer = 1
98 {
99 let inner = 2
100 assert_equal(1, outer)
101 assert_equal(2, inner)
102 }
103 assert_equal(1, outer)
104enddef
105
106func Test_block_failure()
107 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
108endfunc
109
110def ReturnString(): string
111 return 'string'
112enddef
113
114def ReturnNumber(): number
115 return 123
116enddef
117
118def Test_return_string()
119 assert_equal('string', ReturnString())
120 assert_equal(123, ReturnNumber())
121enddef
122
123func Increment()
124 let g:counter += 1
125endfunc
126
127def Test_call_ufunc_count()
128 g:counter = 1
129 Increment()
130 Increment()
131 Increment()
132 " works with and without :call
133 assert_equal(4, g:counter)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100134 call assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135 unlet g:counter
136enddef
137
138def MyVarargs(arg: string, ...rest: list<string>): string
139 let res = arg
140 for s in rest
141 res ..= ',' .. s
142 endfor
143 return res
144enddef
145
146def Test_call_varargs()
147 assert_equal('one', MyVarargs('one'))
148 assert_equal('one,two', MyVarargs('one', 'two'))
149 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
150enddef
151
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100152def MyDefaultArgs(name = 'string'): string
153 return name
154enddef
155
156def Test_call_default_args()
157 assert_equal('string', MyDefaultArgs())
158 assert_equal('one', MyDefaultArgs('one'))
159 assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
160enddef
161
162func Test_call_default_args_from_func()
163 call assert_equal('string', MyDefaultArgs())
164 call assert_equal('one', MyDefaultArgs('one'))
165 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
166endfunc
167
168" Default arg and varargs
169def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
170 let res = one .. ',' .. two
171 for s in rest
172 res ..= ',' .. s
173 endfor
174 return res
175enddef
176
177def Test_call_def_varargs()
178 call assert_fails('call MyDefVarargs()', 'E119:')
179 assert_equal('one,foo', MyDefVarargs('one'))
180 assert_equal('one,two', MyDefVarargs('one', 'two'))
181 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
182enddef
183
184
Bram Moolenaar26e117e2020-02-04 21:24:15 +0100185"def Test_call_func_defined_later()
186" call assert_equal('one', DefineLater('one'))
187" call assert_fails('call NotDefined("one")', 'E99:')
188"enddef
189
190func DefineLater(arg)
191 return a:arg
192endfunc
193
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100194def Test_return_type_wrong()
Bram Moolenaar978d1702020-01-26 17:38:12 +0100195 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
196 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
197 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
198 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100199enddef
200
Bram Moolenaarbfe12042020-02-04 21:54:07 +0100201def Test_arg_type_wrong()
202 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
203enddef
204
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100205def Test_try_catch()
206 let l = []
207 try
208 add(l, '1')
209 throw 'wrong'
210 add(l, '2')
211 catch
212 add(l, v:exception)
213 finally
214 add(l, '3')
215 endtry
216 assert_equal(['1', 'wrong', '3'], l)
217enddef
218
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100219def ThrowFromDef()
220 throw 'getout'
221enddef
222
223func CatchInFunc()
224 try
225 call ThrowFromDef()
226 catch
227 let g:thrown_func = v:exception
228 endtry
229endfunc
230
231def CatchInDef()
232 try
233 ThrowFromDef()
234 catch
235 g:thrown_def = v:exception
236 endtry
237enddef
238
Bram Moolenaarf575adf2020-02-20 20:41:06 +0100239def ReturnFinally(): string
240 try
241 return 'intry'
242 finally
243 g:in_finally = 'finally'
244 endtry
245 return 'end'
246enddef
247
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100248def Test_try_catch_nested()
249 CatchInFunc()
250 assert_equal('getout', g:thrown_func)
251
252 CatchInDef()
253 assert_equal('getout', g:thrown_def)
Bram Moolenaarf575adf2020-02-20 20:41:06 +0100254
255 assert_equal('intry', ReturnFinally())
256 assert_equal('finally', g:in_finally)
257enddef
258
259def Test_try_catch_match()
260 let seq = 'a'
261 try
262 throw 'something'
263 catch /nothing/
264 seq ..= 'x'
265 catch /some/
266 seq ..= 'b'
267 catch /asdf/
268 seq ..= 'x'
269 finally
270 seq ..= 'c'
271 endtry
272 assert_equal('abc', seq)
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100273enddef
274
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275let s:export_script_lines =<< trim END
276 vim9script
277 let name: string = 'bob'
278 def Concat(arg: string): string
279 return name .. arg
280 enddef
281 let g:result = Concat('bie')
282 let g:localname = name
283
284 export const CONST = 1234
285 export let exported = 9876
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100286 export let exp_name = 'John'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100287 export def Exported(): string
288 return 'Exported'
289 enddef
290END
291
292def Test_vim9script()
293 let import_script_lines =<< trim END
294 vim9script
295 import {exported, Exported} from './Xexport.vim'
296 g:imported = exported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100297 exported += 3
298 g:imported_added = exported
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100299 g:imported_func = Exported()
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100300
301 import {exp_name} from './Xexport.vim'
302 g:imported_name = exp_name
303 exp_name ..= ' Doe'
304 g:imported_name_appended = exp_name
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100305 END
306
307 writefile(import_script_lines, 'Ximport.vim')
308 writefile(s:export_script_lines, 'Xexport.vim')
309
310 source Ximport.vim
311
312 assert_equal('bobbie', g:result)
313 assert_equal('bob', g:localname)
314 assert_equal(9876, g:imported)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100315 assert_equal(9879, g:imported_added)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100316 assert_equal('Exported', g:imported_func)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100317 assert_equal('John', g:imported_name)
318 assert_equal('John Doe', g:imported_name_appended)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100319 assert_false(exists('g:name'))
320
321 unlet g:result
322 unlet g:localname
323 unlet g:imported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100324 unlet g:imported_added
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100325 unlet g:imported_func
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100326 unlet g:imported_name g:imported_name_appended
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100327 delete('Ximport.vim')
328 delete('Xexport.vim')
329
330 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
331 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
332enddef
333
334def Test_vim9script_call()
335 let lines =<< trim END
336 vim9script
337 let var = ''
338 def MyFunc(arg: string)
339 var = arg
340 enddef
341 MyFunc('foobar')
342 assert_equal('foobar', var)
343
344 let str = 'barfoo'
345 str->MyFunc()
346 assert_equal('barfoo', var)
347
348 let g:value = 'value'
349 g:value->MyFunc()
350 assert_equal('value', var)
351
352 let listvar = []
353 def ListFunc(arg: list<number>)
354 listvar = arg
355 enddef
356 [1, 2, 3]->ListFunc()
357 assert_equal([1, 2, 3], listvar)
358
359 let dictvar = {}
360 def DictFunc(arg: dict<number>)
361 dictvar = arg
362 enddef
363 {'a': 1, 'b': 2}->DictFunc()
364 assert_equal(#{a: 1, b: 2}, dictvar)
365 #{a: 3, b: 4}->DictFunc()
366 assert_equal(#{a: 3, b: 4}, dictvar)
367 END
368 writefile(lines, 'Xcall.vim')
369 source Xcall.vim
370 delete('Xcall.vim')
371enddef
372
373def Test_vim9script_call_fail_decl()
374 let lines =<< trim END
375 vim9script
376 let var = ''
377 def MyFunc(arg: string)
378 let var = 123
379 enddef
380 END
381 writefile(lines, 'Xcall_decl.vim')
382 assert_fails('source Xcall_decl.vim', 'E1054:')
383 delete('Xcall_decl.vim')
384enddef
385
386def Test_vim9script_call_fail_const()
387 let lines =<< trim END
388 vim9script
389 const var = ''
390 def MyFunc(arg: string)
391 var = 'asdf'
392 enddef
393 END
394 writefile(lines, 'Xcall_const.vim')
395 assert_fails('source Xcall_const.vim', 'E46:')
396 delete('Xcall_const.vim')
397enddef
398
399def Test_vim9script_reload()
400 let lines =<< trim END
401 vim9script
402 const var = ''
403 let valone = 1234
404 def MyFunc(arg: string)
405 valone = 5678
406 enddef
407 END
408 let morelines =<< trim END
409 let valtwo = 222
410 export def GetValtwo(): number
411 return valtwo
412 enddef
413 END
414 writefile(lines + morelines, 'Xreload.vim')
415 source Xreload.vim
416 source Xreload.vim
417 source Xreload.vim
418
419 let testlines =<< trim END
420 vim9script
421 def TheFunc()
422 import GetValtwo from './Xreload.vim'
423 assert_equal(222, GetValtwo())
424 enddef
425 TheFunc()
426 END
427 writefile(testlines, 'Ximport.vim')
428 source Ximport.vim
429
430 " test that when not using "morelines" valtwo is still defined
431 " need to source Xreload.vim again, import doesn't reload a script
432 writefile(lines, 'Xreload.vim')
433 source Xreload.vim
434 source Ximport.vim
435
436 " cannot declare a var twice
437 lines =<< trim END
438 vim9script
439 let valone = 1234
440 let valone = 5678
441 END
442 writefile(lines, 'Xreload.vim')
443 assert_fails('source Xreload.vim', 'E1041:')
444
445 delete('Xreload.vim')
446 delete('Ximport.vim')
447enddef
448
449def Test_import_absolute()
450 let import_lines = [
451 \ 'vim9script',
452 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100453 \ 'def UseExported()',
454 \ ' g:imported_abs = exported',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100455 \ ' exported = 8888',
456 \ ' g:imported_after = exported',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100457 \ 'enddef',
458 \ 'UseExported()',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100459 \ 'g:import_disassembled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100460 \ ]
461 writefile(import_lines, 'Ximport_abs.vim')
462 writefile(s:export_script_lines, 'Xexport_abs.vim')
463
464 source Ximport_abs.vim
465
466 assert_equal(9876, g:imported_abs)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100467 assert_equal(8888, g:imported_after)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100468 assert_match('<SNR>\d\+_UseExported.*'
469 \ .. 'g:imported_abs = exported.*'
470 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100471 \ .. '1 STOREG g:imported_abs.*'
472 \ .. 'exported = 8888.*'
473 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
474 \ .. 'g:imported_after = exported.*'
475 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
476 \ .. '5 STOREG g:imported_after.*'
477 \, g:import_disassembled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100478 unlet g:imported_abs
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100479 unlet g:import_disassembled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100480
481 delete('Ximport_abs.vim')
482 delete('Xexport_abs.vim')
483enddef
484
485def Test_import_rtp()
486 let import_lines = [
487 \ 'vim9script',
488 \ 'import exported from "Xexport_rtp.vim"',
489 \ 'g:imported_rtp = exported',
490 \ ]
491 writefile(import_lines, 'Ximport_rtp.vim')
492 mkdir('import')
493 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
494
495 let save_rtp = &rtp
496 &rtp = getcwd()
497 source Ximport_rtp.vim
498 &rtp = save_rtp
499
500 assert_equal(9876, g:imported_rtp)
501 unlet g:imported_rtp
502
503 delete('Ximport_rtp.vim')
504 delete('import/Xexport_rtp.vim')
505 delete('import', 'd')
506enddef
507
508def Test_fixed_size_list()
509 " will be allocated as one piece of memory, check that changes work
510 let l = [1, 2, 3, 4]
511 l->remove(0)
512 l->add(5)
513 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100514 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100515enddef
516
Bram Moolenaar673660a2020-01-26 16:50:05 +0100517" Test that inside :function a Python function can be defined, :def is not
518" recognized.
519func Test_function_python()
520 CheckFeature python3
521 let py = 'python3'
522 execute py "<< EOF"
523def do_something():
524 return 1
525EOF
526endfunc
527
Bram Moolenaar158906c2020-02-06 20:39:45 +0100528def IfElse(what: number): string
529 let res = ''
530 if what == 1
531 res = "one"
532 elseif what == 2
533 res = "two"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100534 else
Bram Moolenaar158906c2020-02-06 20:39:45 +0100535 res = "three"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100536 endif
Bram Moolenaar158906c2020-02-06 20:39:45 +0100537 return res
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100538enddef
539
Bram Moolenaar158906c2020-02-06 20:39:45 +0100540def Test_if_elseif_else()
541 assert_equal('one', IfElse(1))
542 assert_equal('two', IfElse(2))
543 assert_equal('three', IfElse(3))
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100544enddef
545
Bram Moolenaar63ce4842020-02-19 15:46:48 +0100546def Test_delfunc()
547 let lines =<< trim END
548 vim9script
549 def GoneSoon()
550 echo 'hello'
551 enddef
552
553 def CallGoneSoon()
554 GoneSoon()
555 enddef
556
557 delfunc GoneSoon
558 CallGoneSoon()
559 END
560 writefile(lines, 'XToDelFunc')
561 assert_fails('so XToDelFunc', 'E933')
562 assert_fails('so XToDelFunc', 'E933')
563
564 delete('XToDelFunc')
565enddef
566
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100567
568" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker