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