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