1" Test Vim9 assignments
2
3source check.vim
4source vim9.vim
5
6let s:appendToMe = 'xxx'
7let s:addToMe = 111
8let g:existing = 'yes'
9let g:inc_counter = 1
10let $SOME_ENV_VAR = 'some'
11let g:alist = [7]
12let g:astring = 'text'
13
14def Test_assignment_bool()
15  var bool1: bool = true
16  assert_equal(v:true, bool1)
17  var bool2: bool = false
18  assert_equal(v:false, bool2)
19
20  var bool3: bool = 0
21  assert_equal(false, bool3)
22  var bool4: bool = 1
23  assert_equal(true, bool4)
24
25  var bool5: bool = 1 && true
26  assert_equal(true, bool5)
27  var bool6: bool = 0 && 1
28  assert_equal(false, bool6)
29  var bool7: bool = 0 || 1 && true
30  assert_equal(true, bool7)
31
32  var lines =<< trim END
33    vim9script
34    def GetFlag(): bool
35      var flag: bool = 1
36      return flag
37    enddef
38    var flag: bool = GetFlag()
39    assert_equal(true, flag)
40    flag = 0
41    assert_equal(false, flag)
42    flag = 1
43    assert_equal(true, flag)
44    flag = 1 || true
45    assert_equal(true, flag)
46    flag = 1 && false
47    assert_equal(false, flag)
48  END
49  CheckScriptSuccess(lines)
50  CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
51  CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
52  CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
53  CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
54  CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
55enddef
56
57def Test_syntax()
58  var name = 234
59  var other: list<string> = ['asdf']
60enddef
61
62def Test_assignment()
63  CheckDefFailure(['var x:string'], 'E1069:')
64  CheckDefFailure(['var x:string = "x"'], 'E1069:')
65  CheckDefFailure(['var a:string = "x"'], 'E1069:')
66  CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:')
67  CheckScriptFailure(['var x = "x"'], 'E1124:')
68
69  var nr: number = 1234
70  CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
71
72  var a: number = 6 #comment
73  assert_equal(6, a)
74
75  if has('channel')
76    var chan1: channel
77    assert_equal('fail', ch_status(chan1))
78
79    var job1: job
80    assert_equal('fail', job_status(job1))
81
82    # calling job_start() is in test_vim9_fails.vim, it causes leak reports
83  endif
84  if has('float')
85    var float1: float = 3.4
86  endif
87  var Funky1: func
88  var Funky2: func = function('len')
89  var Party2: func = funcref('g:Test_syntax')
90
91  g:newvar = 'new'  #comment
92  assert_equal('new', g:newvar)
93
94  assert_equal('yes', g:existing)
95  g:existing = 'no'
96  assert_equal('no', g:existing)
97
98  v:char = 'abc'
99  assert_equal('abc', v:char)
100
101  $ENVVAR = 'foobar'
102  assert_equal('foobar', $ENVVAR)
103  $ENVVAR = ''
104
105  var lines =<< trim END
106    vim9script
107    $ENVVAR = 'barfoo'
108    assert_equal('barfoo', $ENVVAR)
109    $ENVVAR = ''
110  END
111  CheckScriptSuccess(lines)
112
113  s:appendToMe ..= 'yyy'
114  assert_equal('xxxyyy', s:appendToMe)
115  s:addToMe += 222
116  assert_equal(333, s:addToMe)
117  s:newVar = 'new'
118  assert_equal('new', s:newVar)
119
120  set ts=7
121  &ts += 1
122  assert_equal(8, &ts)
123  &ts -= 3
124  assert_equal(5, &ts)
125  &ts *= 2
126  assert_equal(10, &ts)
127  &ts /= 3
128  assert_equal(3, &ts)
129  set ts=10
130  &ts %= 4
131  assert_equal(2, &ts)
132
133  if has('float')
134    var f100: float = 100.0
135    f100 /= 5
136    assert_equal(20.0, f100)
137
138    var f200: float = 200.0
139    f200 /= 5.0
140    assert_equal(40.0, f200)
141
142    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
143  endif
144
145  lines =<< trim END
146    &ts = 6
147    &ts += 3
148    assert_equal(9, &ts)
149
150    &l:ts = 6
151    assert_equal(6, &ts)
152    &l:ts += 2
153    assert_equal(8, &ts)
154
155    &g:ts = 6
156    assert_equal(6, &g:ts)
157    &g:ts += 2
158    assert_equal(8, &g:ts)
159  END
160  CheckDefAndScriptSuccess(lines)
161
162  CheckDefFailure(['&notex += 3'], 'E113:')
163  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
164  CheckDefFailure(['&ts = [7]'], 'E1012:')
165  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
166  CheckDefFailure(['&ts = "xx"'], 'E1012:')
167  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
168  CheckDefFailure(['&path += 3'], 'E1012:')
169  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
170  # test freeing ISN_STOREOPT
171  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
172  &ts = 8
173
174  lines =<< trim END
175    var save_TI = &t_TI
176    &t_TI = ''
177    assert_equal('', &t_TI)
178    &t_TI = 'xxx'
179    assert_equal('xxx', &t_TI)
180    &t_TI = save_TI
181  END
182  CheckDefAndScriptSuccess(lines)
183
184  CheckDefFailure(['&t_TI = 123'], 'E1012:')
185  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
186
187  CheckDefFailure(['var s:var = 123'], 'E1101:')
188  CheckDefFailure(['var s:var: number'], 'E1101:')
189
190  lines =<< trim END
191    vim9script
192    def SomeFunc()
193      s:var = 123
194    enddef
195    defcompile
196  END
197  CheckScriptFailure(lines, 'E1089:')
198
199  g:inc_counter += 1
200  assert_equal(2, g:inc_counter)
201
202  $SOME_ENV_VAR ..= 'more'
203  assert_equal('somemore', $SOME_ENV_VAR)
204  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
205  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
206
207  lines =<< trim END
208    @c = 'areg'
209    @c ..= 'add'
210    assert_equal('aregadd', @c)
211  END
212  CheckDefAndScriptSuccess(lines)
213
214  CheckDefFailure(['@a += "more"'], 'E1051:')
215  CheckDefFailure(['@a += 123'], 'E1012:')
216
217  v:errmsg = 'none'
218  v:errmsg ..= 'again'
219  assert_equal('noneagain', v:errmsg)
220  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
221  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
222
223  var text =<< trim END
224    some text
225  END
226enddef
227
228def Test_assign_unpack()
229  var lines =<< trim END
230    var v1: number
231    var v2: number
232    [v1, v2] = [1, 2]
233    assert_equal(1, v1)
234    assert_equal(2, v2)
235  END
236  CheckDefAndScriptSuccess(lines)
237
238  lines =<< trim END
239      var v1: number
240      var v2: number
241      [v1, v2] =
242  END
243  CheckDefFailure(lines, 'E1097:', 5)
244
245  lines =<< trim END
246      var v1: number
247      var v2: number
248      [v1, v2] = xxx
249  END
250  CheckDefFailure(lines, 'E1001:', 3)
251
252  lines =<< trim END
253      var v1: number
254      var v2: number
255      [v1, v2] = popup_clear()
256  END
257  CheckDefFailure(lines, 'E1031:', 3)
258
259  lines =<< trim END
260      var v1: number
261      var v2: number
262      [v1, v2] = ''
263  END
264  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
265enddef
266
267def Test_assign_linebreak()
268  var nr: number
269  nr =
270      123
271  assert_equal(123, nr)
272
273  var n2: number
274  [nr, n2] =
275     [12, 34]
276  assert_equal(12, nr)
277  assert_equal(34, n2)
278
279  CheckDefFailure(["var x = #"], 'E1097:', 3)
280enddef
281
282def Test_assign_index()
283  # list of list
284  var l1: list<number>
285  l1[0] = 123
286  assert_equal([123], l1)
287
288  var l2: list<list<number>>
289  l2[0] = []
290  l2[0][0] = 123
291  assert_equal([[123]], l2)
292
293  var l3: list<list<list<number>>>
294  l3[0] = []
295  l3[0][0] = []
296  l3[0][0][0] = 123
297  assert_equal([[[123]]], l3)
298
299  var lines =<< trim END
300      var l3: list<list<number>>
301      l3[0] = []
302      l3[0][0] = []
303  END
304  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 3)
305
306  # dict of dict
307  var d1: dict<number>
308  d1.one = 1
309  assert_equal({one: 1}, d1)
310
311  var d2: dict<dict<number>>
312  d2.one = {}
313  d2.one.two = 123
314  assert_equal({one: {two: 123}}, d2)
315
316  var d3: dict<dict<dict<number>>>
317  d3.one = {}
318  d3.one.two = {}
319  d3.one.two.three = 123
320  assert_equal({one: {two: {three: 123}}}, d3)
321
322  lines =<< trim END
323      var d3: dict<dict<number>>
324      d3.one = {}
325      d3.one.two = {}
326  END
327  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
328
329  lines =<< trim END
330    var lines: list<string>
331    lines['a'] = 'asdf'
332  END
333  CheckDefFailure(lines, 'E39:', 2)
334
335  lines =<< trim END
336    var lines: string
337    lines[9] = 'asdf'
338  END
339  CheckDefFailure(lines, 'E1141:', 2)
340
341  # list of dict
342  var ld: list<dict<number>>
343  ld[0] = {}
344  ld[0].one = 123
345  assert_equal([{one: 123}], ld)
346
347  lines =<< trim END
348      var ld: list<dict<number>>
349      ld[0] = []
350  END
351  CheckDefFailure(lines, 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
352
353  # dict of list
354  var dl: dict<list<number>>
355  dl.one = []
356  dl.one[0] = 123
357  assert_equal({one: [123]}, dl)
358
359  lines =<< trim END
360      var dl: dict<list<number>>
361      dl.one = {}
362  END
363  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
364enddef
365
366def Test_extend_list()
367  var lines =<< trim END
368      vim9script
369      var l: list<number>
370      l += [123]
371      assert_equal([123], l)
372  END
373  CheckScriptSuccess(lines)
374
375  lines =<< trim END
376      vim9script
377      var list: list<string>
378      extend(list, ['x'])
379      assert_equal(['x'], list)
380  END
381  CheckScriptSuccess(lines)
382
383  # appending to NULL list from a function
384  lines =<< trim END
385      vim9script
386      var list: list<string>
387      def Func()
388        list += ['a', 'b']
389      enddef
390      Func()
391      assert_equal(['a', 'b'], list)
392  END
393  CheckScriptSuccess(lines)
394
395  lines =<< trim END
396      vim9script
397      var l: list<string> = test_null_list()
398      extend(l, ['x'])
399      assert_equal(['x'], l)
400  END
401  CheckScriptSuccess(lines)
402
403  lines =<< trim END
404      vim9script
405      extend(test_null_list(), ['x'])
406  END
407  CheckScriptFailure(lines, 'E1134:', 2)
408enddef
409
410def Test_extend_dict()
411  var lines =<< trim END
412      vim9script
413      var d: dict<number>
414      extend(d, {a: 1})
415      assert_equal({a: 1}, d)
416
417      var d2: dict<number>
418      d2['one'] = 1
419      assert_equal({one: 1}, d2)
420  END
421  CheckScriptSuccess(lines)
422
423  lines =<< trim END
424      vim9script
425      var d: dict<string> = test_null_dict()
426      extend(d, {a: 'x'})
427      assert_equal({a: 'x'}, d)
428  END
429  CheckScriptSuccess(lines)
430
431  lines =<< trim END
432      vim9script
433      extend(test_null_dict(), {a: 'x'})
434  END
435  CheckScriptFailure(lines, 'E1133:', 2)
436enddef
437
438def Test_single_letter_vars()
439  # single letter variables
440  var a: number = 123
441  a = 123
442  assert_equal(123, a)
443  var b: number
444  b = 123
445  assert_equal(123, b)
446  var g: number
447  g = 123
448  assert_equal(123, g)
449  var s: number
450  s = 123
451  assert_equal(123, s)
452  var t: number
453  t = 123
454  assert_equal(123, t)
455  var v: number
456  v = 123
457  assert_equal(123, v)
458  var w: number
459  w = 123
460  assert_equal(123, w)
461enddef
462
463def Test_vim9_single_char_vars()
464  var lines =<< trim END
465      vim9script
466
467      # single character variable declarations work
468      var a: string
469      var b: number
470      var l: list<any>
471      var s: string
472      var t: number
473      var v: number
474      var w: number
475
476      # script-local variables can be used without s: prefix
477      a = 'script-a'
478      b = 111
479      l = [1, 2, 3]
480      s = 'script-s'
481      t = 222
482      v = 333
483      w = 444
484
485      assert_equal('script-a', a)
486      assert_equal(111, b)
487      assert_equal([1, 2, 3], l)
488      assert_equal('script-s', s)
489      assert_equal(222, t)
490      assert_equal(333, v)
491      assert_equal(444, w)
492  END
493  writefile(lines, 'Xsinglechar')
494  source Xsinglechar
495  delete('Xsinglechar')
496enddef
497
498def Test_assignment_list()
499  var list1: list<bool> = [false, true, false]
500  var list2: list<number> = [1, 2, 3]
501  var list3: list<string> = ['sdf', 'asdf']
502  var list4: list<any> = ['yes', true, 1234]
503  var list5: list<blob> = [0z01, 0z02]
504
505  var listS: list<string> = []
506  var listN: list<number> = []
507
508  assert_equal([1, 2, 3], list2)
509  list2[-1] = 99
510  assert_equal([1, 2, 99], list2)
511  list2[-2] = 88
512  assert_equal([1, 88, 99], list2)
513  list2[-3] = 77
514  assert_equal([77, 88, 99], list2)
515  list2 += [100]
516  assert_equal([77, 88, 99, 100], list2)
517
518  list3 += ['end']
519  assert_equal(['sdf', 'asdf', 'end'], list3)
520
521  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
522  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
523
524  # type becomes list<any>
525  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
526enddef
527
528def Test_assignment_list_vim9script()
529  var lines =<< trim END
530    vim9script
531    var v1: number
532    var v2: number
533    var v3: number
534    [v1, v2, v3] = [1, 2, 3]
535    assert_equal([1, 2, 3], [v1, v2, v3])
536  END
537  CheckScriptSuccess(lines)
538enddef
539
540def Test_assignment_dict()
541  var dict1: dict<bool> = {one: false, two: true}
542  var dict2: dict<number> = {one: 1, two: 2}
543  var dict3: dict<string> = {key: 'value'}
544  var dict4: dict<any> = {one: 1, two: '2'}
545  var dict5: dict<blob> = {one: 0z01, two: 0z02}
546
547  # overwrite
548  dict3['key'] = 'another'
549  assert_equal(dict3, {key: 'another'})
550  dict3.key = 'yet another'
551  assert_equal(dict3, {key: 'yet another'})
552
553  var lines =<< trim END
554    var dd = {one: 1}
555    dd.one) = 2
556  END
557  CheckDefFailure(lines, 'E15:', 2)
558
559  # empty key can be used
560  var dd = {}
561  dd[""] = 6
562  assert_equal({['']: 6}, dd)
563
564  # type becomes dict<any>
565  var somedict = rand() > 0 ? {a: 1, b: 2} : {a: 'a', b: 'b'}
566
567  # assignment to script-local dict
568  lines =<< trim END
569    vim9script
570    var test: dict<any> = {}
571    def FillDict(): dict<any>
572      test['a'] = 43
573      return test
574    enddef
575    assert_equal({a: 43}, FillDict())
576  END
577  CheckScriptSuccess(lines)
578
579  lines =<< trim END
580    vim9script
581    var test: dict<any>
582    def FillDict(): dict<any>
583      test['a'] = 43
584      return test
585    enddef
586    FillDict()
587  END
588  CheckScriptFailure(lines, 'E1103:')
589
590  # assignment to global dict
591  lines =<< trim END
592    vim9script
593    g:test = {}
594    def FillDict(): dict<any>
595      g:test['a'] = 43
596      return g:test
597    enddef
598    assert_equal({a: 43}, FillDict())
599  END
600  CheckScriptSuccess(lines)
601
602  # assignment to buffer dict
603  lines =<< trim END
604    vim9script
605    b:test = {}
606    def FillDict(): dict<any>
607      b:test['a'] = 43
608      return b:test
609    enddef
610    assert_equal({a: 43}, FillDict())
611  END
612  CheckScriptSuccess(lines)
613enddef
614
615def Test_assignment_local()
616  # Test in a separated file in order not to the current buffer/window/tab is
617  # changed.
618  var script_lines: list<string> =<< trim END
619    let b:existing = 'yes'
620    let w:existing = 'yes'
621    let t:existing = 'yes'
622
623    def Test_assignment_local_internal()
624      b:newvar = 'new'
625      assert_equal('new', b:newvar)
626      assert_equal('yes', b:existing)
627      b:existing = 'no'
628      assert_equal('no', b:existing)
629      b:existing ..= 'NO'
630      assert_equal('noNO', b:existing)
631
632      w:newvar = 'new'
633      assert_equal('new', w:newvar)
634      assert_equal('yes', w:existing)
635      w:existing = 'no'
636      assert_equal('no', w:existing)
637      w:existing ..= 'NO'
638      assert_equal('noNO', w:existing)
639
640      t:newvar = 'new'
641      assert_equal('new', t:newvar)
642      assert_equal('yes', t:existing)
643      t:existing = 'no'
644      assert_equal('no', t:existing)
645      t:existing ..= 'NO'
646      assert_equal('noNO', t:existing)
647    enddef
648    call Test_assignment_local_internal()
649  END
650  CheckScriptSuccess(script_lines)
651enddef
652
653def Test_assignment_default()
654  # Test default values.
655  var thebool: bool
656  assert_equal(v:false, thebool)
657
658  var thenumber: number
659  assert_equal(0, thenumber)
660
661  if has('float')
662    var thefloat: float
663    assert_equal(0.0, thefloat)
664  endif
665
666  var thestring: string
667  assert_equal('', thestring)
668
669  var theblob: blob
670  assert_equal(0z, theblob)
671
672  var Thefunc: func
673  assert_equal(test_null_function(), Thefunc)
674
675  var thelist: list<any>
676  assert_equal([], thelist)
677
678  var thedict: dict<any>
679  assert_equal({}, thedict)
680
681  if has('channel')
682    var thejob: job
683    assert_equal(test_null_job(), thejob)
684
685    var thechannel: channel
686    assert_equal(test_null_channel(), thechannel)
687
688    if has('unix') && executable('cat')
689      # check with non-null job and channel, types must match
690      thejob = job_start("cat ", {})
691      thechannel = job_getchannel(thejob)
692      job_stop(thejob, 'kill')
693    endif
694  endif
695
696  var nr = 1234 | nr = 5678
697  assert_equal(5678, nr)
698enddef
699
700def Test_assignment_var_list()
701  var lines =<< trim END
702      var v1: string
703      var v2: string
704      var vrem: list<string>
705      [v1] = ['aaa']
706      assert_equal('aaa', v1)
707
708      [v1, v2] = ['one', 'two']
709      assert_equal('one', v1)
710      assert_equal('two', v2)
711
712      [v1, v2; vrem] = ['one', 'two']
713      assert_equal('one', v1)
714      assert_equal('two', v2)
715      assert_equal([], vrem)
716
717      [v1, v2; vrem] = ['one', 'two', 'three']
718      assert_equal('one', v1)
719      assert_equal('two', v2)
720      assert_equal(['three'], vrem)
721
722      [&ts, &sw] = [3, 4]
723      assert_equal(3, &ts)
724      assert_equal(4, &sw)
725      set ts=8 sw=4
726
727      [@a, @z] = ['aa', 'zz']
728      assert_equal('aa', @a)
729      assert_equal('zz', @z)
730
731      [$SOME_VAR, $OTHER_VAR] = ['some', 'other']
732      assert_equal('some', $SOME_VAR)
733      assert_equal('other', $OTHER_VAR)
734
735      [g:globalvar, s:scriptvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
736            ['global', 'script', 'buf', 'win', 'tab', 'error']
737      assert_equal('global', g:globalvar)
738      assert_equal('script', s:scriptvar)
739      assert_equal('buf', b:bufvar)
740      assert_equal('win', w:winvar)
741      assert_equal('tab', t:tabvar)
742      assert_equal('error', v:errmsg)
743      unlet g:globalvar
744  END
745  CheckDefAndScriptSuccess(lines)
746enddef
747
748def Test_assignment_vim9script()
749  var lines =<< trim END
750    vim9script
751    def Func(): list<number>
752      return [1, 2]
753    enddef
754    var name1: number
755    var name2: number
756    [name1, name2] =
757          Func()
758    assert_equal(1, name1)
759    assert_equal(2, name2)
760    var ll =
761          Func()
762    assert_equal([1, 2], ll)
763
764    @/ = 'text'
765    assert_equal('text', @/)
766    @0 = 'zero'
767    assert_equal('zero', @0)
768    @1 = 'one'
769    assert_equal('one', @1)
770    @9 = 'nine'
771    assert_equal('nine', @9)
772    @- = 'minus'
773    assert_equal('minus', @-)
774    if has('clipboard_working')
775      @* = 'star'
776      assert_equal('star', @*)
777      @+ = 'plus'
778      assert_equal('plus', @+)
779    endif
780
781    var a: number = 123
782    assert_equal(123, a)
783    var s: string = 'yes'
784    assert_equal('yes', s)
785    var b: number = 42
786    assert_equal(42, b)
787    var w: number = 43
788    assert_equal(43, w)
789    var t: number = 44
790    assert_equal(44, t)
791
792    var to_var = 0
793    to_var = 3
794    assert_equal(3, to_var)
795  END
796  CheckScriptSuccess(lines)
797
798  lines =<< trim END
799      vim9script
800      var n: number
801      def Func()
802        n = 'string'
803      enddef
804      defcompile
805  END
806  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
807enddef
808
809def Mess(): string
810  v:foldstart = 123
811  return 'xxx'
812enddef
813
814def Test_assignment_failure()
815  CheckDefFailure(['var name=234'], 'E1004:')
816  CheckDefFailure(['var name =234'], 'E1004:')
817  CheckDefFailure(['var name= 234'], 'E1004:')
818
819  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
820  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
821  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
822  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
823  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
824  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
825  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
826  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
827
828  CheckDefFailure(['var true = 1'], 'E1034:')
829  CheckDefFailure(['var false = 1'], 'E1034:')
830
831  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
832  CheckDefExecFailure(['var a: number',
833                       '[a] = test_null_list()'], 'E1093:')
834  CheckDefExecFailure(['var a: number',
835                       '[a] = []'], 'E1093:')
836  CheckDefExecFailure(['var x: number',
837                       'var y: number',
838                       '[x, y] = [1]'], 'E1093:')
839  CheckDefExecFailure(['var x: string',
840                       'var y: string',
841                       '[x, y] = ["x"]'], 'E1093:')
842  CheckDefExecFailure(['var x: number',
843                       'var y: number',
844                       'var z: list<number>',
845                       '[x, y; z] = [1]'], 'E1093:')
846
847  CheckDefFailure(['var somevar'], "E1022:")
848  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
849  CheckDefFailure(['&g:option = 5'], 'E113:')
850  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
851
852  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
853  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
854
855  if has('dnd')
856    CheckDefFailure(['var @~ = 5'], 'E1066:')
857  else
858    CheckDefFailure(['var @~ = 5'], 'E354:')
859    CheckDefFailure(['@~ = 5'], 'E354:')
860  endif
861  CheckDefFailure(['var @a = 5'], 'E1066:')
862  CheckDefFailure(['var @/ = "x"'], 'E1066:')
863  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
864
865  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
866  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
867  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
868  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
869
870  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
871  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
872  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
873  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
874  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
875
876  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
877
878  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
879  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
880
881  CheckDefFailure(['var name: dict<string> = {key: 123}'], 'expected dict<string> but got dict<number>')
882  CheckDefFailure(['var name: dict<number> = {key: "xx"}'], 'expected dict<number> but got dict<string>')
883
884  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
885  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
886
887  CheckDefFailure(['var name: dict <number>'], 'E1068:')
888  CheckDefFailure(['var name: dict<number'], 'E1009:')
889
890  assert_fails('s/^/\=Mess()/n', 'E794:')
891  CheckDefFailure(['var name: dict<number'], 'E1009:')
892
893  CheckDefFailure(['w:foo: number = 10'],
894                  'E488: Trailing characters: : number = 1')
895  CheckDefFailure(['t:foo: bool = true'],
896                  'E488: Trailing characters: : bool = true')
897  CheckDefFailure(['b:foo: string = "x"'],
898                  'E488: Trailing characters: : string = "x"')
899  CheckDefFailure(['g:foo: number = 123'],
900                  'E488: Trailing characters: : number = 123')
901enddef
902
903def Test_assign_list()
904  var l: list<string> = []
905  l[0] = 'value'
906  assert_equal('value', l[0])
907
908  l[1] = 'asdf'
909  assert_equal('value', l[0])
910  assert_equal('asdf', l[1])
911  assert_equal('asdf', l[-1])
912  assert_equal('value', l[-2])
913
914  var nrl: list<number> = []
915  for i in range(5)
916    nrl[i] = i
917  endfor
918  assert_equal([0, 1, 2, 3, 4], nrl)
919
920  CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
921  CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
922enddef
923
924def Test_assign_dict()
925  var d: dict<string> = {}
926  d['key'] = 'value'
927  assert_equal('value', d['key'])
928
929  d[123] = 'qwerty'
930  assert_equal('qwerty', d[123])
931  assert_equal('qwerty', d['123'])
932
933  var nrd: dict<number> = {}
934  for i in range(3)
935    nrd[i] = i
936  endfor
937  assert_equal({0: 0, 1: 1, 2: 2}, nrd)
938
939  CheckDefFailure(["var d: dict<number> = {a: '', b: true}"], 'E1012: Type mismatch; expected dict<number> but got dict<any>', 1)
940  CheckDefFailure(["var d: dict<dict<number>> = {x: {a: '', b: true}}"], 'E1012: Type mismatch; expected dict<dict<number>> but got dict<dict<any>>', 1)
941enddef
942
943def Test_assign_dict_unknown_type()
944  var lines =<< trim END
945      vim9script
946      var mylist = []
947      mylist += [{one: 'one'}]
948      def Func()
949        var dd = mylist[0]
950        assert_equal('one', dd.one)
951      enddef
952      Func()
953  END
954  CheckScriptSuccess(lines)
955
956  lines =<< trim END
957      vim9script
958      var mylist = [[]]
959      mylist[0] += [{one: 'one'}]
960      def Func()
961        var dd = mylist[0][0]
962        assert_equal('one', dd.one)
963      enddef
964      Func()
965  END
966  CheckScriptSuccess(lines)
967enddef
968
969def Test_assign_lambda()
970  # check if assign a lambda to a variable which type is func or any.
971  var lines =<< trim END
972      vim9script
973      var FuncRef = {->123}
974      assert_equal(123, FuncRef())
975      var FuncRef_Func: func = {->123}
976      assert_equal(123, FuncRef_Func())
977      var FuncRef_Any: any = {->123}
978      assert_equal(123, FuncRef_Any())
979  END
980  CheckScriptSuccess(lines)
981enddef
982
983def Test_heredoc()
984  var lines =<< trim END # comment
985    text
986  END
987  assert_equal(['text'], lines)
988
989  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
990  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
991
992  lines =<< trim [END]
993      def Func()
994        var&lines =<< trim END
995        x
996        x
997      enddef
998      defcompile
999  [END]
1000  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1001  delfunc! g:Func
1002
1003  lines =<< trim [END]
1004      def Func()
1005        var lines =<< trim END
1006        x
1007        x
1008        x
1009        x
1010        x
1011        x
1012        x
1013        x
1014      enddef
1015      call Func()
1016  [END]
1017  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1018  delfunc! g:Func
1019enddef
1020
1021def Test_var_func_call()
1022  var lines =<< trim END
1023    vim9script
1024    func GetValue()
1025      if exists('g:count')
1026        let g:count += 1
1027      else
1028        let g:count = 1
1029      endif
1030      return 'this'
1031    endfunc
1032    var val: string = GetValue()
1033    # env var is always a string
1034    var env = $TERM
1035  END
1036  writefile(lines, 'Xfinished')
1037  source Xfinished
1038  # GetValue() is not called during discovery phase
1039  assert_equal(1, g:count)
1040
1041  unlet g:count
1042  delete('Xfinished')
1043enddef
1044
1045def Test_var_missing_type()
1046  var lines =<< trim END
1047    vim9script
1048    var name = g:unknown
1049  END
1050  CheckScriptFailure(lines, 'E121:')
1051
1052  lines =<< trim END
1053    vim9script
1054    var nr: number = 123
1055    var name = nr
1056  END
1057  CheckScriptSuccess(lines)
1058enddef
1059
1060def Test_var_declaration()
1061  var lines =<< trim END
1062    vim9script
1063    var name: string
1064    g:var_uninit = name
1065    name = 'text'
1066    g:var_test = name
1067    # prefixing s: is optional
1068    s:name = 'prefixed'
1069    g:var_prefixed = s:name
1070
1071    const FOO: number = 123
1072    assert_equal(123, FOO)
1073
1074    var s:other: number
1075    other = 1234
1076    g:other_var = other
1077
1078    # type is inferred
1079    s:dict = {['a']: 222}
1080    def GetDictVal(key: any)
1081      g:dict_val = s:dict[key]
1082    enddef
1083    GetDictVal('a')
1084  END
1085  CheckScriptSuccess(lines)
1086  assert_equal('', g:var_uninit)
1087  assert_equal('text', g:var_test)
1088  assert_equal('prefixed', g:var_prefixed)
1089  assert_equal(1234, g:other_var)
1090  assert_equal(222, g:dict_val)
1091
1092  unlet g:var_uninit
1093  unlet g:var_test
1094  unlet g:var_prefixed
1095  unlet g:other_var
1096enddef
1097
1098def Test_var_declaration_fails()
1099  var lines =<< trim END
1100    vim9script
1101    final var: string
1102  END
1103  CheckScriptFailure(lines, 'E1125:')
1104
1105  lines =<< trim END
1106    vim9script
1107    const var: string
1108  END
1109  CheckScriptFailure(lines, 'E1021:')
1110
1111  lines =<< trim END
1112    vim9script
1113    var 9var: string
1114  END
1115  CheckScriptFailure(lines, 'E475:')
1116
1117  CheckDefFailure(['var foo.bar = 2'], 'E1087:')
1118  CheckDefFailure(['var foo[3] = 2'], 'E1087:')
1119  CheckDefFailure(['const foo: number'], 'E1021:')
1120enddef
1121
1122def Test_var_type_check()
1123  var lines =<< trim END
1124    vim9script
1125    var name: string
1126    name = 1234
1127  END
1128  CheckScriptFailure(lines, 'E1012:')
1129
1130  lines =<< trim END
1131    vim9script
1132    var name:string
1133  END
1134  CheckScriptFailure(lines, 'E1069:')
1135
1136  lines =<< trim END
1137    vim9script
1138    var name: asdf
1139  END
1140  CheckScriptFailure(lines, 'E1010:')
1141
1142  lines =<< trim END
1143    vim9script
1144    var s:l: list<number>
1145    s:l = []
1146  END
1147  CheckScriptSuccess(lines)
1148
1149  lines =<< trim END
1150    vim9script
1151    var s:d: dict<number>
1152    s:d = {}
1153  END
1154  CheckScriptSuccess(lines)
1155enddef
1156
1157let g:dict_number = #{one: 1, two: 2}
1158
1159def Test_var_list_dict_type()
1160  var ll: list<number>
1161  ll = [1, 2, 2, 3, 3, 3]->uniq()
1162  ll->assert_equal([1, 2, 3])
1163
1164  var dd: dict<number>
1165  dd = g:dict_number
1166  dd->assert_equal(g:dict_number)
1167
1168  var lines =<< trim END
1169      var ll: list<number>
1170      ll = [1, 2, 3]->map('"one"')
1171  END
1172  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
1173enddef
1174
1175def Test_cannot_use_let()
1176  CheckDefAndScriptFailure(['let a = 34'], 'E1126:', 1)
1177enddef
1178
1179def Test_unlet()
1180  g:somevar = 'yes'
1181  assert_true(exists('g:somevar'))
1182  unlet g:somevar
1183  assert_false(exists('g:somevar'))
1184  unlet! g:somevar
1185
1186  # also works for script-local variable in legacy Vim script
1187  s:somevar = 'legacy'
1188  assert_true(exists('s:somevar'))
1189  unlet s:somevar
1190  assert_false(exists('s:somevar'))
1191  unlet! s:somevar
1192
1193  CheckScriptFailure([
1194   'vim9script',
1195   'var svar = 123',
1196   'unlet svar',
1197   ], 'E1081:')
1198  CheckScriptFailure([
1199   'vim9script',
1200   'var svar = 123',
1201   'unlet s:svar',
1202   ], 'E1081:')
1203  CheckScriptFailure([
1204   'vim9script',
1205   'var svar = 123',
1206   'def Func()',
1207   '  unlet svar',
1208   'enddef',
1209   'defcompile',
1210   ], 'E1081:')
1211  CheckScriptFailure([
1212   'vim9script',
1213   'var svar = 123',
1214   'def Func()',
1215   '  unlet s:svar',
1216   'enddef',
1217   'defcompile',
1218   ], 'E1081:')
1219
1220  $ENVVAR = 'foobar'
1221  assert_equal('foobar', $ENVVAR)
1222  unlet $ENVVAR
1223  assert_equal('', $ENVVAR)
1224enddef
1225
1226
1227" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1228