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