blob: 5dbc9f9ea7772d8ea016caf51828741368928b65 [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
Bram Moolenaar436472f2020-02-20 22:54:43 +010043 let listS: list<string> = []
44 let listN: list<number> = []
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010045
46 let dict1: dict<string> = #{key: 'value'}
47 let dict2: dict<number> = #{one: 1, two: 2}
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010048
Bram Moolenaar401d9ff2020-02-19 18:14:44 +010049 g:newvar = 'new'
50 assert_equal('new', g:newvar)
51
52 assert_equal('yes', g:existing)
53 g:existing = 'no'
54 assert_equal('no', g:existing)
55
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010056 v:char = 'abc'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010057 assert_equal('abc', v:char)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010058
59 $ENVVAR = 'foobar'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010060 assert_equal('foobar', $ENVVAR)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010061 $ENVVAR = ''
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010062
Bram Moolenaarfd1823e2020-02-19 20:23:11 +010063 s:appendToMe ..= 'yyy'
64 assert_equal('xxxyyy', s:appendToMe)
65 s:addToMe += 222
66 assert_equal(333, s:addToMe)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +010067 s:newVar = 'new'
68 assert_equal('new', s:newVar)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010069enddef
70
71func Test_assignment_failure()
72 call CheckDefFailure(['let var=234'], 'E1004:')
73 call CheckDefFailure(['let var =234'], 'E1004:')
74 call CheckDefFailure(['let var= 234'], 'E1004:')
75
76 call CheckDefFailure(['let true = 1'], 'E1034:')
77 call CheckDefFailure(['let false = 1'], 'E1034:')
78
79 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
80 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
81
82 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
83 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
84
85 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
86 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
87endfunc
88
89func Test_const()
90 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
91 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
92 call CheckDefFailure(['const two'], 'E1021:')
93endfunc
94
95def Test_block()
96 let outer = 1
97 {
98 let inner = 2
99 assert_equal(1, outer)
100 assert_equal(2, inner)
101 }
102 assert_equal(1, outer)
103enddef
104
105func Test_block_failure()
106 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
107endfunc
108
109def ReturnString(): string
110 return 'string'
111enddef
112
113def ReturnNumber(): number
114 return 123
115enddef
116
Bram Moolenaar09f28f42020-02-20 23:08:34 +0100117let g:notNumber = 'string'
118
119def ReturnGlobal(): number
120 return g:notNumber
121enddef
122
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100123def Test_return_string()
124 assert_equal('string', ReturnString())
125 assert_equal(123, ReturnNumber())
Bram Moolenaar09f28f42020-02-20 23:08:34 +0100126 assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100127enddef
128
129func Increment()
130 let g:counter += 1
131endfunc
132
133def Test_call_ufunc_count()
134 g:counter = 1
135 Increment()
136 Increment()
137 Increment()
138 " works with and without :call
139 assert_equal(4, g:counter)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100140 call assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100141 unlet g:counter
142enddef
143
144def MyVarargs(arg: string, ...rest: list<string>): string
145 let res = arg
146 for s in rest
147 res ..= ',' .. s
148 endfor
149 return res
150enddef
151
152def Test_call_varargs()
153 assert_equal('one', MyVarargs('one'))
154 assert_equal('one,two', MyVarargs('one', 'two'))
155 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
156enddef
157
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100158def MyDefaultArgs(name = 'string'): string
159 return name
160enddef
161
162def Test_call_default_args()
163 assert_equal('string', MyDefaultArgs())
164 assert_equal('one', MyDefaultArgs('one'))
165 assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
166enddef
167
168func Test_call_default_args_from_func()
169 call assert_equal('string', MyDefaultArgs())
170 call assert_equal('one', MyDefaultArgs('one'))
171 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
172endfunc
173
174" Default arg and varargs
175def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
176 let res = one .. ',' .. two
177 for s in rest
178 res ..= ',' .. s
179 endfor
180 return res
181enddef
182
183def Test_call_def_varargs()
184 call assert_fails('call MyDefVarargs()', 'E119:')
185 assert_equal('one,foo', MyDefVarargs('one'))
186 assert_equal('one,two', MyDefVarargs('one', 'two'))
187 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
188enddef
189
190
Bram Moolenaar26e117e2020-02-04 21:24:15 +0100191"def Test_call_func_defined_later()
192" call assert_equal('one', DefineLater('one'))
193" call assert_fails('call NotDefined("one")', 'E99:')
194"enddef
195
196func DefineLater(arg)
197 return a:arg
198endfunc
199
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100200def Test_return_type_wrong()
Bram Moolenaar978d1702020-01-26 17:38:12 +0100201 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
202 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
203 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
204 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100205enddef
206
Bram Moolenaarbfe12042020-02-04 21:54:07 +0100207def Test_arg_type_wrong()
208 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
209enddef
210
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100211def Test_try_catch()
212 let l = []
213 try
214 add(l, '1')
215 throw 'wrong'
216 add(l, '2')
217 catch
218 add(l, v:exception)
219 finally
220 add(l, '3')
221 endtry
222 assert_equal(['1', 'wrong', '3'], l)
223enddef
224
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100225def ThrowFromDef()
226 throw 'getout'
227enddef
228
229func CatchInFunc()
230 try
231 call ThrowFromDef()
232 catch
233 let g:thrown_func = v:exception
234 endtry
235endfunc
236
237def CatchInDef()
238 try
239 ThrowFromDef()
240 catch
241 g:thrown_def = v:exception
242 endtry
243enddef
244
Bram Moolenaarf575adf2020-02-20 20:41:06 +0100245def ReturnFinally(): string
246 try
247 return 'intry'
248 finally
249 g:in_finally = 'finally'
250 endtry
251 return 'end'
252enddef
253
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100254def Test_try_catch_nested()
255 CatchInFunc()
256 assert_equal('getout', g:thrown_func)
257
258 CatchInDef()
259 assert_equal('getout', g:thrown_def)
Bram Moolenaarf575adf2020-02-20 20:41:06 +0100260
261 assert_equal('intry', ReturnFinally())
262 assert_equal('finally', g:in_finally)
263enddef
264
265def Test_try_catch_match()
266 let seq = 'a'
267 try
268 throw 'something'
269 catch /nothing/
270 seq ..= 'x'
271 catch /some/
272 seq ..= 'b'
273 catch /asdf/
274 seq ..= 'x'
275 finally
276 seq ..= 'c'
277 endtry
278 assert_equal('abc', seq)
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100279enddef
280
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100281let s:export_script_lines =<< trim END
282 vim9script
283 let name: string = 'bob'
284 def Concat(arg: string): string
285 return name .. arg
286 enddef
287 let g:result = Concat('bie')
288 let g:localname = name
289
290 export const CONST = 1234
291 export let exported = 9876
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100292 export let exp_name = 'John'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100293 export def Exported(): string
294 return 'Exported'
295 enddef
296END
297
298def Test_vim9script()
299 let import_script_lines =<< trim END
300 vim9script
301 import {exported, Exported} from './Xexport.vim'
302 g:imported = exported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100303 exported += 3
304 g:imported_added = exported
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100305 g:imported_func = Exported()
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100306
307 import {exp_name} from './Xexport.vim'
308 g:imported_name = exp_name
309 exp_name ..= ' Doe'
310 g:imported_name_appended = exp_name
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100311 END
312
313 writefile(import_script_lines, 'Ximport.vim')
314 writefile(s:export_script_lines, 'Xexport.vim')
315
316 source Ximport.vim
317
318 assert_equal('bobbie', g:result)
319 assert_equal('bob', g:localname)
320 assert_equal(9876, g:imported)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100321 assert_equal(9879, g:imported_added)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100322 assert_equal('Exported', g:imported_func)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100323 assert_equal('John', g:imported_name)
324 assert_equal('John Doe', g:imported_name_appended)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100325 assert_false(exists('g:name'))
326
327 unlet g:result
328 unlet g:localname
329 unlet g:imported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100330 unlet g:imported_added
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100331 unlet g:imported_func
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100332 unlet g:imported_name g:imported_name_appended
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100333 delete('Ximport.vim')
334 delete('Xexport.vim')
335
336 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
337 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
338enddef
339
340def Test_vim9script_call()
341 let lines =<< trim END
342 vim9script
343 let var = ''
344 def MyFunc(arg: string)
345 var = arg
346 enddef
347 MyFunc('foobar')
348 assert_equal('foobar', var)
349
350 let str = 'barfoo'
351 str->MyFunc()
352 assert_equal('barfoo', var)
353
354 let g:value = 'value'
355 g:value->MyFunc()
356 assert_equal('value', var)
357
358 let listvar = []
359 def ListFunc(arg: list<number>)
360 listvar = arg
361 enddef
362 [1, 2, 3]->ListFunc()
363 assert_equal([1, 2, 3], listvar)
364
365 let dictvar = {}
366 def DictFunc(arg: dict<number>)
367 dictvar = arg
368 enddef
369 {'a': 1, 'b': 2}->DictFunc()
370 assert_equal(#{a: 1, b: 2}, dictvar)
371 #{a: 3, b: 4}->DictFunc()
372 assert_equal(#{a: 3, b: 4}, dictvar)
Bram Moolenaar0c6ceaf2020-02-22 18:36:32 +0100373
374 ('text')->MyFunc()
375 assert_equal('text', var)
376 ("some")->MyFunc()
377 assert_equal('some', var)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100378 END
379 writefile(lines, 'Xcall.vim')
380 source Xcall.vim
381 delete('Xcall.vim')
382enddef
383
384def Test_vim9script_call_fail_decl()
385 let lines =<< trim END
386 vim9script
387 let var = ''
388 def MyFunc(arg: string)
389 let var = 123
390 enddef
391 END
392 writefile(lines, 'Xcall_decl.vim')
393 assert_fails('source Xcall_decl.vim', 'E1054:')
394 delete('Xcall_decl.vim')
395enddef
396
397def Test_vim9script_call_fail_const()
398 let lines =<< trim END
399 vim9script
400 const var = ''
401 def MyFunc(arg: string)
402 var = 'asdf'
403 enddef
404 END
405 writefile(lines, 'Xcall_const.vim')
406 assert_fails('source Xcall_const.vim', 'E46:')
407 delete('Xcall_const.vim')
408enddef
409
410def Test_vim9script_reload()
411 let lines =<< trim END
412 vim9script
413 const var = ''
414 let valone = 1234
415 def MyFunc(arg: string)
416 valone = 5678
417 enddef
418 END
419 let morelines =<< trim END
420 let valtwo = 222
421 export def GetValtwo(): number
422 return valtwo
423 enddef
424 END
425 writefile(lines + morelines, 'Xreload.vim')
426 source Xreload.vim
427 source Xreload.vim
428 source Xreload.vim
429
430 let testlines =<< trim END
431 vim9script
432 def TheFunc()
433 import GetValtwo from './Xreload.vim'
434 assert_equal(222, GetValtwo())
435 enddef
436 TheFunc()
437 END
438 writefile(testlines, 'Ximport.vim')
439 source Ximport.vim
440
441 " test that when not using "morelines" valtwo is still defined
442 " need to source Xreload.vim again, import doesn't reload a script
443 writefile(lines, 'Xreload.vim')
444 source Xreload.vim
445 source Ximport.vim
446
447 " cannot declare a var twice
448 lines =<< trim END
449 vim9script
450 let valone = 1234
451 let valone = 5678
452 END
453 writefile(lines, 'Xreload.vim')
454 assert_fails('source Xreload.vim', 'E1041:')
455
456 delete('Xreload.vim')
457 delete('Ximport.vim')
458enddef
459
460def Test_import_absolute()
461 let import_lines = [
462 \ 'vim9script',
463 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100464 \ 'def UseExported()',
465 \ ' g:imported_abs = exported',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100466 \ ' exported = 8888',
467 \ ' g:imported_after = exported',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100468 \ 'enddef',
469 \ 'UseExported()',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100470 \ 'g:import_disassembled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100471 \ ]
472 writefile(import_lines, 'Ximport_abs.vim')
473 writefile(s:export_script_lines, 'Xexport_abs.vim')
474
475 source Ximport_abs.vim
476
477 assert_equal(9876, g:imported_abs)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100478 assert_equal(8888, g:imported_after)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100479 assert_match('<SNR>\d\+_UseExported.*'
480 \ .. 'g:imported_abs = exported.*'
481 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100482 \ .. '1 STOREG g:imported_abs.*'
483 \ .. 'exported = 8888.*'
484 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
485 \ .. 'g:imported_after = exported.*'
486 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
487 \ .. '5 STOREG g:imported_after.*'
488 \, g:import_disassembled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100489 unlet g:imported_abs
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100490 unlet g:import_disassembled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100491
492 delete('Ximport_abs.vim')
493 delete('Xexport_abs.vim')
494enddef
495
496def Test_import_rtp()
497 let import_lines = [
498 \ 'vim9script',
499 \ 'import exported from "Xexport_rtp.vim"',
500 \ 'g:imported_rtp = exported',
501 \ ]
502 writefile(import_lines, 'Ximport_rtp.vim')
503 mkdir('import')
504 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
505
506 let save_rtp = &rtp
507 &rtp = getcwd()
508 source Ximport_rtp.vim
509 &rtp = save_rtp
510
511 assert_equal(9876, g:imported_rtp)
512 unlet g:imported_rtp
513
514 delete('Ximport_rtp.vim')
515 delete('import/Xexport_rtp.vim')
516 delete('import', 'd')
517enddef
518
519def Test_fixed_size_list()
520 " will be allocated as one piece of memory, check that changes work
521 let l = [1, 2, 3, 4]
522 l->remove(0)
523 l->add(5)
524 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100525 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100526enddef
527
Bram Moolenaar673660a2020-01-26 16:50:05 +0100528" Test that inside :function a Python function can be defined, :def is not
529" recognized.
530func Test_function_python()
531 CheckFeature python3
532 let py = 'python3'
533 execute py "<< EOF"
534def do_something():
535 return 1
536EOF
537endfunc
538
Bram Moolenaar158906c2020-02-06 20:39:45 +0100539def IfElse(what: number): string
540 let res = ''
541 if what == 1
542 res = "one"
543 elseif what == 2
544 res = "two"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100545 else
Bram Moolenaar158906c2020-02-06 20:39:45 +0100546 res = "three"
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100547 endif
Bram Moolenaar158906c2020-02-06 20:39:45 +0100548 return res
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100549enddef
550
Bram Moolenaar158906c2020-02-06 20:39:45 +0100551def Test_if_elseif_else()
552 assert_equal('one', IfElse(1))
553 assert_equal('two', IfElse(2))
554 assert_equal('three', IfElse(3))
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100555enddef
556
Bram Moolenaar63ce4842020-02-19 15:46:48 +0100557def Test_delfunc()
558 let lines =<< trim END
559 vim9script
560 def GoneSoon()
561 echo 'hello'
562 enddef
563
564 def CallGoneSoon()
565 GoneSoon()
566 enddef
567
568 delfunc GoneSoon
569 CallGoneSoon()
570 END
571 writefile(lines, 'XToDelFunc')
572 assert_fails('so XToDelFunc', 'E933')
573 assert_fails('so XToDelFunc', 'E933')
574
575 delete('XToDelFunc')
576enddef
577
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +0100578def Test_substitute_cmd()
579 new
580 setline(1, 'something')
581 :substitute(some(other(
582 assert_equal('otherthing', getline(1))
583enddef
584
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585
586" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker