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