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