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