1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source term_util.vim
5source view_util.vim
6source vim9.vim
7source shared.vim
8
9def Test_syntax()
10  let var = 234
11  let other: list<string> = ['asdf']
12enddef
13
14def Test_range_only()
15  new
16  setline(1, ['blah', 'Blah'])
17  :/Blah/
18  assert_equal(2, getcurpos()[1])
19  bwipe!
20
21  # without range commands use current line
22  new
23  setline(1, ['one', 'two', 'three'])
24  :2
25  print
26  assert_equal('two', Screenline(&lines))
27  :3
28  list
29  assert_equal('three$', Screenline(&lines))
30  bwipe!
31enddef
32
33let s:appendToMe = 'xxx'
34let s:addToMe = 111
35let g:existing = 'yes'
36let g:inc_counter = 1
37let $SOME_ENV_VAR = 'some'
38let g:alist = [7]
39let g:astring = 'text'
40let g:anumber = 123
41
42def Test_assignment_bool()
43  let bool1: bool = true
44  assert_equal(v:true, bool1)
45  let bool2: bool = false
46  assert_equal(v:false, bool2)
47
48  let bool3: bool = 0
49  assert_equal(false, bool3)
50  let bool4: bool = 1
51  assert_equal(true, bool4)
52
53  let bool5: bool = 'yes' && 'no'
54  assert_equal(true, bool5)
55  let bool6: bool = [] && 99
56  assert_equal(false, bool6)
57  let bool7: bool = [] || #{a: 1} && 99
58  assert_equal(true, bool7)
59
60  let lines =<< trim END
61    vim9script
62    def GetFlag(): bool
63      let flag: bool = 1
64      return flag
65    enddef
66    let flag: bool = GetFlag()
67    assert_equal(true, flag)
68    flag = 0
69    assert_equal(false, flag)
70    flag = 1
71    assert_equal(true, flag)
72    flag = 99 || 123
73    assert_equal(true, flag)
74    flag = 'yes' && []
75    assert_equal(false, flag)
76  END
77  CheckScriptSuccess(lines)
78  CheckDefAndScriptFailure(['let x: bool = 2'], 'E1012:')
79  CheckDefAndScriptFailure(['let x: bool = -1'], 'E1012:')
80  CheckDefAndScriptFailure(['let x: bool = [1]'], 'E1012:')
81  CheckDefAndScriptFailure(['let x: bool = {}'], 'E1012:')
82  CheckDefAndScriptFailure(['let x: bool = "x"'], 'E1012:')
83enddef
84
85def Test_assignment()
86  CheckDefFailure(['let x:string'], 'E1069:')
87  CheckDefFailure(['let x:string = "x"'], 'E1069:')
88  CheckDefFailure(['let a:string = "x"'], 'E1069:')
89  CheckDefFailure(['let lambda = {-> "lambda"}'], 'E704:')
90
91  let nr: number = 1234
92  CheckDefFailure(['let nr: number = "asdf"'], 'E1012:')
93
94  let a: number = 6 #comment
95  assert_equal(6, a)
96
97  if has('channel')
98    let chan1: channel
99    let job1: job
100    let job2: job = job_start('willfail')
101  endif
102  if has('float')
103    let float1: float = 3.4
104  endif
105  let Funky1: func
106  let Funky2: func = function('len')
107  let Party2: func = funcref('g:Test_syntax')
108
109  g:newvar = 'new'  #comment
110  assert_equal('new', g:newvar)
111
112  assert_equal('yes', g:existing)
113  g:existing = 'no'
114  assert_equal('no', g:existing)
115
116  v:char = 'abc'
117  assert_equal('abc', v:char)
118
119  $ENVVAR = 'foobar'
120  assert_equal('foobar', $ENVVAR)
121  $ENVVAR = ''
122
123  let lines =<< trim END
124    vim9script
125    $ENVVAR = 'barfoo'
126    assert_equal('barfoo', $ENVVAR)
127    $ENVVAR = ''
128  END
129  CheckScriptSuccess(lines)
130
131  s:appendToMe ..= 'yyy'
132  assert_equal('xxxyyy', s:appendToMe)
133  s:addToMe += 222
134  assert_equal(333, s:addToMe)
135  s:newVar = 'new'
136  assert_equal('new', s:newVar)
137
138  set ts=7
139  &ts += 1
140  assert_equal(8, &ts)
141  &ts -= 3
142  assert_equal(5, &ts)
143  &ts *= 2
144  assert_equal(10, &ts)
145  &ts /= 3
146  assert_equal(3, &ts)
147  set ts=10
148  &ts %= 4
149  assert_equal(2, &ts)
150
151  if has('float')
152    let f100: float = 100.0
153    f100 /= 5
154    assert_equal(20.0, f100)
155
156    let f200: float = 200.0
157    f200 /= 5.0
158    assert_equal(40.0, f200)
159
160    CheckDefFailure(['let nr: number = 200', 'nr /= 5.0'], 'E1012:')
161  endif
162
163  lines =<< trim END
164    &ts = 6
165    &ts += 3
166    assert_equal(9, &ts)
167
168    &l:ts = 6
169    assert_equal(6, &ts)
170    &l:ts += 2
171    assert_equal(8, &ts)
172
173    &g:ts = 6
174    assert_equal(6, &g:ts)
175    &g:ts += 2
176    assert_equal(8, &g:ts)
177  END
178  CheckDefAndScriptSuccess(lines)
179
180  CheckDefFailure(['&notex += 3'], 'E113:')
181  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
182  CheckDefFailure(['&ts = [7]'], 'E1012:')
183  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
184  CheckDefFailure(['&ts = "xx"'], 'E1012:')
185  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
186  CheckDefFailure(['&path += 3'], 'E1012:')
187  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
188  # test freeing ISN_STOREOPT
189  CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
190  &ts = 8
191
192  lines =<< trim END
193    let save_TI = &t_TI
194    &t_TI = ''
195    assert_equal('', &t_TI)
196    &t_TI = 'xxx'
197    assert_equal('xxx', &t_TI)
198    &t_TI = save_TI
199  END
200  CheckDefAndScriptSuccess(lines)
201
202  CheckDefFailure(['&t_TI = 123'], 'E1012:')
203  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
204
205  CheckDefFailure(['let s:var = 123'], 'E1101:')
206  CheckDefFailure(['let s:var: number'], 'E1101:')
207
208  lines =<< trim END
209    vim9script
210    def SomeFunc()
211      s:var = 123
212    enddef
213    defcompile
214  END
215  CheckScriptFailure(lines, 'E1089:')
216
217  g:inc_counter += 1
218  assert_equal(2, g:inc_counter)
219
220  $SOME_ENV_VAR ..= 'more'
221  assert_equal('somemore', $SOME_ENV_VAR)
222  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
223  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
224
225  lines =<< trim END
226    @c = 'areg'
227    @c ..= 'add'
228    assert_equal('aregadd', @c)
229  END
230  CheckDefAndScriptSuccess(lines)
231
232  CheckDefFailure(['@a += "more"'], 'E1051:')
233  CheckDefFailure(['@a += 123'], 'E1012:')
234
235  v:errmsg = 'none'
236  v:errmsg ..= 'again'
237  assert_equal('noneagain', v:errmsg)
238  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
239  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
240
241  # single letter variables
242  a = 123
243  assert_equal(123, a)
244  let b: number
245  b = 123
246  assert_equal(123, b)
247  let g: number
248  g = 123
249  assert_equal(123, g)
250  let s: number
251  s = 123
252  assert_equal(123, s)
253  let t: number
254  t = 123
255  assert_equal(123, t)
256  let v: number
257  v = 123
258  assert_equal(123, v)
259  let w: number
260  w = 123
261  assert_equal(123, w)
262
263
264  # this should not leak
265  if 0
266    let text =<< trim END
267      some text
268    END
269  endif
270enddef
271
272def Test_vim9_single_char_vars()
273  let lines =<< trim END
274      vim9script
275
276      # single character variable declarations work
277      let a: string
278      let b: number
279      let l: list<any>
280      let s: string
281      let t: number
282      let v: number
283      let w: number
284
285      # script-local variables can be used without s: prefix
286      a = 'script-a'
287      b = 111
288      l = [1, 2, 3]
289      s = 'script-s'
290      t = 222
291      v = 333
292      w = 444
293
294      assert_equal('script-a', a)
295      assert_equal(111, b)
296      assert_equal([1, 2, 3], l)
297      assert_equal('script-s', s)
298      assert_equal(222, t)
299      assert_equal(333, v)
300      assert_equal(444, w)
301  END
302  writefile(lines, 'Xsinglechar')
303  source Xsinglechar
304  delete('Xsinglechar')
305enddef
306
307def Test_assignment_list()
308  let list1: list<bool> = [false, true, false]
309  let list2: list<number> = [1, 2, 3]
310  let list3: list<string> = ['sdf', 'asdf']
311  let list4: list<any> = ['yes', true, 1234]
312  let list5: list<blob> = [0z01, 0z02]
313
314  let listS: list<string> = []
315  let listN: list<number> = []
316
317  assert_equal([1, 2, 3], list2)
318  list2[-1] = 99
319  assert_equal([1, 2, 99], list2)
320  list2[-2] = 88
321  assert_equal([1, 88, 99], list2)
322  list2[-3] = 77
323  assert_equal([77, 88, 99], list2)
324  list2 += [100]
325  assert_equal([77, 88, 99, 100], list2)
326
327  list3 += ['end']
328  assert_equal(['sdf', 'asdf', 'end'], list3)
329
330  CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
331  CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:')
332
333  # type becomes list<any>
334  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
335enddef
336
337def Test_assignment_list_vim9script()
338  let lines =<< trim END
339    vim9script
340    let v1: number
341    let v2: number
342    let v3: number
343    [v1, v2, v3] = [1, 2, 3]
344    assert_equal([1, 2, 3], [v1, v2, v3])
345  END
346  CheckScriptSuccess(lines)
347enddef
348
349def Test_assignment_dict()
350  let dict1: dict<bool> = #{one: false, two: true}
351  let dict2: dict<number> = #{one: 1, two: 2}
352  let dict3: dict<string> = #{key: 'value'}
353  let dict4: dict<any> = #{one: 1, two: '2'}
354  let dict5: dict<blob> = #{one: 0z01, two: 0z02}
355
356  # overwrite
357  dict3['key'] = 'another'
358
359  # empty key can be used
360  let dd = {}
361  dd[""] = 6
362  assert_equal({'': 6}, dd)
363
364  # type becomes dict<any>
365  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
366
367  # assignment to script-local dict
368  let lines =<< trim END
369    vim9script
370    let test: dict<any> = {}
371    def FillDict(): dict<any>
372      test['a'] = 43
373      return test
374    enddef
375    assert_equal(#{a: 43}, FillDict())
376  END
377  CheckScriptSuccess(lines)
378
379  lines =<< trim END
380    vim9script
381    let test: dict<any>
382    def FillDict(): dict<any>
383      test['a'] = 43
384      return test
385    enddef
386    FillDict()
387  END
388  CheckScriptFailure(lines, 'E1103:')
389
390  # assignment to global dict
391  lines =<< trim END
392    vim9script
393    g:test = {}
394    def FillDict(): dict<any>
395      g:test['a'] = 43
396      return g:test
397    enddef
398    assert_equal(#{a: 43}, FillDict())
399  END
400  CheckScriptSuccess(lines)
401
402  # assignment to buffer dict
403  lines =<< trim END
404    vim9script
405    b:test = {}
406    def FillDict(): dict<any>
407      b:test['a'] = 43
408      return b:test
409    enddef
410    assert_equal(#{a: 43}, FillDict())
411  END
412  CheckScriptSuccess(lines)
413enddef
414
415def Test_assignment_local()
416  # Test in a separated file in order not to the current buffer/window/tab is
417  # changed.
418  let script_lines: list<string> =<< trim END
419    let b:existing = 'yes'
420    let w:existing = 'yes'
421    let t:existing = 'yes'
422
423    def Test_assignment_local_internal()
424      b:newvar = 'new'
425      assert_equal('new', b:newvar)
426      assert_equal('yes', b:existing)
427      b:existing = 'no'
428      assert_equal('no', b:existing)
429      b:existing ..= 'NO'
430      assert_equal('noNO', b:existing)
431
432      w:newvar = 'new'
433      assert_equal('new', w:newvar)
434      assert_equal('yes', w:existing)
435      w:existing = 'no'
436      assert_equal('no', w:existing)
437      w:existing ..= 'NO'
438      assert_equal('noNO', w:existing)
439
440      t:newvar = 'new'
441      assert_equal('new', t:newvar)
442      assert_equal('yes', t:existing)
443      t:existing = 'no'
444      assert_equal('no', t:existing)
445      t:existing ..= 'NO'
446      assert_equal('noNO', t:existing)
447    enddef
448    call Test_assignment_local_internal()
449  END
450  CheckScriptSuccess(script_lines)
451enddef
452
453def Test_assignment_default()
454
455  # Test default values.
456  let thebool: bool
457  assert_equal(v:false, thebool)
458
459  let thenumber: number
460  assert_equal(0, thenumber)
461
462  if has('float')
463    let thefloat: float
464    assert_equal(0.0, thefloat)
465  endif
466
467  let thestring: string
468  assert_equal('', thestring)
469
470  let theblob: blob
471  assert_equal(0z, theblob)
472
473  let Thefunc: func
474  assert_equal(test_null_function(), Thefunc)
475
476  let thelist: list<any>
477  assert_equal([], thelist)
478
479  let thedict: dict<any>
480  assert_equal({}, thedict)
481
482  if has('channel')
483    let thejob: job
484    assert_equal(test_null_job(), thejob)
485
486    let thechannel: channel
487    assert_equal(test_null_channel(), thechannel)
488
489    if has('unix') && executable('cat')
490      # check with non-null job and channel, types must match
491      thejob = job_start("cat ", #{})
492      thechannel = job_getchannel(thejob)
493      job_stop(thejob, 'kill')
494    endif
495  endif
496
497  let nr = 1234 | nr = 5678
498  assert_equal(5678, nr)
499enddef
500
501def Test_assignment_var_list()
502  let v1: string
503  let v2: string
504  let vrem: list<string>
505  [v1] = ['aaa']
506  assert_equal('aaa', v1)
507
508  [v1, v2] = ['one', 'two']
509  assert_equal('one', v1)
510  assert_equal('two', v2)
511
512  [v1, v2; vrem] = ['one', 'two']
513  assert_equal('one', v1)
514  assert_equal('two', v2)
515  assert_equal([], vrem)
516
517  [v1, v2; vrem] = ['one', 'two', 'three']
518  assert_equal('one', v1)
519  assert_equal('two', v2)
520  assert_equal(['three'], vrem)
521
522  [&ts, &sw] = [3, 4]
523  assert_equal(3, &ts)
524  assert_equal(4, &sw)
525  set ts=8 sw=4
526enddef
527
528def Test_assignment_vim9script()
529  let lines =<< trim END
530    vim9script
531    def Func(): list<number>
532      return [1, 2]
533    enddef
534    let var1: number
535    let var2: number
536    [var1, var2] =
537          Func()
538    assert_equal(1, var1)
539    assert_equal(2, var2)
540    let ll =
541          Func()
542    assert_equal([1, 2], ll)
543
544    @/ = 'text'
545    assert_equal('text', @/)
546    @0 = 'zero'
547    assert_equal('zero', @0)
548    @1 = 'one'
549    assert_equal('one', @1)
550    @9 = 'nine'
551    assert_equal('nine', @9)
552    @- = 'minus'
553    assert_equal('minus', @-)
554    if has('clipboard_working')
555      @* = 'star'
556      assert_equal('star', @*)
557      @+ = 'plus'
558      assert_equal('plus', @+)
559    endif
560
561    let a: number = 123
562    assert_equal(123, a)
563    let s: string = 'yes'
564    assert_equal('yes', s)
565    let b: number = 42
566    assert_equal(42, b)
567    let w: number = 43
568    assert_equal(43, w)
569    let t: number = 44
570    assert_equal(44, t)
571  END
572  CheckScriptSuccess(lines)
573enddef
574
575def Mess(): string
576  v:foldstart = 123
577  return 'xxx'
578enddef
579
580def Test_assignment_failure()
581  CheckDefFailure(['let var=234'], 'E1004:')
582  CheckDefFailure(['let var =234'], 'E1004:')
583  CheckDefFailure(['let var= 234'], 'E1004:')
584
585  CheckScriptFailure(['vim9script', 'let var=234'], 'E1004:')
586  CheckScriptFailure(['vim9script', 'let var=234'], "before and after '='")
587  CheckScriptFailure(['vim9script', 'let var =234'], 'E1004:')
588  CheckScriptFailure(['vim9script', 'let var= 234'], 'E1004:')
589  CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], 'E1004:')
590  CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], "before and after '+='")
591  CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], 'E1004:')
592  CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], "before and after '..='")
593
594  CheckDefFailure(['let true = 1'], 'E1034:')
595  CheckDefFailure(['let false = 1'], 'E1034:')
596
597  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
598  CheckDefExecFailure(['let a: number',
599                       '[a] = test_null_list()'], 'E1093:')
600  CheckDefExecFailure(['let a: number',
601                       '[a] = []'], 'E1093:')
602  CheckDefExecFailure(['let x: number',
603                       'let y: number',
604                       '[x, y] = [1]'], 'E1093:')
605  CheckDefExecFailure(['let x: number',
606                       'let y: number',
607                       'let z: list<number>',
608                       '[x, y; z] = [1]'], 'E1093:')
609
610  CheckDefFailure(['let somevar'], "E1022:")
611  CheckDefFailure(['let &tabstop = 4'], 'E1052:')
612  CheckDefFailure(['&g:option = 5'], 'E113:')
613  CheckScriptFailure(['vim9script', 'let &tabstop = 4'], 'E1052:')
614
615  CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:')
616  CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:')
617
618  if has('dnd')
619    CheckDefFailure(['let @~ = 5'], 'E1066:')
620  else
621    CheckDefFailure(['let @~ = 5'], 'E354:')
622    CheckDefFailure(['@~ = 5'], 'E354:')
623  endif
624  CheckDefFailure(['let @a = 5'], 'E1066:')
625  CheckDefFailure(['let @/ = "x"'], 'E1066:')
626  CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:')
627
628  CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:')
629  CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:')
630  CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer variable:')
631  CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:')
632
633  CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
634  CheckDefFailure(['let xnr += 4'], 'E1020:', 1)
635  CheckScriptFailure(['vim9script', 'let xnr += 4'], 'E1020:')
636  CheckDefFailure(["let xnr = xnr + 1"], 'E1001:', 1)
637  CheckScriptFailure(['vim9script', 'let xnr = xnr + 4'], 'E121:')
638
639  CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
640
641  CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
642  CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
643
644  CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
645  CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
646
647  CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
648  CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
649
650  CheckDefFailure(['let var: dict <number>'], 'E1068:')
651  CheckDefFailure(['let var: dict<number'], 'E1009:')
652
653  assert_fails('s/^/\=Mess()/n', 'E794:')
654  CheckDefFailure(['let var: dict<number'], 'E1009:')
655
656  CheckDefFailure(['w:foo: number = 10'],
657                  'E488: Trailing characters: : number = 1')
658  CheckDefFailure(['t:foo: bool = true'],
659                  'E488: Trailing characters: : bool = true')
660  CheckDefFailure(['b:foo: string = "x"'],
661                  'E488: Trailing characters: : string = "x"')
662  CheckDefFailure(['g:foo: number = 123'],
663                  'E488: Trailing characters: : number = 123')
664enddef
665
666def Test_unlet()
667  g:somevar = 'yes'
668  assert_true(exists('g:somevar'))
669  unlet g:somevar
670  assert_false(exists('g:somevar'))
671  unlet! g:somevar
672
673  # also works for script-local variable in legacy Vim script
674  s:somevar = 'legacy'
675  assert_true(exists('s:somevar'))
676  unlet s:somevar
677  assert_false(exists('s:somevar'))
678  unlet! s:somevar
679
680  CheckScriptFailure([
681   'vim9script',
682   'let svar = 123',
683   'unlet svar',
684   ], 'E1081:')
685  CheckScriptFailure([
686   'vim9script',
687   'let svar = 123',
688   'unlet s:svar',
689   ], 'E1081:')
690  CheckScriptFailure([
691   'vim9script',
692   'let svar = 123',
693   'def Func()',
694   '  unlet svar',
695   'enddef',
696   'defcompile',
697   ], 'E1081:')
698  CheckScriptFailure([
699   'vim9script',
700   'let svar = 123',
701   'def Func()',
702   '  unlet s:svar',
703   'enddef',
704   'defcompile',
705   ], 'E1081:')
706
707  $ENVVAR = 'foobar'
708  assert_equal('foobar', $ENVVAR)
709  unlet $ENVVAR
710  assert_equal('', $ENVVAR)
711enddef
712
713def Test_delfunction()
714  # Check function is defined in script namespace
715  CheckScriptSuccess([
716      'vim9script',
717      'func CheckMe()',
718      '  return 123',
719      'endfunc',
720      'assert_equal(123, s:CheckMe())',
721      ])
722
723  # Check function in script namespace cannot be deleted
724  CheckScriptFailure([
725      'vim9script',
726      'func DeleteMe1()',
727      'endfunc',
728      'delfunction DeleteMe1',
729      ], 'E1084:')
730  CheckScriptFailure([
731      'vim9script',
732      'func DeleteMe2()',
733      'endfunc',
734      'def DoThat()',
735      '  delfunction DeleteMe2',
736      'enddef',
737      'DoThat()',
738      ], 'E1084:')
739  CheckScriptFailure([
740      'vim9script',
741      'def DeleteMe3()',
742      'enddef',
743      'delfunction DeleteMe3',
744      ], 'E1084:')
745  CheckScriptFailure([
746      'vim9script',
747      'def DeleteMe4()',
748      'enddef',
749      'def DoThat()',
750      '  delfunction DeleteMe4',
751      'enddef',
752      'DoThat()',
753      ], 'E1084:')
754
755  # Check that global :def function can be replaced and deleted
756  let lines =<< trim END
757      vim9script
758      def g:Global(): string
759        return "yes"
760      enddef
761      assert_equal("yes", g:Global())
762      def! g:Global(): string
763        return "no"
764      enddef
765      assert_equal("no", g:Global())
766      delfunc g:Global
767      assert_false(exists('*g:Global'))
768  END
769  CheckScriptSuccess(lines)
770
771  # Check that global function can be replaced by a :def function and deleted
772  lines =<< trim END
773      vim9script
774      func g:Global()
775        return "yes"
776      endfunc
777      assert_equal("yes", g:Global())
778      def! g:Global(): string
779        return "no"
780      enddef
781      assert_equal("no", g:Global())
782      delfunc g:Global
783      assert_false(exists('*g:Global'))
784  END
785  CheckScriptSuccess(lines)
786
787  # Check that global :def function can be replaced by a function and deleted
788  lines =<< trim END
789      vim9script
790      def g:Global(): string
791        return "yes"
792      enddef
793      assert_equal("yes", g:Global())
794      func! g:Global()
795        return "no"
796      endfunc
797      assert_equal("no", g:Global())
798      delfunc g:Global
799      assert_false(exists('*g:Global'))
800  END
801  CheckScriptSuccess(lines)
802enddef
803
804def Test_wrong_type()
805  CheckDefFailure(['let var: list<nothing>'], 'E1010:')
806  CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
807  CheckDefFailure(['let var: dict<nothing>'], 'E1010:')
808  CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:')
809
810  CheckDefFailure(['let var: dict<number'], 'E1009:')
811  CheckDefFailure(['let var: dict<list<number>'], 'E1009:')
812
813  CheckDefFailure(['let var: ally'], 'E1010:')
814  CheckDefFailure(['let var: bram'], 'E1010:')
815  CheckDefFailure(['let var: cathy'], 'E1010:')
816  CheckDefFailure(['let var: dom'], 'E1010:')
817  CheckDefFailure(['let var: freddy'], 'E1010:')
818  CheckDefFailure(['let var: john'], 'E1010:')
819  CheckDefFailure(['let var: larry'], 'E1010:')
820  CheckDefFailure(['let var: ned'], 'E1010:')
821  CheckDefFailure(['let var: pam'], 'E1010:')
822  CheckDefFailure(['let var: sam'], 'E1010:')
823  CheckDefFailure(['let var: vim'], 'E1010:')
824
825  CheckDefFailure(['let Ref: number', 'Ref()'], 'E1085:')
826  CheckDefFailure(['let Ref: string', 'let res = Ref()'], 'E1085:')
827enddef
828
829def Test_const()
830  CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
831  CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
832  CheckDefFailure(['const list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
833  CheckDefFailure(['const two'], 'E1021:')
834  CheckDefFailure(['const &option'], 'E996:')
835
836  let lines =<< trim END
837    const list = [1, 2, 3]
838    list[0] = 4
839    list->assert_equal([4, 2, 3])
840    const! other = [5, 6, 7]
841    other->assert_equal([5, 6, 7])
842
843    let varlist = [7, 8]
844    const! constlist = [1, varlist, 3]
845    varlist[0] = 77
846    # TODO: does not work yet
847    # constlist[1][1] = 88
848    let cl = constlist[1]
849    cl[1] = 88
850    constlist->assert_equal([1, [77, 88], 3])
851
852    let vardict = #{five: 5, six: 6}
853    const! constdict = #{one: 1, two: vardict, three: 3}
854    vardict['five'] = 55
855    # TODO: does not work yet
856    # constdict['two']['six'] = 66
857    let cd = constdict['two']
858    cd['six'] = 66
859    constdict->assert_equal(#{one: 1, two: #{five: 55, six: 66}, three: 3})
860  END
861  CheckDefAndScriptSuccess(lines)
862enddef
863
864def Test_const_bang()
865  let lines =<< trim END
866      const! var = 234
867      var = 99
868  END
869  CheckDefExecFailure(lines, 'E1018:', 2)
870  CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
871
872  lines =<< trim END
873      const! ll = [2, 3, 4]
874      ll[0] = 99
875  END
876  CheckDefExecFailure(lines, 'E1119:', 2)
877  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
878
879  lines =<< trim END
880      const! ll = [2, 3, 4]
881      ll[3] = 99
882  END
883  CheckDefExecFailure(lines, 'E1118:', 2)
884  CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
885
886  lines =<< trim END
887      const! dd = #{one: 1, two: 2}
888      dd["one"] = 99
889  END
890  CheckDefExecFailure(lines, 'E1121:', 2)
891  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
892
893  lines =<< trim END
894      const! dd = #{one: 1, two: 2}
895      dd["three"] = 99
896  END
897  CheckDefExecFailure(lines, 'E1120:')
898  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
899enddef
900
901def Test_range_no_colon()
902  CheckDefFailure(['%s/a/b/'], 'E1050:')
903  CheckDefFailure(['+ s/a/b/'], 'E1050:')
904  CheckDefFailure(['- s/a/b/'], 'E1050:')
905  CheckDefFailure(['. s/a/b/'], 'E1050:')
906enddef
907
908
909def Test_block()
910  let outer = 1
911  {
912    let inner = 2
913    assert_equal(1, outer)
914    assert_equal(2, inner)
915  }
916  assert_equal(1, outer)
917enddef
918
919def Test_block_failure()
920  CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
921  CheckDefFailure(['}'], 'E1025:')
922  CheckDefFailure(['{', 'echo 1'], 'E1026:')
923enddef
924
925func g:NoSuchFunc()
926  echo 'none'
927endfunc
928
929def Test_try_catch()
930  let l = []
931  try # comment
932    add(l, '1')
933    throw 'wrong'
934    add(l, '2')
935  catch # comment
936    add(l, v:exception)
937  finally # comment
938    add(l, '3')
939  endtry # comment
940  assert_equal(['1', 'wrong', '3'], l)
941
942  l = []
943  try
944    try
945      add(l, '1')
946      throw 'wrong'
947      add(l, '2')
948    catch /right/
949      add(l, v:exception)
950    endtry
951  catch /wrong/
952    add(l, 'caught')
953  finally
954    add(l, 'finally')
955  endtry
956  assert_equal(['1', 'caught', 'finally'], l)
957
958  let n: number
959  try
960    n = l[3]
961  catch /E684:/
962    n = 99
963  endtry
964  assert_equal(99, n)
965
966  try
967    # string slice returns a string, not a number
968    n = g:astring[3]
969  catch /E1012:/
970    n = 77
971  endtry
972  assert_equal(77, n)
973
974  try
975    n = l[g:astring]
976  catch /E1012:/
977    n = 88
978  endtry
979  assert_equal(88, n)
980
981  try
982    n = s:does_not_exist
983  catch /E121:/
984    n = 111
985  endtry
986  assert_equal(111, n)
987
988  try
989    n = g:does_not_exist
990  catch /E121:/
991    n = 121
992  endtry
993  assert_equal(121, n)
994
995  let d = #{one: 1}
996  try
997    n = d[g:astring]
998  catch /E716:/
999    n = 222
1000  endtry
1001  assert_equal(222, n)
1002
1003  try
1004    n = -g:astring
1005  catch /E39:/
1006    n = 233
1007  endtry
1008  assert_equal(233, n)
1009
1010  try
1011    n = +g:astring
1012  catch /E1030:/
1013    n = 244
1014  endtry
1015  assert_equal(244, n)
1016
1017  try
1018    n = +g:alist
1019  catch /E745:/
1020    n = 255
1021  endtry
1022  assert_equal(255, n)
1023
1024  let nd: dict<any>
1025  try
1026    nd = {g:anumber: 1}
1027  catch /E1012:/
1028    n = 266
1029  endtry
1030  assert_equal(266, n)
1031
1032  try
1033    [n] = [1, 2, 3]
1034  catch /E1093:/
1035    n = 277
1036  endtry
1037  assert_equal(277, n)
1038
1039  try
1040    &ts = g:astring
1041  catch /E1012:/
1042    n = 288
1043  endtry
1044  assert_equal(288, n)
1045
1046  try
1047    &backspace = 'asdf'
1048  catch /E474:/
1049    n = 299
1050  endtry
1051  assert_equal(299, n)
1052
1053  l = [1]
1054  try
1055    l[3] = 3
1056  catch /E684:/
1057    n = 300
1058  endtry
1059  assert_equal(300, n)
1060
1061  try
1062    unlet g:does_not_exist
1063  catch /E108:/
1064    n = 322
1065  endtry
1066  assert_equal(322, n)
1067
1068  try
1069    d = {'text': 1, g:astring: 2}
1070  catch /E721:/
1071    n = 333
1072  endtry
1073  assert_equal(333, n)
1074
1075  try
1076    l = DeletedFunc()
1077  catch /E933:/
1078    n = 344
1079  endtry
1080  assert_equal(344, n)
1081
1082  try
1083    echo len(v:true)
1084  catch /E701:/
1085    n = 355
1086  endtry
1087  assert_equal(355, n)
1088
1089  let P = function('g:NoSuchFunc')
1090  delfunc g:NoSuchFunc
1091  try
1092    echo P()
1093  catch /E117:/
1094    n = 366
1095  endtry
1096  assert_equal(366, n)
1097
1098  try
1099    echo g:NoSuchFunc()
1100  catch /E117:/
1101    n = 377
1102  endtry
1103  assert_equal(377, n)
1104
1105  try
1106    echo g:alist + 4
1107  catch /E745:/
1108    n = 388
1109  endtry
1110  assert_equal(388, n)
1111
1112  try
1113    echo 4 + g:alist
1114  catch /E745:/
1115    n = 399
1116  endtry
1117  assert_equal(399, n)
1118
1119  try
1120    echo g:alist.member
1121  catch /E715:/
1122    n = 400
1123  endtry
1124  assert_equal(400, n)
1125
1126  try
1127    echo d.member
1128  catch /E716:/
1129    n = 411
1130  endtry
1131  assert_equal(411, n)
1132enddef
1133
1134def DeletedFunc(): list<any>
1135  return ['delete me']
1136enddef
1137defcompile
1138delfunc DeletedFunc
1139
1140def ThrowFromDef()
1141  throw "getout" # comment
1142enddef
1143
1144func CatchInFunc()
1145  try
1146    call ThrowFromDef()
1147  catch
1148    let g:thrown_func = v:exception
1149  endtry
1150endfunc
1151
1152def CatchInDef()
1153  try
1154    ThrowFromDef()
1155  catch
1156    g:thrown_def = v:exception
1157  endtry
1158enddef
1159
1160def ReturnFinally(): string
1161  try
1162    return 'intry'
1163  finally
1164    g:in_finally = 'finally'
1165  endtry
1166  return 'end'
1167enddef
1168
1169def Test_try_catch_nested()
1170  CatchInFunc()
1171  assert_equal('getout', g:thrown_func)
1172
1173  CatchInDef()
1174  assert_equal('getout', g:thrown_def)
1175
1176  assert_equal('intry', ReturnFinally())
1177  assert_equal('finally', g:in_finally)
1178enddef
1179
1180def TryOne(): number
1181  try
1182    return 0
1183  catch
1184  endtry
1185  return 0
1186enddef
1187
1188def TryTwo(n: number): string
1189  try
1190    let x = {}
1191  catch
1192  endtry
1193  return 'text'
1194enddef
1195
1196def Test_try_catch_twice()
1197  assert_equal('text', TryOne()->TryTwo())
1198enddef
1199
1200def Test_try_catch_match()
1201  let seq = 'a'
1202  try
1203    throw 'something'
1204  catch /nothing/
1205    seq ..= 'x'
1206  catch /some/
1207    seq ..= 'b'
1208  catch /asdf/
1209    seq ..= 'x'
1210  catch ?a\?sdf?
1211    seq ..= 'y'
1212  finally
1213    seq ..= 'c'
1214  endtry
1215  assert_equal('abc', seq)
1216enddef
1217
1218def Test_try_catch_fails()
1219  CheckDefFailure(['catch'], 'E603:')
1220  CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:')
1221  CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
1222  CheckDefFailure(['finally'], 'E606:')
1223  CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
1224  CheckDefFailure(['endtry'], 'E602:')
1225  CheckDefFailure(['while 1', 'endtry'], 'E170:')
1226  CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
1227  CheckDefFailure(['if 2', 'endtry'], 'E171:')
1228  CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
1229
1230  CheckDefFailure(['throw'], 'E1015:')
1231  CheckDefFailure(['throw xxx'], 'E1001:')
1232enddef
1233
1234def Test_throw_vimscript()
1235  # only checks line continuation
1236  let lines =<< trim END
1237      vim9script
1238      try
1239        throw 'one'
1240              .. 'two'
1241      catch
1242        assert_equal('onetwo', v:exception)
1243      endtry
1244  END
1245  CheckScriptSuccess(lines)
1246enddef
1247
1248def Test_error_in_nested_function()
1249  # an error in a nested :function aborts executin in the calling :def function
1250  let lines =<< trim END
1251      vim9script
1252      def Func()
1253        Error()
1254        g:test_var = 1
1255      enddef
1256      func Error() abort
1257        eval [][0]
1258      endfunc
1259      Func()
1260  END
1261  g:test_var = 0
1262  CheckScriptFailure(lines, 'E684:')
1263  assert_equal(0, g:test_var)
1264enddef
1265
1266def Test_cexpr_vimscript()
1267  # only checks line continuation
1268  set errorformat=File\ %f\ line\ %l
1269  let lines =<< trim END
1270      vim9script
1271      cexpr 'File'
1272                .. ' someFile' ..
1273                   ' line 19'
1274      assert_equal(19, getqflist()[0].lnum)
1275  END
1276  CheckScriptSuccess(lines)
1277  set errorformat&
1278enddef
1279
1280def Test_statusline_syntax()
1281  # legacy syntax is used for 'statusline'
1282  let lines =<< trim END
1283      vim9script
1284      func g:Status()
1285        return '%{"x" is# "x"}'
1286      endfunc
1287      set laststatus=2 statusline=%!Status()
1288      redrawstatus
1289      set laststatus statusline=
1290  END
1291  CheckScriptSuccess(lines)
1292enddef
1293
1294def Test_list_vimscript()
1295  # checks line continuation and comments
1296  let lines =<< trim END
1297      vim9script
1298      let mylist = [
1299            'one',
1300            # comment
1301            'two', # empty line follows
1302
1303            'three',
1304            ]
1305      assert_equal(['one', 'two', 'three'], mylist)
1306  END
1307  CheckScriptSuccess(lines)
1308
1309  # check all lines from heredoc are kept
1310  lines =<< trim END
1311      # comment 1
1312      two
1313      # comment 3
1314
1315      five
1316      # comment 6
1317  END
1318  assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines)
1319enddef
1320
1321if has('channel')
1322  let someJob = test_null_job()
1323
1324  def FuncWithError()
1325    echomsg g:someJob
1326  enddef
1327
1328  func Test_convert_emsg_to_exception()
1329    try
1330      call FuncWithError()
1331    catch
1332      call assert_match('Vim:E908:', v:exception)
1333    endtry
1334  endfunc
1335endif
1336
1337let s:export_script_lines =<< trim END
1338  vim9script
1339  let name: string = 'bob'
1340  def Concat(arg: string): string
1341    return name .. arg
1342  enddef
1343  g:result = Concat('bie')
1344  g:localname = name
1345
1346  export const CONST = 1234
1347  export let exported = 9876
1348  export let exp_name = 'John'
1349  export def Exported(): string
1350    return 'Exported'
1351  enddef
1352END
1353
1354def Undo_export_script_lines()
1355  unlet g:result
1356  unlet g:localname
1357enddef
1358
1359def Test_vim9_import_export()
1360  let import_script_lines =<< trim END
1361    vim9script
1362    import {exported, Exported} from './Xexport.vim'
1363    g:imported = exported
1364    exported += 3
1365    g:imported_added = exported
1366    g:imported_func = Exported()
1367
1368    def GetExported(): string
1369      let local_dict = #{ref: Exported}
1370      return local_dict.ref()
1371    enddef
1372    g:funcref_result = GetExported()
1373
1374    import {exp_name} from './Xexport.vim'
1375    g:imported_name = exp_name
1376    exp_name ..= ' Doe'
1377    g:imported_name_appended = exp_name
1378    g:imported_later = exported
1379  END
1380
1381  writefile(import_script_lines, 'Ximport.vim')
1382  writefile(s:export_script_lines, 'Xexport.vim')
1383
1384  source Ximport.vim
1385
1386  assert_equal('bobbie', g:result)
1387  assert_equal('bob', g:localname)
1388  assert_equal(9876, g:imported)
1389  assert_equal(9879, g:imported_added)
1390  assert_equal(9879, g:imported_later)
1391  assert_equal('Exported', g:imported_func)
1392  assert_equal('Exported', g:funcref_result)
1393  assert_equal('John', g:imported_name)
1394  assert_equal('John Doe', g:imported_name_appended)
1395  assert_false(exists('g:name'))
1396
1397  Undo_export_script_lines()
1398  unlet g:imported
1399  unlet g:imported_added
1400  unlet g:imported_later
1401  unlet g:imported_func
1402  unlet g:imported_name g:imported_name_appended
1403  delete('Ximport.vim')
1404
1405  # similar, with line breaks
1406  let import_line_break_script_lines =<< trim END
1407    vim9script
1408    import {
1409        exported,
1410        Exported,
1411        }
1412        from
1413        './Xexport.vim'
1414    g:imported = exported
1415    exported += 5
1416    g:imported_added = exported
1417    g:imported_func = Exported()
1418  END
1419  writefile(import_line_break_script_lines, 'Ximport_lbr.vim')
1420  source Ximport_lbr.vim
1421
1422  assert_equal(9876, g:imported)
1423  assert_equal(9881, g:imported_added)
1424  assert_equal('Exported', g:imported_func)
1425
1426  # exported script not sourced again
1427  assert_false(exists('g:result'))
1428  unlet g:imported
1429  unlet g:imported_added
1430  unlet g:imported_func
1431  delete('Ximport_lbr.vim')
1432
1433  # import inside :def function
1434  let import_in_def_lines =<< trim END
1435    vim9script
1436    def ImportInDef()
1437      import exported from './Xexport.vim'
1438      g:imported = exported
1439      exported += 7
1440      g:imported_added = exported
1441    enddef
1442    ImportInDef()
1443  END
1444  writefile(import_in_def_lines, 'Ximport2.vim')
1445  source Ximport2.vim
1446  # TODO: this should be 9879
1447  assert_equal(9876, g:imported)
1448  assert_equal(9883, g:imported_added)
1449  unlet g:imported
1450  unlet g:imported_added
1451  delete('Ximport2.vim')
1452
1453  let import_star_as_lines =<< trim END
1454    vim9script
1455    import * as Export from './Xexport.vim'
1456    def UseExport()
1457      g:imported = Export.exported
1458    enddef
1459    UseExport()
1460  END
1461  writefile(import_star_as_lines, 'Ximport.vim')
1462  source Ximport.vim
1463  assert_equal(9883, g:imported)
1464
1465  let import_star_as_lines_no_dot =<< trim END
1466    vim9script
1467    import * as Export from './Xexport.vim'
1468    def Func()
1469      let dummy = 1
1470      let imported = Export + dummy
1471    enddef
1472    defcompile
1473  END
1474  writefile(import_star_as_lines_no_dot, 'Ximport.vim')
1475  assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func')
1476
1477  let import_star_as_lines_dot_space =<< trim END
1478    vim9script
1479    import * as Export from './Xexport.vim'
1480    def Func()
1481      let imported = Export . exported
1482    enddef
1483    defcompile
1484  END
1485  writefile(import_star_as_lines_dot_space, 'Ximport.vim')
1486  assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func')
1487
1488  let import_star_as_lines_missing_name =<< trim END
1489    vim9script
1490    import * as Export from './Xexport.vim'
1491    def Func()
1492      let imported = Export.
1493    enddef
1494    defcompile
1495  END
1496  writefile(import_star_as_lines_missing_name, 'Ximport.vim')
1497  assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func')
1498
1499  let import_star_as_lbr_lines =<< trim END
1500    vim9script
1501    import *
1502        as Export
1503        from
1504        './Xexport.vim'
1505    def UseExport()
1506      g:imported = Export.exported
1507    enddef
1508    UseExport()
1509  END
1510  writefile(import_star_as_lbr_lines, 'Ximport.vim')
1511  source Ximport.vim
1512  assert_equal(9883, g:imported)
1513
1514  let import_star_lines =<< trim END
1515    vim9script
1516    import * from './Xexport.vim'
1517  END
1518  writefile(import_star_lines, 'Ximport.vim')
1519  assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim')
1520
1521  # try to import something that exists but is not exported
1522  let import_not_exported_lines =<< trim END
1523    vim9script
1524    import name from './Xexport.vim'
1525  END
1526  writefile(import_not_exported_lines, 'Ximport.vim')
1527  assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim')
1528
1529  # try to import something that is already defined
1530  let import_already_defined =<< trim END
1531    vim9script
1532    let exported = 'something'
1533    import exported from './Xexport.vim'
1534  END
1535  writefile(import_already_defined, 'Ximport.vim')
1536  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1537
1538  # try to import something that is already defined
1539  import_already_defined =<< trim END
1540    vim9script
1541    let exported = 'something'
1542    import * as exported from './Xexport.vim'
1543  END
1544  writefile(import_already_defined, 'Ximport.vim')
1545  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1546
1547  # try to import something that is already defined
1548  import_already_defined =<< trim END
1549    vim9script
1550    let exported = 'something'
1551    import {exported} from './Xexport.vim'
1552  END
1553  writefile(import_already_defined, 'Ximport.vim')
1554  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1555
1556  # import a very long name, requires making a copy
1557  let import_long_name_lines =<< trim END
1558    vim9script
1559    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
1560  END
1561  writefile(import_long_name_lines, 'Ximport.vim')
1562  assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim')
1563
1564  let import_no_from_lines =<< trim END
1565    vim9script
1566    import name './Xexport.vim'
1567  END
1568  writefile(import_no_from_lines, 'Ximport.vim')
1569  assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim')
1570
1571  let import_invalid_string_lines =<< trim END
1572    vim9script
1573    import name from Xexport.vim
1574  END
1575  writefile(import_invalid_string_lines, 'Ximport.vim')
1576  assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim')
1577
1578  let import_wrong_name_lines =<< trim END
1579    vim9script
1580    import name from './XnoExport.vim'
1581  END
1582  writefile(import_wrong_name_lines, 'Ximport.vim')
1583  assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim')
1584
1585  let import_missing_comma_lines =<< trim END
1586    vim9script
1587    import {exported name} from './Xexport.vim'
1588  END
1589  writefile(import_missing_comma_lines, 'Ximport3.vim')
1590  assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim')
1591
1592  delete('Ximport.vim')
1593  delete('Ximport3.vim')
1594  delete('Xexport.vim')
1595
1596  # Check that in a Vim9 script 'cpo' is set to the Vim default.
1597  set cpo&vi
1598  let cpo_before = &cpo
1599  let lines =<< trim END
1600    vim9script
1601    g:cpo_in_vim9script = &cpo
1602  END
1603  writefile(lines, 'Xvim9_script')
1604  source Xvim9_script
1605  assert_equal(cpo_before, &cpo)
1606  set cpo&vim
1607  assert_equal(&cpo, g:cpo_in_vim9script)
1608  delete('Xvim9_script')
1609enddef
1610
1611func g:Trigger()
1612  source Ximport.vim
1613  return "echo 'yes'\<CR>"
1614endfunc
1615
1616def Test_import_export_expr_map()
1617  # check that :import and :export work when buffer is locked
1618  let export_lines =<< trim END
1619    vim9script
1620    export def That(): string
1621      return 'yes'
1622    enddef
1623  END
1624  writefile(export_lines, 'Xexport_that.vim')
1625
1626  let import_lines =<< trim END
1627    vim9script
1628    import That from './Xexport_that.vim'
1629    assert_equal('yes', That())
1630  END
1631  writefile(import_lines, 'Ximport.vim')
1632
1633  nnoremap <expr> trigger g:Trigger()
1634  feedkeys('trigger', "xt")
1635
1636  delete('Xexport_that.vim')
1637  delete('Ximport.vim')
1638  nunmap trigger
1639enddef
1640
1641def Test_import_in_filetype()
1642  # check that :import works when the buffer is locked
1643  mkdir('ftplugin', 'p')
1644  let export_lines =<< trim END
1645    vim9script
1646    export let That = 'yes'
1647  END
1648  writefile(export_lines, 'ftplugin/Xexport_ft.vim')
1649
1650  let import_lines =<< trim END
1651    vim9script
1652    import That from './Xexport_ft.vim'
1653    assert_equal('yes', That)
1654    g:did_load_mytpe = 1
1655  END
1656  writefile(import_lines, 'ftplugin/qf.vim')
1657
1658  let save_rtp = &rtp
1659  &rtp = getcwd() .. ',' .. &rtp
1660
1661  filetype plugin on
1662  copen
1663  assert_equal(1, g:did_load_mytpe)
1664
1665  quit!
1666  delete('Xexport_ft.vim')
1667  delete('ftplugin', 'rf')
1668  &rtp = save_rtp
1669enddef
1670
1671def Test_use_import_in_mapping()
1672  let lines =<< trim END
1673      vim9script
1674      export def Funcx()
1675        g:result = 42
1676      enddef
1677  END
1678  writefile(lines, 'XsomeExport.vim')
1679  lines =<< trim END
1680      vim9script
1681      import Funcx from './XsomeExport.vim'
1682      nnoremap <F3> :call <sid>Funcx()<cr>
1683  END
1684  writefile(lines, 'Xmapscript.vim')
1685
1686  source Xmapscript.vim
1687  feedkeys("\<F3>", "xt")
1688  assert_equal(42, g:result)
1689
1690  unlet g:result
1691  delete('XsomeExport.vim')
1692  delete('Xmapscript.vim')
1693  nunmap <F3>
1694enddef
1695
1696def Test_vim9script_fails()
1697  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
1698  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
1699  CheckScriptFailure(['export let some = 123'], 'E1042:')
1700  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:')
1701  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1022:')
1702  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
1703
1704  CheckScriptFailure(['vim9script', 'let str: string', 'str = 1234'], 'E1012:')
1705  CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:')
1706
1707  assert_fails('vim9script', 'E1038:')
1708  assert_fails('export something', 'E1043:')
1709enddef
1710
1711func Test_import_fails_without_script()
1712  CheckRunVimInTerminal
1713
1714  " call indirectly to avoid compilation error for missing functions
1715  call Run_Test_import_fails_on_command_line()
1716endfunc
1717
1718def Run_Test_import_fails_on_command_line()
1719  let export =<< trim END
1720    vim9script
1721    export def Foo(): number
1722        return 0
1723    enddef
1724  END
1725  writefile(export, 'XexportCmd.vim')
1726
1727  let buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', #{
1728                rows: 6, wait_for_ruler: 0})
1729  WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))})
1730
1731  delete('XexportCmd.vim')
1732  StopVimInTerminal(buf)
1733enddef
1734
1735def Test_vim9script_reload_import()
1736  let lines =<< trim END
1737    vim9script
1738    const var = ''
1739    let valone = 1234
1740    def MyFunc(arg: string)
1741       valone = 5678
1742    enddef
1743  END
1744  let morelines =<< trim END
1745    let valtwo = 222
1746    export def GetValtwo(): number
1747      return valtwo
1748    enddef
1749  END
1750  writefile(lines + morelines, 'Xreload.vim')
1751  source Xreload.vim
1752  source Xreload.vim
1753  source Xreload.vim
1754
1755  let testlines =<< trim END
1756    vim9script
1757    def TheFunc()
1758      import GetValtwo from './Xreload.vim'
1759      assert_equal(222, GetValtwo())
1760    enddef
1761    TheFunc()
1762  END
1763  writefile(testlines, 'Ximport.vim')
1764  source Ximport.vim
1765
1766  # Test that when not using "morelines" GetValtwo() and valtwo are still
1767  # defined, because import doesn't reload a script.
1768  writefile(lines, 'Xreload.vim')
1769  source Ximport.vim
1770
1771  # cannot declare a var twice
1772  lines =<< trim END
1773    vim9script
1774    let valone = 1234
1775    let valone = 5678
1776  END
1777  writefile(lines, 'Xreload.vim')
1778  assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim')
1779
1780  delete('Xreload.vim')
1781  delete('Ximport.vim')
1782enddef
1783
1784def s:RetSome(): string
1785  return 'some'
1786enddef
1787
1788" Not exported function that is referenced needs to be accessed by the
1789" script-local name.
1790def Test_vim9script_funcref()
1791  let sortlines =<< trim END
1792      vim9script
1793      def Compare(i1: number, i2: number): number
1794        return i2 - i1
1795      enddef
1796
1797      export def FastSort(): list<number>
1798        return range(5)->sort(Compare)
1799      enddef
1800  END
1801  writefile(sortlines, 'Xsort.vim')
1802
1803  let lines =<< trim END
1804    vim9script
1805    import FastSort from './Xsort.vim'
1806    def Test()
1807      g:result = FastSort()
1808    enddef
1809    Test()
1810  END
1811  writefile(lines, 'Xscript.vim')
1812
1813  source Xscript.vim
1814  assert_equal([4, 3, 2, 1, 0], g:result)
1815
1816  unlet g:result
1817  delete('Xsort.vim')
1818  delete('Xscript.vim')
1819
1820  let Funcref = function('s:RetSome')
1821  assert_equal('some', Funcref())
1822enddef
1823
1824" Check that when searching for "FilterFunc" it finds the import in the
1825" script where FastFilter() is called from, both as a string and as a direct
1826" function reference.
1827def Test_vim9script_funcref_other_script()
1828  let filterLines =<< trim END
1829    vim9script
1830    export def FilterFunc(idx: number, val: number): bool
1831      return idx % 2 == 1
1832    enddef
1833    export def FastFilter(): list<number>
1834      return range(10)->filter('FilterFunc')
1835    enddef
1836    export def FastFilterDirect(): list<number>
1837      return range(10)->filter(FilterFunc)
1838    enddef
1839  END
1840  writefile(filterLines, 'Xfilter.vim')
1841
1842  let lines =<< trim END
1843    vim9script
1844    import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim'
1845    def Test()
1846      let x: list<number> = FastFilter()
1847    enddef
1848    Test()
1849    def TestDirect()
1850      let x: list<number> = FastFilterDirect()
1851    enddef
1852    TestDirect()
1853  END
1854  CheckScriptSuccess(lines)
1855  delete('Xfilter.vim')
1856enddef
1857
1858def Test_vim9script_reload_delfunc()
1859  let first_lines =<< trim END
1860    vim9script
1861    def FuncYes(): string
1862      return 'yes'
1863    enddef
1864  END
1865  let withno_lines =<< trim END
1866    def FuncNo(): string
1867      return 'no'
1868    enddef
1869    def g:DoCheck(no_exists: bool)
1870      assert_equal('yes', FuncYes())
1871      assert_equal('no', FuncNo())
1872    enddef
1873  END
1874  let nono_lines =<< trim END
1875    def g:DoCheck(no_exists: bool)
1876      assert_equal('yes', FuncYes())
1877      assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck')
1878    enddef
1879  END
1880
1881  # FuncNo() is defined
1882  writefile(first_lines + withno_lines, 'Xreloaded.vim')
1883  source Xreloaded.vim
1884  g:DoCheck(true)
1885
1886  # FuncNo() is not redefined
1887  writefile(first_lines + nono_lines, 'Xreloaded.vim')
1888  source Xreloaded.vim
1889  g:DoCheck()
1890
1891  # FuncNo() is back
1892  writefile(first_lines + withno_lines, 'Xreloaded.vim')
1893  source Xreloaded.vim
1894  g:DoCheck()
1895
1896  delete('Xreloaded.vim')
1897enddef
1898
1899def Test_vim9script_reload_delvar()
1900  # write the script with a script-local variable
1901  let lines =<< trim END
1902    vim9script
1903    let var = 'string'
1904  END
1905  writefile(lines, 'XreloadVar.vim')
1906  source XreloadVar.vim
1907
1908  # now write the script using the same variable locally - works
1909  lines =<< trim END
1910    vim9script
1911    def Func()
1912      let var = 'string'
1913    enddef
1914  END
1915  writefile(lines, 'XreloadVar.vim')
1916  source XreloadVar.vim
1917
1918  delete('XreloadVar.vim')
1919enddef
1920
1921def Test_import_absolute()
1922  let import_lines = [
1923        'vim9script',
1924        'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
1925        'def UseExported()',
1926        '  g:imported_abs = exported',
1927        '  exported = 8888',
1928        '  g:imported_after = exported',
1929        'enddef',
1930        'UseExported()',
1931        'g:import_disassembled = execute("disass UseExported")',
1932        ]
1933  writefile(import_lines, 'Ximport_abs.vim')
1934  writefile(s:export_script_lines, 'Xexport_abs.vim')
1935
1936  source Ximport_abs.vim
1937
1938  assert_equal(9876, g:imported_abs)
1939  assert_equal(8888, g:imported_after)
1940  assert_match('<SNR>\d\+_UseExported.*' ..
1941          'g:imported_abs = exported.*' ..
1942          '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
1943          '1 STOREG g:imported_abs.*' ..
1944          'exported = 8888.*' ..
1945          '3 STORESCRIPT exported in .*Xexport_abs.vim.*' ..
1946          'g:imported_after = exported.*' ..
1947          '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
1948          '5 STOREG g:imported_after.*',
1949        g:import_disassembled)
1950
1951  Undo_export_script_lines()
1952  unlet g:imported_abs
1953  unlet g:import_disassembled
1954
1955  delete('Ximport_abs.vim')
1956  delete('Xexport_abs.vim')
1957enddef
1958
1959def Test_import_rtp()
1960  let import_lines = [
1961        'vim9script',
1962        'import exported from "Xexport_rtp.vim"',
1963        'g:imported_rtp = exported',
1964        ]
1965  writefile(import_lines, 'Ximport_rtp.vim')
1966  mkdir('import')
1967  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
1968
1969  let save_rtp = &rtp
1970  &rtp = getcwd()
1971  source Ximport_rtp.vim
1972  &rtp = save_rtp
1973
1974  assert_equal(9876, g:imported_rtp)
1975
1976  Undo_export_script_lines()
1977  unlet g:imported_rtp
1978  delete('Ximport_rtp.vim')
1979  delete('import', 'rf')
1980enddef
1981
1982def Test_import_compile_error()
1983  let export_lines = [
1984        'vim9script',
1985        'export def ExpFunc(): string',
1986        '  return notDefined',
1987        'enddef',
1988        ]
1989  writefile(export_lines, 'Xexported.vim')
1990
1991  let import_lines = [
1992        'vim9script',
1993        'import ExpFunc from "./Xexported.vim"',
1994        'def ImpFunc()',
1995        '  echo ExpFunc()',
1996        'enddef',
1997        'defcompile',
1998        ]
1999  writefile(import_lines, 'Ximport.vim')
2000
2001  try
2002    source Ximport.vim
2003  catch /E1001/
2004    # Error should be fore the Xexported.vim file.
2005    assert_match('E1001: Variable not found: notDefined', v:exception)
2006    assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint)
2007  endtry
2008
2009  delete('Xexported.vim')
2010  delete('Ximport.vim')
2011enddef
2012
2013def Test_func_redefine_error()
2014  let lines = [
2015        'vim9script',
2016        'def Func()',
2017        '  eval [][0]',
2018        'enddef',
2019        'Func()',
2020        ]
2021  writefile(lines, 'Xtestscript.vim')
2022
2023  for count in range(3)
2024    try
2025      source Xtestscript.vim
2026    catch /E684/
2027      # function name should contain <SNR> every time
2028      assert_match('E684: list index out of range', v:exception)
2029      assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint)
2030    endtry
2031  endfor
2032
2033  delete('Xtestscript.vim')
2034enddef
2035
2036def Test_func_overrules_import_fails()
2037  let export_lines =<< trim END
2038      vim9script
2039      export def Func()
2040        echo 'imported'
2041      enddef
2042  END
2043  writefile(export_lines, 'XexportedFunc.vim')
2044
2045  let lines =<< trim END
2046    vim9script
2047    import Func from './XexportedFunc.vim'
2048    def Func()
2049      echo 'local to function'
2050    enddef
2051  END
2052  CheckScriptFailure(lines, 'E1073:')
2053
2054  lines =<< trim END
2055    vim9script
2056    import Func from './XexportedFunc.vim'
2057    def Outer()
2058      def Func()
2059        echo 'local to function'
2060      enddef
2061    enddef
2062    defcompile
2063  END
2064  CheckScriptFailure(lines, 'E1073:')
2065
2066  delete('XexportedFunc.vim')
2067enddef
2068
2069def Test_func_redefine_fails()
2070  let lines =<< trim END
2071    vim9script
2072    def Func()
2073      echo 'one'
2074    enddef
2075    def Func()
2076      echo 'two'
2077    enddef
2078  END
2079  CheckScriptFailure(lines, 'E1073:')
2080
2081  lines =<< trim END
2082    vim9script
2083    def Foo(): string
2084      return 'foo'
2085      enddef
2086    def Func()
2087      let  Foo = {-> 'lambda'}
2088    enddef
2089    defcompile
2090  END
2091  CheckScriptFailure(lines, 'E1073:')
2092enddef
2093
2094def Test_fixed_size_list()
2095  # will be allocated as one piece of memory, check that changes work
2096  let l = [1, 2, 3, 4]
2097  l->remove(0)
2098  l->add(5)
2099  l->insert(99, 1)
2100  assert_equal([2, 99, 3, 4, 5], l)
2101enddef
2102
2103def Test_no_insert_xit()
2104  CheckDefExecFailure(['a = 1'], 'E1100:')
2105  CheckDefExecFailure(['c = 1'], 'E1100:')
2106  CheckDefExecFailure(['i = 1'], 'E1100:')
2107  CheckDefExecFailure(['t = 1'], 'E1100:')
2108  CheckDefExecFailure(['x = 1'], 'E1100:')
2109
2110  CheckScriptFailure(['vim9script', 'a = 1'], 'E488:')
2111  CheckScriptFailure(['vim9script', 'a'], 'E1100:')
2112  CheckScriptFailure(['vim9script', 'c = 1'], 'E488:')
2113  CheckScriptFailure(['vim9script', 'c'], 'E1100:')
2114  CheckScriptFailure(['vim9script', 'i = 1'], 'E488:')
2115  CheckScriptFailure(['vim9script', 'i'], 'E1100:')
2116  CheckScriptFailure(['vim9script', 't'], 'E1100:')
2117  CheckScriptFailure(['vim9script', 't = 1'], 'E1100:')
2118  CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:')
2119enddef
2120
2121def IfElse(what: number): string
2122  let res = ''
2123  if what == 1
2124    res = "one"
2125  elseif what == 2
2126    res = "two"
2127  else
2128    res = "three"
2129  endif
2130  return res
2131enddef
2132
2133def Test_if_elseif_else()
2134  assert_equal('one', IfElse(1))
2135  assert_equal('two', IfElse(2))
2136  assert_equal('three', IfElse(3))
2137enddef
2138
2139def Test_if_elseif_else_fails()
2140  CheckDefFailure(['elseif true'], 'E582:')
2141  CheckDefFailure(['else'], 'E581:')
2142  CheckDefFailure(['endif'], 'E580:')
2143  CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
2144  CheckDefFailure(['if true', 'echo 1'], 'E171:')
2145enddef
2146
2147let g:bool_true = v:true
2148let g:bool_false = v:false
2149
2150def Test_if_const_expr()
2151  let res = false
2152  if true ? true : false
2153    res = true
2154  endif
2155  assert_equal(true, res)
2156
2157  g:glob = 2
2158  if false
2159    execute('g:glob = 3')
2160  endif
2161  assert_equal(2, g:glob)
2162  if true
2163    execute('g:glob = 3')
2164  endif
2165  assert_equal(3, g:glob)
2166
2167  res = false
2168  if g:bool_true ? true : false
2169    res = true
2170  endif
2171  assert_equal(true, res)
2172
2173  res = false
2174  if true ? g:bool_true : false
2175    res = true
2176  endif
2177  assert_equal(true, res)
2178
2179  res = false
2180  if true ? true : g:bool_false
2181    res = true
2182  endif
2183  assert_equal(true, res)
2184
2185  res = false
2186  if true ? false : true
2187    res = true
2188  endif
2189  assert_equal(false, res)
2190
2191  res = false
2192  if false ? false : true
2193    res = true
2194  endif
2195  assert_equal(true, res)
2196
2197  res = false
2198  if false ? true : false
2199    res = true
2200  endif
2201  assert_equal(false, res)
2202
2203  res = false
2204  if has('xyz') ? true : false
2205    res = true
2206  endif
2207  assert_equal(false, res)
2208
2209  res = false
2210  if true && true
2211    res = true
2212  endif
2213  assert_equal(true, res)
2214
2215  res = false
2216  if true && false
2217    res = true
2218  endif
2219  assert_equal(false, res)
2220
2221  res = false
2222  if g:bool_true && false
2223    res = true
2224  endif
2225  assert_equal(false, res)
2226
2227  res = false
2228  if true && g:bool_false
2229    res = true
2230  endif
2231  assert_equal(false, res)
2232
2233  res = false
2234  if false && false
2235    res = true
2236  endif
2237  assert_equal(false, res)
2238
2239  res = false
2240  if true || false
2241    res = true
2242  endif
2243  assert_equal(true, res)
2244
2245  res = false
2246  if g:bool_true || false
2247    res = true
2248  endif
2249  assert_equal(true, res)
2250
2251  res = false
2252  if true || g:bool_false
2253    res = true
2254  endif
2255  assert_equal(true, res)
2256
2257  res = false
2258  if false || false
2259    res = true
2260  endif
2261  assert_equal(false, res)
2262
2263  # with constant "false" expression may be invalid so long as the syntax is OK
2264  if false | eval 0 | endif
2265  if false | eval burp + 234 | endif
2266  if false | echo burp 234 'asd' | endif
2267  if false
2268    burp
2269  endif
2270enddef
2271
2272def Test_if_const_expr_fails()
2273  CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
2274  CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
2275  CheckDefFailure(["if has('aaa'"], 'E110:')
2276  CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
2277enddef
2278
2279def RunNested(i: number): number
2280  let x: number = 0
2281  if i % 2
2282    if 1
2283      # comment
2284    else
2285      # comment
2286    endif
2287    x += 1
2288  else
2289    x += 1000
2290  endif
2291  return x
2292enddef
2293
2294def Test_nested_if()
2295  assert_equal(1, RunNested(1))
2296  assert_equal(1000, RunNested(2))
2297enddef
2298
2299def Test_execute_cmd()
2300  new
2301  setline(1, 'default')
2302  execute 'setline(1, "execute-string")'
2303  assert_equal('execute-string', getline(1))
2304
2305  execute "setline(1, 'execute-string')"
2306  assert_equal('execute-string', getline(1))
2307
2308  let cmd1 = 'setline(1,'
2309  let cmd2 = '"execute-var")'
2310  execute cmd1 cmd2 # comment
2311  assert_equal('execute-var', getline(1))
2312
2313  execute cmd1 cmd2 '|setline(1, "execute-var-string")'
2314  assert_equal('execute-var-string', getline(1))
2315
2316  let cmd_first = 'call '
2317  let cmd_last = 'setline(1, "execute-var-var")'
2318  execute cmd_first .. cmd_last
2319  assert_equal('execute-var-var', getline(1))
2320  bwipe!
2321
2322  let n = true
2323  execute 'echomsg' (n ? '"true"' : '"no"')
2324  assert_match('^true$', Screenline(&lines))
2325
2326  echomsg [1, 2, 3] #{a: 1, b: 2}
2327  assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines))
2328
2329  CheckDefFailure(['execute xxx'], 'E1001:', 1)
2330  CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1)
2331  CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1)
2332enddef
2333
2334def Test_execute_cmd_vimscript()
2335  # only checks line continuation
2336  let lines =<< trim END
2337      vim9script
2338      execute 'g:someVar'
2339                .. ' = ' ..
2340                   '28'
2341      assert_equal(28, g:someVar)
2342      unlet g:someVar
2343  END
2344  CheckScriptSuccess(lines)
2345enddef
2346
2347def Test_echo_cmd()
2348  echo 'some' # comment
2349  echon 'thing'
2350  assert_match('^something$', Screenline(&lines))
2351
2352  echo "some" # comment
2353  echon "thing"
2354  assert_match('^something$', Screenline(&lines))
2355
2356  let str1 = 'some'
2357  let str2 = 'more'
2358  echo str1 str2
2359  assert_match('^some more$', Screenline(&lines))
2360
2361  CheckDefFailure(['echo "xxx"# comment'], 'E488:')
2362enddef
2363
2364def Test_echomsg_cmd()
2365  echomsg 'some' 'more' # comment
2366  assert_match('^some more$', Screenline(&lines))
2367  echo 'clear'
2368  :1messages
2369  assert_match('^some more$', Screenline(&lines))
2370
2371  CheckDefFailure(['echomsg "xxx"# comment'], 'E488:')
2372enddef
2373
2374def Test_echomsg_cmd_vimscript()
2375  # only checks line continuation
2376  let lines =<< trim END
2377      vim9script
2378      echomsg 'here'
2379                .. ' is ' ..
2380                   'a message'
2381      assert_match('^here is a message$', Screenline(&lines))
2382  END
2383  CheckScriptSuccess(lines)
2384enddef
2385
2386def Test_echoerr_cmd()
2387  try
2388    echoerr 'something' 'wrong' # comment
2389  catch
2390    assert_match('something wrong', v:exception)
2391  endtry
2392enddef
2393
2394def Test_echoerr_cmd_vimscript()
2395  # only checks line continuation
2396  let lines =<< trim END
2397      vim9script
2398      try
2399        echoerr 'this'
2400                .. ' is ' ..
2401                   'wrong'
2402      catch
2403        assert_match('this is wrong', v:exception)
2404      endtry
2405  END
2406  CheckScriptSuccess(lines)
2407enddef
2408
2409def Test_for_outside_of_function()
2410  let lines =<< trim END
2411    vim9script
2412    new
2413    for var in range(0, 3)
2414      append(line('$'), var)
2415    endfor
2416    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
2417    bwipe!
2418  END
2419  writefile(lines, 'Xvim9for.vim')
2420  source Xvim9for.vim
2421  delete('Xvim9for.vim')
2422enddef
2423
2424def Test_for_loop()
2425  let result = ''
2426  for cnt in range(7)
2427    if cnt == 4
2428      break
2429    endif
2430    if cnt == 2
2431      continue
2432    endif
2433    result ..= cnt .. '_'
2434  endfor
2435  assert_equal('0_1_3_', result)
2436
2437  let concat = ''
2438  for str in eval('["one", "two"]')
2439    concat ..= str
2440  endfor
2441  assert_equal('onetwo', concat)
2442enddef
2443
2444def Test_for_loop_fails()
2445  CheckDefFailure(['for # in range(5)'], 'E690:')
2446  CheckDefFailure(['for i In range(5)'], 'E690:')
2447  CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1017:')
2448  CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:')
2449  CheckDefFailure(['for i in "text"'], 'E1012:')
2450  CheckDefFailure(['for i in xxx'], 'E1001:')
2451  CheckDefFailure(['endfor'], 'E588:')
2452  CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
2453enddef
2454
2455def Test_while_loop()
2456  let result = ''
2457  let cnt = 0
2458  while cnt < 555
2459    if cnt == 3
2460      break
2461    endif
2462    cnt += 1
2463    if cnt == 2
2464      continue
2465    endif
2466    result ..= cnt .. '_'
2467  endwhile
2468  assert_equal('1_3_', result)
2469enddef
2470
2471def Test_while_loop_fails()
2472  CheckDefFailure(['while xxx'], 'E1001:')
2473  CheckDefFailure(['endwhile'], 'E588:')
2474  CheckDefFailure(['continue'], 'E586:')
2475  CheckDefFailure(['if true', 'continue'], 'E586:')
2476  CheckDefFailure(['break'], 'E587:')
2477  CheckDefFailure(['if true', 'break'], 'E587:')
2478  CheckDefFailure(['while 1', 'echo 3'], 'E170:')
2479enddef
2480
2481def Test_interrupt_loop()
2482  let caught = false
2483  let x = 0
2484  try
2485    while 1
2486      x += 1
2487      if x == 100
2488        feedkeys("\<C-C>", 'Lt')
2489      endif
2490    endwhile
2491  catch
2492    caught = true
2493    assert_equal(100, x)
2494  endtry
2495  assert_true(caught, 'should have caught an exception')
2496  # consume the CTRL-C
2497  getchar(0)
2498enddef
2499
2500def Test_automatic_line_continuation()
2501  let mylist = [
2502      'one',
2503      'two',
2504      'three',
2505      ] # comment
2506  assert_equal(['one', 'two', 'three'], mylist)
2507
2508  let mydict = {
2509      'one': 1,
2510      'two': 2,
2511      'three':
2512          3,
2513      } # comment
2514  assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
2515  mydict = #{
2516      one: 1,  # comment
2517      two:     # comment
2518           2,  # comment
2519      three: 3 # comment
2520      }
2521  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
2522  mydict = #{
2523      one: 1,
2524      two:
2525           2,
2526      three: 3
2527      }
2528  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
2529
2530  assert_equal(
2531        ['one', 'two', 'three'],
2532        split('one two three')
2533        )
2534enddef
2535
2536def Test_vim9_comment()
2537  CheckScriptSuccess([
2538      'vim9script',
2539      '# something',
2540      ])
2541  CheckScriptFailure([
2542      'vim9script',
2543      ':# something',
2544      ], 'E488:')
2545  CheckScriptFailure([
2546      '# something',
2547      ], 'E488:')
2548  CheckScriptFailure([
2549      ':# something',
2550      ], 'E488:')
2551
2552  { # block start
2553  } # block end
2554  CheckDefFailure([
2555      '{# comment',
2556      ], 'E488:')
2557  CheckDefFailure([
2558      '{',
2559      '}# comment',
2560      ], 'E488:')
2561
2562  echo "yes" # comment
2563  CheckDefFailure([
2564      'echo "yes"# comment',
2565      ], 'E488:')
2566  CheckScriptSuccess([
2567      'vim9script',
2568      'echo "yes" # something',
2569      ])
2570  CheckScriptFailure([
2571      'vim9script',
2572      'echo "yes"# something',
2573      ], 'E121:')
2574  CheckScriptFailure([
2575      'vim9script',
2576      'echo# something',
2577      ], 'E121:')
2578  CheckScriptFailure([
2579      'echo "yes" # something',
2580      ], 'E121:')
2581
2582  exe "echo" # comment
2583  CheckDefFailure([
2584      'exe "echo"# comment',
2585      ], 'E488:')
2586  CheckScriptSuccess([
2587      'vim9script',
2588      'exe "echo" # something',
2589      ])
2590  CheckScriptFailure([
2591      'vim9script',
2592      'exe "echo"# something',
2593      ], 'E121:')
2594  CheckDefFailure([
2595      'exe # comment',
2596      ], 'E1015:')
2597  CheckScriptFailure([
2598      'vim9script',
2599      'exe# something',
2600      ], 'E121:')
2601  CheckScriptFailure([
2602      'exe "echo" # something',
2603      ], 'E121:')
2604
2605  CheckDefFailure([
2606      'try# comment',
2607      '  echo "yes"',
2608      'catch',
2609      'endtry',
2610      ], 'E488:')
2611  CheckScriptFailure([
2612      'vim9script',
2613      'try# comment',
2614      'echo "yes"',
2615      ], 'E488:')
2616  CheckDefFailure([
2617      'try',
2618      '  throw#comment',
2619      'catch',
2620      'endtry',
2621      ], 'E1015:')
2622  CheckDefFailure([
2623      'try',
2624      '  throw "yes"#comment',
2625      'catch',
2626      'endtry',
2627      ], 'E488:')
2628  CheckDefFailure([
2629      'try',
2630      '  echo "yes"',
2631      'catch# comment',
2632      'endtry',
2633      ], 'E488:')
2634  CheckScriptFailure([
2635      'vim9script',
2636      'try',
2637      '  echo "yes"',
2638      'catch# comment',
2639      'endtry',
2640      ], 'E654:')
2641  CheckDefFailure([
2642      'try',
2643      '  echo "yes"',
2644      'catch /pat/# comment',
2645      'endtry',
2646      ], 'E488:')
2647  CheckDefFailure([
2648      'try',
2649      'echo "yes"',
2650      'catch',
2651      'endtry# comment',
2652      ], 'E488:')
2653  CheckScriptFailure([
2654      'vim9script',
2655      'try',
2656      '  echo "yes"',
2657      'catch',
2658      'endtry# comment',
2659      ], 'E488:')
2660
2661  CheckScriptSuccess([
2662      'vim9script',
2663      'hi # comment',
2664      ])
2665  CheckScriptFailure([
2666      'vim9script',
2667      'hi# comment',
2668      ], 'E416:')
2669  CheckScriptSuccess([
2670      'vim9script',
2671      'hi Search # comment',
2672      ])
2673  CheckScriptFailure([
2674      'vim9script',
2675      'hi Search# comment',
2676      ], 'E416:')
2677  CheckScriptSuccess([
2678      'vim9script',
2679      'hi link This Search # comment',
2680      ])
2681  CheckScriptFailure([
2682      'vim9script',
2683      'hi link This That# comment',
2684      ], 'E413:')
2685  CheckScriptSuccess([
2686      'vim9script',
2687      'hi clear This # comment',
2688      'hi clear # comment',
2689      ])
2690  # not tested, because it doesn't give an error but a warning:
2691  # hi clear This# comment',
2692  CheckScriptFailure([
2693      'vim9script',
2694      'hi clear# comment',
2695      ], 'E416:')
2696
2697  CheckScriptSuccess([
2698      'vim9script',
2699      'hi Group term=bold',
2700      'match Group /todo/ # comment',
2701      ])
2702  CheckScriptFailure([
2703      'vim9script',
2704      'hi Group term=bold',
2705      'match Group /todo/# comment',
2706      ], 'E488:')
2707  CheckScriptSuccess([
2708      'vim9script',
2709      'match # comment',
2710      ])
2711  CheckScriptFailure([
2712      'vim9script',
2713      'match# comment',
2714      ], 'E475:')
2715  CheckScriptSuccess([
2716      'vim9script',
2717      'match none # comment',
2718      ])
2719  CheckScriptFailure([
2720      'vim9script',
2721      'match none# comment',
2722      ], 'E475:')
2723
2724  CheckScriptSuccess([
2725      'vim9script',
2726      'menutrans clear # comment',
2727      ])
2728  CheckScriptFailure([
2729      'vim9script',
2730      'menutrans clear# comment text',
2731      ], 'E474:')
2732
2733  CheckScriptSuccess([
2734      'vim9script',
2735      'syntax clear # comment',
2736      ])
2737  CheckScriptFailure([
2738      'vim9script',
2739      'syntax clear# comment text',
2740      ], 'E28:')
2741  CheckScriptSuccess([
2742      'vim9script',
2743      'syntax keyword Word some',
2744      'syntax clear Word # comment',
2745      ])
2746  CheckScriptFailure([
2747      'vim9script',
2748      'syntax keyword Word some',
2749      'syntax clear Word# comment text',
2750      ], 'E28:')
2751
2752  CheckScriptSuccess([
2753      'vim9script',
2754      'syntax list # comment',
2755      ])
2756  CheckScriptFailure([
2757      'vim9script',
2758      'syntax list# comment text',
2759      ], 'E28:')
2760
2761  CheckScriptSuccess([
2762      'vim9script',
2763      'syntax match Word /pat/ oneline # comment',
2764      ])
2765  CheckScriptFailure([
2766      'vim9script',
2767      'syntax match Word /pat/ oneline# comment',
2768      ], 'E475:')
2769
2770  CheckScriptSuccess([
2771      'vim9script',
2772      'syntax keyword Word word # comm[ent',
2773      ])
2774  CheckScriptFailure([
2775      'vim9script',
2776      'syntax keyword Word word# comm[ent',
2777      ], 'E789:')
2778
2779  CheckScriptSuccess([
2780      'vim9script',
2781      'syntax match Word /pat/ # comment',
2782      ])
2783  CheckScriptFailure([
2784      'vim9script',
2785      'syntax match Word /pat/# comment',
2786      ], 'E402:')
2787
2788  CheckScriptSuccess([
2789      'vim9script',
2790      'syntax match Word /pat/ contains=Something # comment',
2791      ])
2792  CheckScriptFailure([
2793      'vim9script',
2794      'syntax match Word /pat/ contains=Something# comment',
2795      ], 'E475:')
2796  CheckScriptFailure([
2797      'vim9script',
2798      'syntax match Word /pat/ contains= # comment',
2799      ], 'E406:')
2800  CheckScriptFailure([
2801      'vim9script',
2802      'syntax match Word /pat/ contains=# comment',
2803      ], 'E475:')
2804
2805  CheckScriptSuccess([
2806      'vim9script',
2807      'syntax region Word start=/pat/ end=/pat/ # comment',
2808      ])
2809  CheckScriptFailure([
2810      'vim9script',
2811      'syntax region Word start=/pat/ end=/pat/# comment',
2812      ], 'E402:')
2813
2814  CheckScriptSuccess([
2815      'vim9script',
2816      'syntax sync # comment',
2817      ])
2818  CheckScriptFailure([
2819      'vim9script',
2820      'syntax sync# comment',
2821      ], 'E404:')
2822  CheckScriptSuccess([
2823      'vim9script',
2824      'syntax sync ccomment # comment',
2825      ])
2826  CheckScriptFailure([
2827      'vim9script',
2828      'syntax sync ccomment# comment',
2829      ], 'E404:')
2830
2831  CheckScriptSuccess([
2832      'vim9script',
2833      'syntax cluster Some contains=Word # comment',
2834      ])
2835  CheckScriptFailure([
2836      'vim9script',
2837      'syntax cluster Some contains=Word# comment',
2838      ], 'E475:')
2839
2840  CheckScriptSuccess([
2841      'vim9script',
2842      'command Echo echo # comment',
2843      'command Echo # comment',
2844      ])
2845  CheckScriptFailure([
2846      'vim9script',
2847      'command Echo echo# comment',
2848      'Echo',
2849      ], 'E121:')
2850  CheckScriptFailure([
2851      'vim9script',
2852      'command Echo# comment',
2853      ], 'E182:')
2854  CheckScriptFailure([
2855      'vim9script',
2856      'command Echo echo',
2857      'command Echo# comment',
2858      ], 'E182:')
2859
2860  CheckScriptSuccess([
2861      'vim9script',
2862      'function # comment',
2863      ])
2864  CheckScriptFailure([
2865      'vim9script',
2866      'function " comment',
2867      ], 'E129:')
2868  CheckScriptFailure([
2869      'vim9script',
2870      'function# comment',
2871      ], 'E129:')
2872  CheckScriptSuccess([
2873      'vim9script',
2874      'function CheckScriptSuccess # comment',
2875      ])
2876  CheckScriptFailure([
2877      'vim9script',
2878      'function CheckScriptSuccess# comment',
2879      ], 'E488:')
2880
2881  CheckScriptSuccess([
2882      'vim9script',
2883      'func g:DeleteMeA()',
2884      'endfunc',
2885      'delfunction g:DeleteMeA # comment',
2886      ])
2887  CheckScriptFailure([
2888      'vim9script',
2889      'func g:DeleteMeB()',
2890      'endfunc',
2891      'delfunction g:DeleteMeB# comment',
2892      ], 'E488:')
2893
2894  CheckScriptSuccess([
2895      'vim9script',
2896      'call execute("ls") # comment',
2897      ])
2898  CheckScriptFailure([
2899      'vim9script',
2900      'call execute("ls")# comment',
2901      ], 'E488:')
2902
2903  CheckScriptFailure([
2904      'def Test() " comment',
2905      'enddef',
2906      ], 'E488:')
2907  CheckScriptFailure([
2908      'vim9script',
2909      'def Test() " comment',
2910      'enddef',
2911      ], 'E488:')
2912
2913  CheckScriptSuccess([
2914      'func Test() " comment',
2915      'endfunc',
2916      ])
2917  CheckScriptSuccess([
2918      'vim9script',
2919      'func Test() " comment',
2920      'endfunc',
2921      ])
2922
2923  CheckScriptSuccess([
2924      'def Test() # comment',
2925      'enddef',
2926      ])
2927  CheckScriptFailure([
2928      'func Test() # comment',
2929      'endfunc',
2930      ], 'E488:')
2931enddef
2932
2933def Test_vim9_comment_gui()
2934  CheckCanRunGui
2935
2936  CheckScriptFailure([
2937      'vim9script',
2938      'gui#comment'
2939      ], 'E499:')
2940  CheckScriptFailure([
2941      'vim9script',
2942      'gui -f#comment'
2943      ], 'E499:')
2944enddef
2945
2946def Test_vim9_comment_not_compiled()
2947  au TabEnter *.vim g:entered = 1
2948  au TabEnter *.x g:entered = 2
2949
2950  edit test.vim
2951  doautocmd TabEnter #comment
2952  assert_equal(1, g:entered)
2953
2954  doautocmd TabEnter f.x
2955  assert_equal(2, g:entered)
2956
2957  g:entered = 0
2958  doautocmd TabEnter f.x #comment
2959  assert_equal(2, g:entered)
2960
2961  assert_fails('doautocmd Syntax#comment', 'E216:')
2962
2963  au! TabEnter
2964  unlet g:entered
2965
2966  CheckScriptSuccess([
2967      'vim9script',
2968      'g:var = 123',
2969      'b:var = 456',
2970      'w:var = 777',
2971      't:var = 888',
2972      'unlet g:var w:var # something',
2973      ])
2974
2975  CheckScriptFailure([
2976      'vim9script',
2977      'let g:var = 123',
2978      ], 'E1016: Cannot declare a global variable:')
2979
2980  CheckScriptFailure([
2981      'vim9script',
2982      'let b:var = 123',
2983      ], 'E1016: Cannot declare a buffer variable:')
2984
2985  CheckScriptFailure([
2986      'vim9script',
2987      'let w:var = 123',
2988      ], 'E1016: Cannot declare a window variable:')
2989
2990  CheckScriptFailure([
2991      'vim9script',
2992      'let t:var = 123',
2993      ], 'E1016: Cannot declare a tab variable:')
2994
2995  CheckScriptFailure([
2996      'vim9script',
2997      'let v:version = 123',
2998      ], 'E1016: Cannot declare a v: variable:')
2999
3000  CheckScriptFailure([
3001      'vim9script',
3002      'let $VARIABLE = "text"',
3003      ], 'E1016: Cannot declare an environment variable:')
3004
3005  CheckScriptFailure([
3006      'vim9script',
3007      'g:var = 123',
3008      'unlet g:var# comment1',
3009      ], 'E108:')
3010
3011  CheckScriptFailure([
3012      'let g:var = 123',
3013      'unlet g:var # something',
3014      ], 'E488:')
3015
3016  CheckScriptSuccess([
3017      'vim9script',
3018      'if 1 # comment2',
3019      '  echo "yes"',
3020      'elseif 2 #comment',
3021      '  echo "no"',
3022      'endif',
3023      ])
3024
3025  CheckScriptFailure([
3026      'vim9script',
3027      'if 1# comment3',
3028      '  echo "yes"',
3029      'endif',
3030      ], 'E15:')
3031
3032  CheckScriptFailure([
3033      'vim9script',
3034      'if 0 # comment4',
3035      '  echo "yes"',
3036      'elseif 2#comment',
3037      '  echo "no"',
3038      'endif',
3039      ], 'E15:')
3040
3041  CheckScriptSuccess([
3042      'vim9script',
3043      'let v = 1 # comment5',
3044      ])
3045
3046  CheckScriptFailure([
3047      'vim9script',
3048      'let v = 1# comment6',
3049      ], 'E15:')
3050
3051  CheckScriptSuccess([
3052      'vim9script',
3053      'new'
3054      'setline(1, ["# define pat", "last"])',
3055      ':$',
3056      'dsearch /pat/ #comment',
3057      'bwipe!',
3058      ])
3059
3060  CheckScriptFailure([
3061      'vim9script',
3062      'new'
3063      'setline(1, ["# define pat", "last"])',
3064      ':$',
3065      'dsearch /pat/#comment',
3066      'bwipe!',
3067      ], 'E488:')
3068
3069  CheckScriptFailure([
3070      'vim9script',
3071      'func! SomeFunc()',
3072      ], 'E477:')
3073enddef
3074
3075def Test_finish()
3076  let lines =<< trim END
3077    vim9script
3078    g:res = 'one'
3079    if v:false | finish | endif
3080    g:res = 'two'
3081    finish
3082    g:res = 'three'
3083  END
3084  writefile(lines, 'Xfinished')
3085  source Xfinished
3086  assert_equal('two', g:res)
3087
3088  unlet g:res
3089  delete('Xfinished')
3090enddef
3091
3092def Test_let_func_call()
3093  let lines =<< trim END
3094    vim9script
3095    func GetValue()
3096      if exists('g:count')
3097        let g:count += 1
3098      else
3099        let g:count = 1
3100      endif
3101      return 'this'
3102    endfunc
3103    let val: string = GetValue()
3104    # env var is always a string
3105    let env = $TERM
3106  END
3107  writefile(lines, 'Xfinished')
3108  source Xfinished
3109  # GetValue() is not called during discovery phase
3110  assert_equal(1, g:count)
3111
3112  unlet g:count
3113  delete('Xfinished')
3114enddef
3115
3116def Test_let_missing_type()
3117  let lines =<< trim END
3118    vim9script
3119    let var = g:unknown
3120  END
3121  CheckScriptFailure(lines, 'E121:')
3122
3123  lines =<< trim END
3124    vim9script
3125    let nr: number = 123
3126    let var = nr
3127  END
3128  CheckScriptSuccess(lines)
3129enddef
3130
3131def Test_let_declaration()
3132  let lines =<< trim END
3133    vim9script
3134    let var: string
3135    g:var_uninit = var
3136    var = 'text'
3137    g:var_test = var
3138    # prefixing s: is optional
3139    s:var = 'prefixed'
3140    g:var_prefixed = s:var
3141
3142    let s:other: number
3143    other = 1234
3144    g:other_var = other
3145
3146    # type is inferred
3147    s:dict = {'a': 222}
3148    def GetDictVal(key: any)
3149      g:dict_val = s:dict[key]
3150    enddef
3151    GetDictVal('a')
3152  END
3153  CheckScriptSuccess(lines)
3154  assert_equal('', g:var_uninit)
3155  assert_equal('text', g:var_test)
3156  assert_equal('prefixed', g:var_prefixed)
3157  assert_equal(1234, g:other_var)
3158  assert_equal(222, g:dict_val)
3159
3160  unlet g:var_uninit
3161  unlet g:var_test
3162  unlet g:var_prefixed
3163  unlet g:other_var
3164enddef
3165
3166def Test_let_declaration_fails()
3167  let lines =<< trim END
3168    vim9script
3169    const var: string
3170  END
3171  CheckScriptFailure(lines, 'E1021:')
3172
3173  lines =<< trim END
3174    vim9script
3175    let 9var: string
3176  END
3177  CheckScriptFailure(lines, 'E475:')
3178enddef
3179
3180def Test_let_type_check()
3181  let lines =<< trim END
3182    vim9script
3183    let var: string
3184    var = 1234
3185  END
3186  CheckScriptFailure(lines, 'E1012:')
3187
3188  lines =<< trim END
3189    vim9script
3190    let var:string
3191  END
3192  CheckScriptFailure(lines, 'E1069:')
3193
3194  lines =<< trim END
3195    vim9script
3196    let var: asdf
3197  END
3198  CheckScriptFailure(lines, 'E1010:')
3199
3200  lines =<< trim END
3201    vim9script
3202    let s:l: list<number>
3203    s:l = []
3204  END
3205  CheckScriptSuccess(lines)
3206
3207  lines =<< trim END
3208    vim9script
3209    let s:d: dict<number>
3210    s:d = {}
3211  END
3212  CheckScriptSuccess(lines)
3213enddef
3214
3215let g:dict_number = #{one: 1, two: 2}
3216
3217def Test_let_list_dict_type()
3218  let ll: list<number>
3219  ll = [1, 2, 2, 3, 3, 3]->uniq()
3220  ll->assert_equal([1, 2, 3])
3221
3222  let dd: dict<number>
3223  dd = g:dict_number
3224  dd->assert_equal(g:dict_number)
3225
3226  let lines =<< trim END
3227      let ll: list<number>
3228      ll = [1, 2, 3]->map('"one"')
3229  END
3230  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
3231enddef
3232
3233def Test_forward_declaration()
3234  let lines =<< trim END
3235    vim9script
3236    def GetValue(): string
3237      return theVal
3238    enddef
3239    let theVal = 'something'
3240    g:initVal = GetValue()
3241    theVal = 'else'
3242    g:laterVal = GetValue()
3243  END
3244  writefile(lines, 'Xforward')
3245  source Xforward
3246  assert_equal('something', g:initVal)
3247  assert_equal('else', g:laterVal)
3248
3249  unlet g:initVal
3250  unlet g:laterVal
3251  delete('Xforward')
3252enddef
3253
3254def Test_source_vim9_from_legacy()
3255  let legacy_lines =<< trim END
3256    source Xvim9_script.vim
3257
3258    call assert_false(exists('local'))
3259    call assert_false(exists('exported'))
3260    call assert_false(exists('s:exported'))
3261    call assert_equal('global', global)
3262    call assert_equal('global', g:global)
3263
3264    " imported variable becomes script-local
3265    import exported from './Xvim9_script.vim'
3266    call assert_equal('exported', s:exported)
3267    call assert_false(exists('exported'))
3268
3269    " imported function becomes script-local
3270    import GetText from './Xvim9_script.vim'
3271    call assert_equal('text', s:GetText())
3272    call assert_false(exists('*GetText'))
3273  END
3274  writefile(legacy_lines, 'Xlegacy_script.vim')
3275
3276  let vim9_lines =<< trim END
3277    vim9script
3278    let local = 'local'
3279    g:global = 'global'
3280    export let exported = 'exported'
3281    export def GetText(): string
3282       return 'text'
3283    enddef
3284  END
3285  writefile(vim9_lines, 'Xvim9_script.vim')
3286
3287  source Xlegacy_script.vim
3288
3289  assert_equal('global', g:global)
3290  unlet g:global
3291
3292  delete('Xlegacy_script.vim')
3293  delete('Xvim9_script.vim')
3294enddef
3295
3296func Test_vim9script_not_global()
3297  " check that items defined in Vim9 script are script-local, not global
3298  let vim9lines =<< trim END
3299    vim9script
3300    let var = 'local'
3301    func TheFunc()
3302      echo 'local'
3303    endfunc
3304    def DefFunc()
3305      echo 'local'
3306    enddef
3307  END
3308  call writefile(vim9lines, 'Xvim9script.vim')
3309  source Xvim9script.vim
3310  try
3311    echo g:var
3312    assert_report('did not fail')
3313  catch /E121:/
3314    " caught
3315  endtry
3316  try
3317    call TheFunc()
3318    assert_report('did not fail')
3319  catch /E117:/
3320    " caught
3321  endtry
3322  try
3323    call DefFunc()
3324    assert_report('did not fail')
3325  catch /E117:/
3326    " caught
3327  endtry
3328
3329  call delete('Xvim9script.vim')
3330endfunc
3331
3332def Test_vim9_copen()
3333  # this was giving an error for setting w:quickfix_title
3334  copen
3335  quit
3336enddef
3337
3338" test using a vim9script that is auto-loaded from an autocmd
3339def Test_vim9_autoload()
3340  let lines =<< trim END
3341     vim9script
3342     def foo#test()
3343         echomsg getreg('"')
3344     enddef
3345  END
3346
3347  mkdir('Xdir/autoload', 'p')
3348  writefile(lines, 'Xdir/autoload/foo.vim')
3349  let save_rtp = &rtp
3350  exe 'set rtp^=' .. getcwd() .. '/Xdir'
3351  augroup test
3352    autocmd TextYankPost * call foo#test()
3353  augroup END
3354
3355  normal Y
3356
3357  augroup test
3358    autocmd!
3359  augroup END
3360  delete('Xdir', 'rf')
3361  &rtp = save_rtp
3362enddef
3363
3364" This was causing a crash because suppress_errthrow wasn't reset.
3365def Test_vim9_autoload_error()
3366  let lines =<< trim END
3367      vim9script
3368      def crash#func()
3369          try
3370              for x in List()
3371              endfor
3372          catch
3373          endtry
3374          g:ok = true
3375      enddef
3376      fu List()
3377          invalid
3378      endfu
3379      try
3380          invalid
3381      catch /wontmatch/
3382      endtry
3383  END
3384  call mkdir('Xruntime/autoload', 'p')
3385  call writefile(lines, 'Xruntime/autoload/crash.vim')
3386
3387  # run in a separate Vim to avoid the side effects of assert_fails()
3388  lines =<< trim END
3389    exe 'set rtp^=' .. getcwd() .. '/Xruntime'
3390    call crash#func()
3391    call writefile(['ok'], 'Xdidit')
3392    qall
3393  END
3394  writefile(lines, 'Xscript')
3395  RunVim([], [], '-S Xscript')
3396  assert_equal(['ok'], readfile('Xdidit'))
3397
3398  delete('Xdidit')
3399  delete('Xscript')
3400  delete('Xruntime', 'rf')
3401enddef
3402
3403def Test_script_var_in_autocmd()
3404  # using a script variable from an autocommand, defined in a :def function in a
3405  # legacy Vim script, cannot check the variable type.
3406  let lines =<< trim END
3407    let s:counter = 1
3408    def s:Func()
3409      au! CursorHold
3410      au CursorHold * s:counter += 1
3411    enddef
3412    call s:Func()
3413    doau CursorHold
3414    call assert_equal(2, s:counter)
3415    au! CursorHold
3416  END
3417  CheckScriptSuccess(lines)
3418enddef
3419
3420def Test_cmdline_win()
3421  # if the Vim syntax highlighting uses Vim9 constructs they can be used from
3422  # the command line window.
3423  mkdir('rtp/syntax', 'p')
3424  let export_lines =<< trim END
3425    vim9script
3426    export let That = 'yes'
3427  END
3428  writefile(export_lines, 'rtp/syntax/Xexport.vim')
3429  let import_lines =<< trim END
3430    vim9script
3431    import That from './Xexport.vim'
3432  END
3433  writefile(import_lines, 'rtp/syntax/vim.vim')
3434  let save_rtp = &rtp
3435  &rtp = getcwd() .. '/rtp' .. ',' .. &rtp
3436  syntax on
3437  augroup CmdWin
3438    autocmd CmdwinEnter * g:got_there = 'yes'
3439  augroup END
3440  # this will open and also close the cmdline window
3441  feedkeys('q:', 'xt')
3442  assert_equal('yes', g:got_there)
3443
3444  augroup CmdWin
3445    au!
3446  augroup END
3447  &rtp = save_rtp
3448  delete('rtp', 'rf')
3449enddef
3450
3451def Test_invalid_sid()
3452  assert_fails('func <SNR>1234_func', 'E123:')
3453
3454  if RunVim([], ['wq Xdidit'], '+"func <SNR>1_func"')
3455    assert_equal([], readfile('Xdidit'))
3456  endif
3457  delete('Xdidit')
3458enddef
3459
3460def Test_unset_any_variable()
3461  let lines =<< trim END
3462    let var: any
3463    assert_equal(0, var)
3464  END
3465  CheckDefAndScriptSuccess(lines)
3466enddef
3467
3468" Keep this last, it messes up highlighting.
3469def Test_substitute_cmd()
3470  new
3471  setline(1, 'something')
3472  :substitute(some(other(
3473  assert_equal('otherthing', getline(1))
3474  bwipe!
3475
3476  # also when the context is Vim9 script
3477  let lines =<< trim END
3478    vim9script
3479    new
3480    setline(1, 'something')
3481    :substitute(some(other(
3482    assert_equal('otherthing', getline(1))
3483    bwipe!
3484  END
3485  writefile(lines, 'Xvim9lines')
3486  source Xvim9lines
3487
3488  delete('Xvim9lines')
3489enddef
3490
3491" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
3492