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