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    var job1: job
78    var job2: job = job_start('willfail')
79  endif
80  if has('float')
81    var float1: float = 3.4
82  endif
83  var Funky1: func
84  var Funky2: func = function('len')
85  var Party2: func = funcref('g:Test_syntax')
86
87  g:newvar = 'new'  #comment
88  assert_equal('new', g:newvar)
89
90  assert_equal('yes', g:existing)
91  g:existing = 'no'
92  assert_equal('no', g:existing)
93
94  v:char = 'abc'
95  assert_equal('abc', v:char)
96
97  $ENVVAR = 'foobar'
98  assert_equal('foobar', $ENVVAR)
99  $ENVVAR = ''
100
101  var lines =<< trim END
102    vim9script
103    $ENVVAR = 'barfoo'
104    assert_equal('barfoo', $ENVVAR)
105    $ENVVAR = ''
106  END
107  CheckScriptSuccess(lines)
108
109  s:appendToMe ..= 'yyy'
110  assert_equal('xxxyyy', s:appendToMe)
111  s:addToMe += 222
112  assert_equal(333, s:addToMe)
113  s:newVar = 'new'
114  assert_equal('new', s:newVar)
115
116  set ts=7
117  &ts += 1
118  assert_equal(8, &ts)
119  &ts -= 3
120  assert_equal(5, &ts)
121  &ts *= 2
122  assert_equal(10, &ts)
123  &ts /= 3
124  assert_equal(3, &ts)
125  set ts=10
126  &ts %= 4
127  assert_equal(2, &ts)
128
129  if has('float')
130    var f100: float = 100.0
131    f100 /= 5
132    assert_equal(20.0, f100)
133
134    var f200: float = 200.0
135    f200 /= 5.0
136    assert_equal(40.0, f200)
137
138    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
139  endif
140
141  lines =<< trim END
142    &ts = 6
143    &ts += 3
144    assert_equal(9, &ts)
145
146    &l:ts = 6
147    assert_equal(6, &ts)
148    &l:ts += 2
149    assert_equal(8, &ts)
150
151    &g:ts = 6
152    assert_equal(6, &g:ts)
153    &g:ts += 2
154    assert_equal(8, &g:ts)
155  END
156  CheckDefAndScriptSuccess(lines)
157
158  CheckDefFailure(['&notex += 3'], 'E113:')
159  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
160  CheckDefFailure(['&ts = [7]'], 'E1012:')
161  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
162  CheckDefFailure(['&ts = "xx"'], 'E1012:')
163  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
164  CheckDefFailure(['&path += 3'], 'E1012:')
165  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
166  # test freeing ISN_STOREOPT
167  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
168  &ts = 8
169
170  lines =<< trim END
171    var save_TI = &t_TI
172    &t_TI = ''
173    assert_equal('', &t_TI)
174    &t_TI = 'xxx'
175    assert_equal('xxx', &t_TI)
176    &t_TI = save_TI
177  END
178  CheckDefAndScriptSuccess(lines)
179
180  CheckDefFailure(['&t_TI = 123'], 'E1012:')
181  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
182
183  CheckDefFailure(['var s:var = 123'], 'E1101:')
184  CheckDefFailure(['var s:var: number'], 'E1101:')
185
186  lines =<< trim END
187    vim9script
188    def SomeFunc()
189      s:var = 123
190    enddef
191    defcompile
192  END
193  CheckScriptFailure(lines, 'E1089:')
194
195  g:inc_counter += 1
196  assert_equal(2, g:inc_counter)
197
198  $SOME_ENV_VAR ..= 'more'
199  assert_equal('somemore', $SOME_ENV_VAR)
200  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
201  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
202
203  lines =<< trim END
204    @c = 'areg'
205    @c ..= 'add'
206    assert_equal('aregadd', @c)
207  END
208  CheckDefAndScriptSuccess(lines)
209
210  CheckDefFailure(['@a += "more"'], 'E1051:')
211  CheckDefFailure(['@a += 123'], 'E1012:')
212
213  v:errmsg = 'none'
214  v:errmsg ..= 'again'
215  assert_equal('noneagain', v:errmsg)
216  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
217  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
218
219  # this should not leak
220  if 0
221    var text =<< trim END
222      some text
223    END
224  endif
225enddef
226
227def Test_extend_list()
228  var lines =<< trim END
229      vim9script
230      var l: list<number>
231      l += [123]
232      assert_equal([123], l)
233
234      var d: dict<number>
235      d['one'] = 1
236      assert_equal(#{one: 1}, d)
237  END
238  CheckScriptSuccess(lines)
239
240  # appending to NULL list from a function
241  lines =<< trim END
242      vim9script
243      var list: list<string>
244      def Func()
245        list += ['a', 'b']
246      enddef
247      Func()
248      assert_equal(['a', 'b'], list)
249  END
250  CheckScriptSuccess(lines)
251enddef
252
253def Test_single_letter_vars()
254  # single letter variables
255  var a: number = 123
256  a = 123
257  assert_equal(123, a)
258  var b: number
259  b = 123
260  assert_equal(123, b)
261  var g: number
262  g = 123
263  assert_equal(123, g)
264  var s: number
265  s = 123
266  assert_equal(123, s)
267  var t: number
268  t = 123
269  assert_equal(123, t)
270  var v: number
271  v = 123
272  assert_equal(123, v)
273  var w: number
274  w = 123
275  assert_equal(123, w)
276enddef
277
278def Test_vim9_single_char_vars()
279  var lines =<< trim END
280      vim9script
281
282      # single character variable declarations work
283      var a: string
284      var b: number
285      var l: list<any>
286      var s: string
287      var t: number
288      var v: number
289      var w: number
290
291      # script-local variables can be used without s: prefix
292      a = 'script-a'
293      b = 111
294      l = [1, 2, 3]
295      s = 'script-s'
296      t = 222
297      v = 333
298      w = 444
299
300      assert_equal('script-a', a)
301      assert_equal(111, b)
302      assert_equal([1, 2, 3], l)
303      assert_equal('script-s', s)
304      assert_equal(222, t)
305      assert_equal(333, v)
306      assert_equal(444, w)
307  END
308  writefile(lines, 'Xsinglechar')
309  source Xsinglechar
310  delete('Xsinglechar')
311enddef
312
313def Test_assignment_list()
314  var list1: list<bool> = [false, true, false]
315  var list2: list<number> = [1, 2, 3]
316  var list3: list<string> = ['sdf', 'asdf']
317  var list4: list<any> = ['yes', true, 1234]
318  var list5: list<blob> = [0z01, 0z02]
319
320  var listS: list<string> = []
321  var listN: list<number> = []
322
323  assert_equal([1, 2, 3], list2)
324  list2[-1] = 99
325  assert_equal([1, 2, 99], list2)
326  list2[-2] = 88
327  assert_equal([1, 88, 99], list2)
328  list2[-3] = 77
329  assert_equal([77, 88, 99], list2)
330  list2 += [100]
331  assert_equal([77, 88, 99, 100], list2)
332
333  list3 += ['end']
334  assert_equal(['sdf', 'asdf', 'end'], list3)
335
336  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
337  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
338
339  # type becomes list<any>
340  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
341enddef
342
343def Test_assignment_list_vim9script()
344  var lines =<< trim END
345    vim9script
346    var v1: number
347    var v2: number
348    var v3: number
349    [v1, v2, v3] = [1, 2, 3]
350    assert_equal([1, 2, 3], [v1, v2, v3])
351  END
352  CheckScriptSuccess(lines)
353enddef
354
355def Test_assignment_dict()
356  var dict1: dict<bool> = #{one: false, two: true}
357  var dict2: dict<number> = #{one: 1, two: 2}
358  var dict3: dict<string> = #{key: 'value'}
359  var dict4: dict<any> = #{one: 1, two: '2'}
360  var dict5: dict<blob> = #{one: 0z01, two: 0z02}
361
362  # overwrite
363  dict3['key'] = 'another'
364
365  # empty key can be used
366  var dd = {}
367  dd[""] = 6
368  assert_equal({'': 6}, dd)
369
370  # type becomes dict<any>
371  var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
372
373  # assignment to script-local dict
374  var lines =<< trim END
375    vim9script
376    var test: dict<any> = {}
377    def FillDict(): dict<any>
378      test['a'] = 43
379      return test
380    enddef
381    assert_equal(#{a: 43}, FillDict())
382  END
383  CheckScriptSuccess(lines)
384
385  lines =<< trim END
386    vim9script
387    var test: dict<any>
388    def FillDict(): dict<any>
389      test['a'] = 43
390      return test
391    enddef
392    FillDict()
393  END
394  CheckScriptFailure(lines, 'E1103:')
395
396  # assignment to global dict
397  lines =<< trim END
398    vim9script
399    g:test = {}
400    def FillDict(): dict<any>
401      g:test['a'] = 43
402      return g:test
403    enddef
404    assert_equal(#{a: 43}, FillDict())
405  END
406  CheckScriptSuccess(lines)
407
408  # assignment to buffer dict
409  lines =<< trim END
410    vim9script
411    b:test = {}
412    def FillDict(): dict<any>
413      b:test['a'] = 43
414      return b:test
415    enddef
416    assert_equal(#{a: 43}, FillDict())
417  END
418  CheckScriptSuccess(lines)
419enddef
420
421def Test_assignment_local()
422  # Test in a separated file in order not to the current buffer/window/tab is
423  # changed.
424  var script_lines: list<string> =<< trim END
425    let b:existing = 'yes'
426    let w:existing = 'yes'
427    let t:existing = 'yes'
428
429    def Test_assignment_local_internal()
430      b:newvar = 'new'
431      assert_equal('new', b:newvar)
432      assert_equal('yes', b:existing)
433      b:existing = 'no'
434      assert_equal('no', b:existing)
435      b:existing ..= 'NO'
436      assert_equal('noNO', b:existing)
437
438      w:newvar = 'new'
439      assert_equal('new', w:newvar)
440      assert_equal('yes', w:existing)
441      w:existing = 'no'
442      assert_equal('no', w:existing)
443      w:existing ..= 'NO'
444      assert_equal('noNO', w:existing)
445
446      t:newvar = 'new'
447      assert_equal('new', t:newvar)
448      assert_equal('yes', t:existing)
449      t:existing = 'no'
450      assert_equal('no', t:existing)
451      t:existing ..= 'NO'
452      assert_equal('noNO', t:existing)
453    enddef
454    call Test_assignment_local_internal()
455  END
456  CheckScriptSuccess(script_lines)
457enddef
458
459def Test_assignment_default()
460
461  # Test default values.
462  var thebool: bool
463  assert_equal(v:false, thebool)
464
465  var thenumber: number
466  assert_equal(0, thenumber)
467
468  if has('float')
469    var thefloat: float
470    assert_equal(0.0, thefloat)
471  endif
472
473  var thestring: string
474  assert_equal('', thestring)
475
476  var theblob: blob
477  assert_equal(0z, theblob)
478
479  var Thefunc: func
480  assert_equal(test_null_function(), Thefunc)
481
482  var thelist: list<any>
483  assert_equal([], thelist)
484
485  var thedict: dict<any>
486  assert_equal({}, thedict)
487
488  if has('channel')
489    var thejob: job
490    assert_equal(test_null_job(), thejob)
491
492    var thechannel: channel
493    assert_equal(test_null_channel(), thechannel)
494
495    if has('unix') && executable('cat')
496      # check with non-null job and channel, types must match
497      thejob = job_start("cat ", #{})
498      thechannel = job_getchannel(thejob)
499      job_stop(thejob, 'kill')
500    endif
501  endif
502
503  var nr = 1234 | nr = 5678
504  assert_equal(5678, nr)
505enddef
506
507def Test_assignment_var_list()
508  var v1: string
509  var v2: string
510  var vrem: list<string>
511  [v1] = ['aaa']
512  assert_equal('aaa', v1)
513
514  [v1, v2] = ['one', 'two']
515  assert_equal('one', v1)
516  assert_equal('two', v2)
517
518  [v1, v2; vrem] = ['one', 'two']
519  assert_equal('one', v1)
520  assert_equal('two', v2)
521  assert_equal([], vrem)
522
523  [v1, v2; vrem] = ['one', 'two', 'three']
524  assert_equal('one', v1)
525  assert_equal('two', v2)
526  assert_equal(['three'], vrem)
527
528  [&ts, &sw] = [3, 4]
529  assert_equal(3, &ts)
530  assert_equal(4, &sw)
531  set ts=8 sw=4
532enddef
533
534def Test_assignment_vim9script()
535  var lines =<< trim END
536    vim9script
537    def Func(): list<number>
538      return [1, 2]
539    enddef
540    var name1: number
541    var name2: number
542    [name1, name2] =
543          Func()
544    assert_equal(1, name1)
545    assert_equal(2, name2)
546    var ll =
547          Func()
548    assert_equal([1, 2], ll)
549
550    @/ = 'text'
551    assert_equal('text', @/)
552    @0 = 'zero'
553    assert_equal('zero', @0)
554    @1 = 'one'
555    assert_equal('one', @1)
556    @9 = 'nine'
557    assert_equal('nine', @9)
558    @- = 'minus'
559    assert_equal('minus', @-)
560    if has('clipboard_working')
561      @* = 'star'
562      assert_equal('star', @*)
563      @+ = 'plus'
564      assert_equal('plus', @+)
565    endif
566
567    var a: number = 123
568    assert_equal(123, a)
569    var s: string = 'yes'
570    assert_equal('yes', s)
571    var b: number = 42
572    assert_equal(42, b)
573    var w: number = 43
574    assert_equal(43, w)
575    var t: number = 44
576    assert_equal(44, t)
577  END
578  CheckScriptSuccess(lines)
579
580  lines =<< trim END
581      vim9script
582      var n: number
583      def Func()
584        n = 'string'
585      enddef
586      defcompile
587  END
588  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
589enddef
590
591def Mess(): string
592  v:foldstart = 123
593  return 'xxx'
594enddef
595
596def Test_assignment_failure()
597  CheckDefFailure(['var name=234'], 'E1004:')
598  CheckDefFailure(['var name =234'], 'E1004:')
599  CheckDefFailure(['var name= 234'], 'E1004:')
600
601  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
602  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
603  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
604  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
605  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
606  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
607  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
608  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
609
610  CheckDefFailure(['var true = 1'], 'E1034:')
611  CheckDefFailure(['var false = 1'], 'E1034:')
612
613  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
614  CheckDefExecFailure(['var a: number',
615                       '[a] = test_null_list()'], 'E1093:')
616  CheckDefExecFailure(['var a: number',
617                       '[a] = []'], 'E1093:')
618  CheckDefExecFailure(['var x: number',
619                       'var y: number',
620                       '[x, y] = [1]'], 'E1093:')
621  CheckDefExecFailure(['var x: number',
622                       'var y: number',
623                       'var z: list<number>',
624                       '[x, y; z] = [1]'], 'E1093:')
625
626  CheckDefFailure(['var somevar'], "E1022:")
627  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
628  CheckDefFailure(['&g:option = 5'], 'E113:')
629  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
630
631  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
632  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
633
634  if has('dnd')
635    CheckDefFailure(['var @~ = 5'], 'E1066:')
636  else
637    CheckDefFailure(['var @~ = 5'], 'E354:')
638    CheckDefFailure(['@~ = 5'], 'E354:')
639  endif
640  CheckDefFailure(['var @a = 5'], 'E1066:')
641  CheckDefFailure(['var @/ = "x"'], 'E1066:')
642  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
643
644  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
645  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
646  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
647  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
648
649  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
650  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
651  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
652  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
653  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
654
655  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
656
657  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
658  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
659
660  CheckDefFailure(['var name: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
661  CheckDefFailure(['var name: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
662
663  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
664  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
665
666  CheckDefFailure(['var name: dict <number>'], 'E1068:')
667  CheckDefFailure(['var name: dict<number'], 'E1009:')
668
669  assert_fails('s/^/\=Mess()/n', 'E794:')
670  CheckDefFailure(['var name: dict<number'], 'E1009:')
671
672  CheckDefFailure(['w:foo: number = 10'],
673                  'E488: Trailing characters: : number = 1')
674  CheckDefFailure(['t:foo: bool = true'],
675                  'E488: Trailing characters: : bool = true')
676  CheckDefFailure(['b:foo: string = "x"'],
677                  'E488: Trailing characters: : string = "x"')
678  CheckDefFailure(['g:foo: number = 123'],
679                  'E488: Trailing characters: : number = 123')
680enddef
681
682def Test_assign_list()
683  var l: list<string> = []
684  l[0] = 'value'
685  assert_equal('value', l[0])
686
687  l[1] = 'asdf'
688  assert_equal('value', l[0])
689  assert_equal('asdf', l[1])
690  assert_equal('asdf', l[-1])
691  assert_equal('value', l[-2])
692
693  var nrl: list<number> = []
694  for i in range(5)
695    nrl[i] = i
696  endfor
697  assert_equal([0, 1, 2, 3, 4], nrl)
698enddef
699
700def Test_assign_dict()
701  var d: dict<string> = {}
702  d['key'] = 'value'
703  assert_equal('value', d['key'])
704
705  d[123] = 'qwerty'
706  assert_equal('qwerty', d[123])
707  assert_equal('qwerty', d['123'])
708
709  var nrd: dict<number> = {}
710  for i in range(3)
711    nrd[i] = i
712  endfor
713  assert_equal({'0': 0, '1': 1, '2': 2}, nrd)
714enddef
715
716def Test_assign_dict_unknown_type()
717  var lines =<< trim END
718      vim9script
719      var mylist = []
720      mylist += [#{one: 'one'}]
721      def Func()
722        var dd = mylist[0]
723        assert_equal('one', dd.one)
724      enddef
725      Func()
726  END
727  CheckScriptSuccess(lines)
728
729  # doesn't work yet
730  #lines =<< trim END
731  #    vim9script
732  #    var mylist = [[]]
733  #    mylist[0] += [#{one: 'one'}]
734  #    def Func()
735  #      var dd = mylist[0][0]
736  #      assert_equal('one', dd.one)
737  #    enddef
738  #    Func()
739  #END
740  #CheckScriptSuccess(lines)
741enddef
742
743def Test_assign_lambda()
744  # check if assign a lambda to a variable which type is func or any.
745  var lines =<< trim END
746      vim9script
747      var FuncRef = {->123}
748      assert_equal(123, FuncRef())
749      var FuncRef_Func: func = {->123}
750      assert_equal(123, FuncRef_Func())
751      var FuncRef_Any: any = {->123}
752      assert_equal(123, FuncRef_Any())
753  END
754  CheckScriptSuccess(lines)
755enddef
756
757def Test_heredoc()
758  var lines =<< trim END # comment
759    text
760  END
761  assert_equal(['text'], lines)
762
763  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
764  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
765
766  lines =<< trim [END]
767      def Func()
768        var&lines =<< trim END
769        x
770        x
771        x
772        x
773        x
774        x
775        x
776        x
777      enddef
778      call Func()
779  [END]
780  CheckScriptFailure(lines, 'E990:')
781enddef
782
783def Test_let_func_call()
784  var lines =<< trim END
785    vim9script
786    func GetValue()
787      if exists('g:count')
788        let g:count += 1
789      else
790        let g:count = 1
791      endif
792      return 'this'
793    endfunc
794    var val: string = GetValue()
795    # env var is always a string
796    var env = $TERM
797  END
798  writefile(lines, 'Xfinished')
799  source Xfinished
800  # GetValue() is not called during discovery phase
801  assert_equal(1, g:count)
802
803  unlet g:count
804  delete('Xfinished')
805enddef
806
807def Test_let_missing_type()
808  var lines =<< trim END
809    vim9script
810    var name = g:unknown
811  END
812  CheckScriptFailure(lines, 'E121:')
813
814  lines =<< trim END
815    vim9script
816    var nr: number = 123
817    var name = nr
818  END
819  CheckScriptSuccess(lines)
820enddef
821
822def Test_let_declaration()
823  var lines =<< trim END
824    vim9script
825    var name: string
826    g:var_uninit = name
827    name = 'text'
828    g:var_test = name
829    # prefixing s: is optional
830    s:name = 'prefixed'
831    g:var_prefixed = s:name
832
833    var s:other: number
834    other = 1234
835    g:other_var = other
836
837    # type is inferred
838    s:dict = {'a': 222}
839    def GetDictVal(key: any)
840      g:dict_val = s:dict[key]
841    enddef
842    GetDictVal('a')
843  END
844  CheckScriptSuccess(lines)
845  assert_equal('', g:var_uninit)
846  assert_equal('text', g:var_test)
847  assert_equal('prefixed', g:var_prefixed)
848  assert_equal(1234, g:other_var)
849  assert_equal(222, g:dict_val)
850
851  unlet g:var_uninit
852  unlet g:var_test
853  unlet g:var_prefixed
854  unlet g:other_var
855enddef
856
857def Test_let_declaration_fails()
858  var lines =<< trim END
859    vim9script
860    final var: string
861  END
862  CheckScriptFailure(lines, 'E1125:')
863
864  lines =<< trim END
865    vim9script
866    const var: string
867  END
868  CheckScriptFailure(lines, 'E1021:')
869
870  lines =<< trim END
871    vim9script
872    var 9var: string
873  END
874  CheckScriptFailure(lines, 'E475:')
875enddef
876
877def Test_let_type_check()
878  var lines =<< trim END
879    vim9script
880    var name: string
881    name = 1234
882  END
883  CheckScriptFailure(lines, 'E1012:')
884
885  lines =<< trim END
886    vim9script
887    var name:string
888  END
889  CheckScriptFailure(lines, 'E1069:')
890
891  lines =<< trim END
892    vim9script
893    var name: asdf
894  END
895  CheckScriptFailure(lines, 'E1010:')
896
897  lines =<< trim END
898    vim9script
899    var s:l: list<number>
900    s:l = []
901  END
902  CheckScriptSuccess(lines)
903
904  lines =<< trim END
905    vim9script
906    var s:d: dict<number>
907    s:d = {}
908  END
909  CheckScriptSuccess(lines)
910enddef
911
912let g:dict_number = #{one: 1, two: 2}
913
914def Test_let_list_dict_type()
915  var ll: list<number>
916  ll = [1, 2, 2, 3, 3, 3]->uniq()
917  ll->assert_equal([1, 2, 3])
918
919  var dd: dict<number>
920  dd = g:dict_number
921  dd->assert_equal(g:dict_number)
922
923  var lines =<< trim END
924      var ll: list<number>
925      ll = [1, 2, 3]->map('"one"')
926  END
927  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
928enddef
929
930def Test_unlet()
931  g:somevar = 'yes'
932  assert_true(exists('g:somevar'))
933  unlet g:somevar
934  assert_false(exists('g:somevar'))
935  unlet! g:somevar
936
937  # also works for script-local variable in legacy Vim script
938  s:somevar = 'legacy'
939  assert_true(exists('s:somevar'))
940  unlet s:somevar
941  assert_false(exists('s:somevar'))
942  unlet! s:somevar
943
944  CheckScriptFailure([
945   'vim9script',
946   'var svar = 123',
947   'unlet svar',
948   ], 'E1081:')
949  CheckScriptFailure([
950   'vim9script',
951   'var svar = 123',
952   'unlet s:svar',
953   ], 'E1081:')
954  CheckScriptFailure([
955   'vim9script',
956   'var svar = 123',
957   'def Func()',
958   '  unlet svar',
959   'enddef',
960   'defcompile',
961   ], 'E1081:')
962  CheckScriptFailure([
963   'vim9script',
964   'var svar = 123',
965   'def Func()',
966   '  unlet s:svar',
967   'enddef',
968   'defcompile',
969   ], 'E1081:')
970
971  $ENVVAR = 'foobar'
972  assert_equal('foobar', $ENVVAR)
973  unlet $ENVVAR
974  assert_equal('', $ENVVAR)
975enddef
976
977
978" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
979