1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source term_util.vim
5source view_util.vim
6source vim9.vim
7
8def Test_syntax()
9  let var = 234
10  let other: list<string> = ['asdf']
11enddef
12
13let s:appendToMe = 'xxx'
14let s:addToMe = 111
15let g:existing = 'yes'
16let g:inc_counter = 1
17let $SOME_ENV_VAR = 'some'
18let g:alist = [7]
19let g:astring = 'text'
20let g:anumber = 123
21
22def Test_assignment()
23  let bool1: bool = true
24  assert_equal(v:true, bool1)
25  let bool2: bool = false
26  assert_equal(v:false, bool2)
27
28  call CheckDefFailure(['let x:string'], 'E1069:')
29  call CheckDefFailure(['let x:string = "x"'], 'E1069:')
30  call CheckDefFailure(['let a:string = "x"'], 'E1069:')
31  call CheckDefFailure(['let lambda = {-> "lambda"}'], 'E704:')
32
33  let nr: number = 1234
34  call CheckDefFailure(['let nr: number = "asdf"'], 'E1013:')
35
36  let a: number = 6 #comment
37  assert_equal(6, a)
38
39  if has('channel')
40    let chan1: channel
41    let job1: job
42    let job2: job = job_start('willfail')
43  endif
44  if has('float')
45    let float1: float = 3.4
46  endif
47  let Funky1: func
48  let Funky2: func = function('len')
49  let Party2: func = funcref('g:Test_syntax')
50
51  g:newvar = 'new'  #comment
52  assert_equal('new', g:newvar)
53
54  assert_equal('yes', g:existing)
55  g:existing = 'no'
56  assert_equal('no', g:existing)
57
58  v:char = 'abc'
59  assert_equal('abc', v:char)
60
61  $ENVVAR = 'foobar'
62  assert_equal('foobar', $ENVVAR)
63  $ENVVAR = ''
64
65  let lines =<< trim END
66    vim9script
67    $ENVVAR = 'barfoo'
68    assert_equal('barfoo', $ENVVAR)
69    $ENVVAR = ''
70  END
71  call CheckScriptSuccess(lines)
72
73  s:appendToMe ..= 'yyy'
74  assert_equal('xxxyyy', s:appendToMe)
75  s:addToMe += 222
76  assert_equal(333, s:addToMe)
77  s:newVar = 'new'
78  assert_equal('new', s:newVar)
79
80  set ts=7
81  &ts += 1
82  assert_equal(8, &ts)
83  &ts -= 3
84  assert_equal(5, &ts)
85  &ts *= 2
86  assert_equal(10, &ts)
87  &ts /= 3
88  assert_equal(3, &ts)
89  set ts=10
90  &ts %= 4
91  assert_equal(2, &ts)
92
93  lines =<< trim END
94    vim9script
95    &ts = 6
96    &ts += 3
97    assert_equal(9, &ts)
98  END
99  call CheckScriptSuccess(lines)
100
101  call CheckDefFailure(['&notex += 3'], 'E113:')
102  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
103  call CheckDefFailure(['&ts = [7]'], 'E1013:')
104  call CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got list')
105  call CheckDefFailure(['&ts = "xx"'], 'E1013:')
106  call CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got string')
107  call CheckDefFailure(['&path += 3'], 'E1013:')
108  call CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
109  # test freeing ISN_STOREOPT
110  call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
111  &ts = 8
112
113  call CheckDefFailure(['let s:var = 123'], 'E1101:')
114  call CheckDefFailure(['let s:var: number'], 'E1101:')
115
116  lines =<< trim END
117    vim9script
118    def SomeFunc()
119      s:var = 123
120    enddef
121    defcompile
122  END
123  call CheckScriptFailure(lines, 'E1089:')
124
125  g:inc_counter += 1
126  assert_equal(2, g:inc_counter)
127
128  $SOME_ENV_VAR ..= 'more'
129  assert_equal('somemore', $SOME_ENV_VAR)
130  call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
131  call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:')
132
133  @a = 'areg'
134  @a ..= 'add'
135  assert_equal('aregadd', @a)
136  call CheckDefFailure(['@a += "more"'], 'E1051:')
137  call CheckDefFailure(['@a += 123'], 'E1013:')
138
139  lines =<< trim END
140    vim9script
141    @c = 'areg'
142    @c ..= 'add'
143    assert_equal('aregadd', @c)
144  END
145  call CheckScriptSuccess(lines)
146
147  v:errmsg = 'none'
148  v:errmsg ..= 'again'
149  assert_equal('noneagain', v:errmsg)
150  call CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
151  call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
152
153  # single letter variables
154  a = 123
155  assert_equal(123, a)
156  let b: number
157  b = 123
158  assert_equal(123, b)
159  let g: number
160  g = 123
161  assert_equal(123, g)
162  let s: number
163  s = 123
164  assert_equal(123, s)
165  let t: number
166  t = 123
167  assert_equal(123, t)
168  let v: number
169  v = 123
170  assert_equal(123, v)
171  let w: number
172  w = 123
173  assert_equal(123, w)
174enddef
175
176def Test_vim9_single_char_vars()
177  let lines =<< trim END
178      vim9script
179
180      # single character variable declarations work
181      let a: string
182      let b: number
183      let l: list<any>
184      let s: string
185      let t: number
186      let v: number
187      let w: number
188
189      # script-local variables can be used without s: prefix
190      a = 'script-a'
191      b = 111
192      l = [1, 2, 3]
193      s = 'script-s'
194      t = 222
195      v = 333
196      w = 444
197
198      assert_equal('script-a', a)
199      assert_equal(111, b)
200      assert_equal([1, 2, 3], l)
201      assert_equal('script-s', s)
202      assert_equal(222, t)
203      assert_equal(333, v)
204      assert_equal(444, w)
205  END
206  writefile(lines, 'Xsinglechar')
207  source Xsinglechar
208  delete('Xsinglechar')
209enddef
210
211def Test_assignment_list()
212  let list1: list<bool> = [false, true, false]
213  let list2: list<number> = [1, 2, 3]
214  let list3: list<string> = ['sdf', 'asdf']
215  let list4: list<any> = ['yes', true, 1234]
216  let list5: list<blob> = [0z01, 0z02]
217
218  let listS: list<string> = []
219  let listN: list<number> = []
220
221  assert_equal([1, 2, 3], list2)
222  list2[-1] = 99
223  assert_equal([1, 2, 99], list2)
224  list2[-2] = 88
225  assert_equal([1, 88, 99], list2)
226  list2[-3] = 77
227  assert_equal([77, 88, 99], list2)
228  list2 += [100]
229  assert_equal([77, 88, 99, 100], list2)
230
231  list3 += ['end']
232  assert_equal(['sdf', 'asdf', 'end'], list3)
233
234
235  call CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
236  call CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:')
237
238  # type becomes list<any>
239  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
240enddef
241
242def Test_assignment_list_vim9script()
243  let lines =<< trim END
244    vim9script
245    let v1: number
246    let v2: number
247    let v3: number
248    [v1, v2, v3] = [1, 2, 3]
249    assert_equal([1, 2, 3], [v1, v2, v3])
250  END
251  call CheckScriptSuccess(lines)
252enddef
253
254def Test_assignment_dict()
255  let dict1: dict<bool> = #{one: false, two: true}
256  let dict2: dict<number> = #{one: 1, two: 2}
257  let dict3: dict<string> = #{key: 'value'}
258  let dict4: dict<any> = #{one: 1, two: '2'}
259  let dict5: dict<blob> = #{one: 0z01, two: 0z02}
260
261  # overwrite
262  dict3['key'] = 'another'
263
264  # empty key can be used
265  let dd = {}
266  dd[""] = 6
267  assert_equal({'': 6}, dd)
268
269  # type becomes dict<any>
270  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
271
272  # assignment to script-local dict
273  let lines =<< trim END
274    vim9script
275    let test: dict<any> = {}
276    def FillDict(): dict<any>
277      test['a'] = 43
278      return test
279    enddef
280    assert_equal(#{a: 43}, FillDict())
281  END
282  call CheckScriptSuccess(lines)
283
284  lines =<< trim END
285    vim9script
286    let test: dict<any>
287    def FillDict(): dict<any>
288      test['a'] = 43
289      return test
290    enddef
291    FillDict()
292  END
293  call CheckScriptFailure(lines, 'E1103:')
294
295  # assignment to global dict
296  lines =<< trim END
297    vim9script
298    g:test = {}
299    def FillDict(): dict<any>
300      g:test['a'] = 43
301      return g:test
302    enddef
303    assert_equal(#{a: 43}, FillDict())
304  END
305  call CheckScriptSuccess(lines)
306
307  # assignment to buffer dict
308  lines =<< trim END
309    vim9script
310    b:test = {}
311    def FillDict(): dict<any>
312      b:test['a'] = 43
313      return b:test
314    enddef
315    assert_equal(#{a: 43}, FillDict())
316  END
317  call CheckScriptSuccess(lines)
318enddef
319
320def Test_assignment_local()
321  # Test in a separated file in order not to the current buffer/window/tab is
322  # changed.
323  let script_lines: list<string> =<< trim END
324    let b:existing = 'yes'
325    let w:existing = 'yes'
326    let t:existing = 'yes'
327
328    def Test_assignment_local_internal()
329      b:newvar = 'new'
330      assert_equal('new', b:newvar)
331      assert_equal('yes', b:existing)
332      b:existing = 'no'
333      assert_equal('no', b:existing)
334      b:existing ..= 'NO'
335      assert_equal('noNO', b:existing)
336
337      w:newvar = 'new'
338      assert_equal('new', w:newvar)
339      assert_equal('yes', w:existing)
340      w:existing = 'no'
341      assert_equal('no', w:existing)
342      w:existing ..= 'NO'
343      assert_equal('noNO', w:existing)
344
345      t:newvar = 'new'
346      assert_equal('new', t:newvar)
347      assert_equal('yes', t:existing)
348      t:existing = 'no'
349      assert_equal('no', t:existing)
350      t:existing ..= 'NO'
351      assert_equal('noNO', t:existing)
352    enddef
353    call Test_assignment_local_internal()
354  END
355  call CheckScriptSuccess(script_lines)
356enddef
357
358def Test_assignment_default()
359
360  # Test default values.
361  let thebool: bool
362  assert_equal(v:false, thebool)
363
364  let thenumber: number
365  assert_equal(0, thenumber)
366
367  if has('float')
368    let thefloat: float
369    assert_equal(0.0, thefloat)
370  endif
371
372  let thestring: string
373  assert_equal('', thestring)
374
375  let theblob: blob
376  assert_equal(0z, theblob)
377
378  let Thefunc: func
379  assert_equal(test_null_function(), Thefunc)
380
381  let thelist: list<any>
382  assert_equal([], thelist)
383
384  let thedict: dict<any>
385  assert_equal({}, thedict)
386
387  if has('channel')
388    let thejob: job
389    assert_equal(test_null_job(), thejob)
390
391    let thechannel: channel
392    assert_equal(test_null_channel(), thechannel)
393
394    if has('unix') && executable('cat')
395      # check with non-null job and channel, types must match
396      thejob = job_start("cat ", #{})
397      thechannel = job_getchannel(thejob)
398      job_stop(thejob, 'kill')
399    endif
400  endif
401
402  let nr = 1234 | nr = 5678
403  assert_equal(5678, nr)
404enddef
405
406def Test_assignment_var_list()
407  let v1: string
408  let v2: string
409  let vrem: list<string>
410  [v1] = ['aaa']
411  assert_equal('aaa', v1)
412
413  [v1, v2] = ['one', 'two']
414  assert_equal('one', v1)
415  assert_equal('two', v2)
416
417  [v1, v2; vrem] = ['one', 'two']
418  assert_equal('one', v1)
419  assert_equal('two', v2)
420  assert_equal([], vrem)
421
422  [v1, v2; vrem] = ['one', 'two', 'three']
423  assert_equal('one', v1)
424  assert_equal('two', v2)
425  assert_equal(['three'], vrem)
426
427  [&ts, &sw] = [3, 4]
428  assert_equal(3, &ts)
429  assert_equal(4, &sw)
430  set ts=8 sw=4
431enddef
432
433def Test_assignment_vim9script()
434  let lines =<< trim END
435    vim9script
436    def Func(): list<number>
437      return [1, 2]
438    enddef
439    let var1: number
440    let var2: number
441    [var1, var2] =
442          Func()
443    assert_equal(1, var1)
444    assert_equal(2, var2)
445    let ll =
446          Func()
447    assert_equal([1, 2], ll)
448
449    @/ = 'text'
450    assert_equal('text', @/)
451    @0 = 'zero'
452    assert_equal('zero', @0)
453    @1 = 'one'
454    assert_equal('one', @1)
455    @9 = 'nine'
456    assert_equal('nine', @9)
457    @- = 'minus'
458    assert_equal('minus', @-)
459    if has('clipboard_working')
460      @* = 'star'
461      assert_equal('star', @*)
462      @+ = 'plus'
463      assert_equal('plus', @+)
464    endif
465
466    let a: number = 123
467    assert_equal(123, a)
468    let s: string = 'yes'
469    assert_equal('yes', s)
470    let b: number = 42
471    assert_equal(42, b)
472    let w: number = 43
473    assert_equal(43, w)
474    let t: number = 44
475    assert_equal(44, t)
476  END
477  CheckScriptSuccess(lines)
478enddef
479
480def Mess(): string
481  v:foldstart = 123
482  return 'xxx'
483enddef
484
485def Test_assignment_failure()
486  call CheckDefFailure(['let var=234'], 'E1004:')
487  call CheckDefFailure(['let var =234'], 'E1004:')
488  call CheckDefFailure(['let var= 234'], 'E1004:')
489
490  call CheckScriptFailure(['vim9script', 'let var=234'], 'E1004:')
491  call CheckScriptFailure(['vim9script', 'let var=234'], "before and after '='")
492  call CheckScriptFailure(['vim9script', 'let var =234'], 'E1004:')
493  call CheckScriptFailure(['vim9script', 'let var= 234'], 'E1004:')
494  call CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], 'E1004:')
495  call CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], "before and after '+='")
496  call CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], 'E1004:')
497  call CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], "before and after '..='")
498
499  call CheckDefFailure(['let true = 1'], 'E1034:')
500  call CheckDefFailure(['let false = 1'], 'E1034:')
501
502  call CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
503  call CheckDefExecFailure(['let a: number',
504                            '[a] = test_null_list()'], 'E1093:')
505  call CheckDefExecFailure(['let a: number',
506                            '[a] = []'], 'E1093:')
507  call CheckDefExecFailure(['let x: number',
508                            'let y: number',
509                            '[x, y] = [1]'], 'E1093:')
510  call CheckDefExecFailure(['let x: number',
511                            'let y: number',
512                            'let z: list<number>',
513                            '[x, y; z] = [1]'], 'E1093:')
514
515  call CheckDefFailure(['let somevar'], "E1022:")
516  call CheckDefFailure(['let &tabstop = 4'], 'E1052:')
517  call CheckDefFailure(['&g:option = 5'], 'E113:')
518  call CheckScriptFailure(['vim9script', 'let &tabstop = 4'], 'E1052:')
519
520  call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:')
521  call CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:')
522
523  if has('dnd')
524    call CheckDefFailure(['let @~ = 5'], 'E1066:')
525  else
526    call CheckDefFailure(['let @~ = 5'], 'E354:')
527    call CheckDefFailure(['@~ = 5'], 'E354:')
528  endif
529  call CheckDefFailure(['let @a = 5'], 'E1066:')
530  call CheckDefFailure(['let @/ = "x"'], 'E1066:')
531  call CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:')
532
533  call CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:')
534  call CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:')
535  call CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer variable:')
536  call CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:')
537
538  call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
539  call CheckDefFailure(['let xnr += 4'], 'E1020:')
540
541  call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef', 'defcompile'], 'E1050:')
542
543  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
544  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
545
546  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
547  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
548
549  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
550  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
551
552  call CheckDefFailure(['let var: dict <number>'], 'E1068:')
553  call CheckDefFailure(['let var: dict<number'], 'E1009:')
554
555  call assert_fails('s/^/\=Mess()/n', 'E794:')
556  call CheckDefFailure(['let var: dict<number'], 'E1009:')
557
558  call CheckDefFailure(['w:foo: number = 10'],
559                       'E488: Trailing characters: : number = 1')
560  call CheckDefFailure(['t:foo: bool = true'],
561                       'E488: Trailing characters: : bool = true')
562  call CheckDefFailure(['b:foo: string = "x"'],
563                       'E488: Trailing characters: : string = "x"')
564  call CheckDefFailure(['g:foo: number = 123'],
565                       'E488: Trailing characters: : number = 123')
566enddef
567
568def Test_unlet()
569  g:somevar = 'yes'
570  assert_true(exists('g:somevar'))
571  unlet g:somevar
572  assert_false(exists('g:somevar'))
573  unlet! g:somevar
574
575  call CheckScriptFailure([
576        'vim9script',
577        'let svar = 123',
578        'unlet svar',
579        ], 'E1081:')
580  call CheckScriptFailure([
581        'vim9script',
582        'let svar = 123',
583        'unlet s:svar',
584        ], 'E1081:')
585  call CheckScriptFailure([
586        'vim9script',
587        'let svar = 123',
588        'def Func()',
589        '  unlet svar',
590        'enddef',
591        'defcompile',
592        ], 'E1081:')
593  call CheckScriptFailure([
594        'vim9script',
595        'let svar = 123',
596        'def Func()',
597        '  unlet s:svar',
598        'enddef',
599        'defcompile',
600        ], 'E1081:')
601
602  $ENVVAR = 'foobar'
603  assert_equal('foobar', $ENVVAR)
604  unlet $ENVVAR
605  assert_equal('', $ENVVAR)
606enddef
607
608def Test_delfunction()
609  # Check function is defined in script namespace
610  CheckScriptSuccess([
611      'vim9script',
612      'func CheckMe()',
613      '  return 123',
614      'endfunc',
615      'assert_equal(123, s:CheckMe())',
616      ])
617
618  # Check function in script namespace cannot be deleted
619  CheckScriptFailure([
620      'vim9script',
621      'func DeleteMe1()',
622      'endfunc',
623      'delfunction DeleteMe1',
624      ], 'E1084:')
625  CheckScriptFailure([
626      'vim9script',
627      'func DeleteMe2()',
628      'endfunc',
629      'def DoThat()',
630      '  delfunction DeleteMe2',
631      'enddef',
632      'DoThat()',
633      ], 'E1084:')
634  CheckScriptFailure([
635      'vim9script',
636      'def DeleteMe3()',
637      'enddef',
638      'delfunction DeleteMe3',
639      ], 'E1084:')
640  CheckScriptFailure([
641      'vim9script',
642      'def DeleteMe4()',
643      'enddef',
644      'def DoThat()',
645      '  delfunction DeleteMe4',
646      'enddef',
647      'DoThat()',
648      ], 'E1084:')
649
650  # Check that global :def function can be replaced and deleted
651  let lines =<< trim END
652      vim9script
653      def g:Global(): string
654        return "yes"
655      enddef
656      assert_equal("yes", g:Global())
657      def! g:Global(): string
658        return "no"
659      enddef
660      assert_equal("no", g:Global())
661      delfunc g:Global
662      assert_false(exists('*g:Global'))
663  END
664  CheckScriptSuccess(lines)
665
666  # Check that global function can be replaced by a :def function and deleted
667  lines =<< trim END
668      vim9script
669      func g:Global()
670        return "yes"
671      endfunc
672      assert_equal("yes", g:Global())
673      def! g:Global(): string
674        return "no"
675      enddef
676      assert_equal("no", g:Global())
677      delfunc g:Global
678      assert_false(exists('*g:Global'))
679  END
680  CheckScriptSuccess(lines)
681
682  # Check that global :def function can be replaced by a function and deleted
683  lines =<< trim END
684      vim9script
685      def g:Global(): string
686        return "yes"
687      enddef
688      assert_equal("yes", g:Global())
689      func! g:Global()
690        return "no"
691      endfunc
692      assert_equal("no", g:Global())
693      delfunc g:Global
694      assert_false(exists('*g:Global'))
695  END
696  CheckScriptSuccess(lines)
697enddef
698
699func Test_wrong_type()
700  call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
701  call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
702  call CheckDefFailure(['let var: dict<nothing>'], 'E1010:')
703  call CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:')
704
705  call CheckDefFailure(['let var: dict<number'], 'E1009:')
706  call CheckDefFailure(['let var: dict<list<number>'], 'E1009:')
707
708  call CheckDefFailure(['let var: ally'], 'E1010:')
709  call CheckDefFailure(['let var: bram'], 'E1010:')
710  call CheckDefFailure(['let var: cathy'], 'E1010:')
711  call CheckDefFailure(['let var: dom'], 'E1010:')
712  call CheckDefFailure(['let var: freddy'], 'E1010:')
713  call CheckDefFailure(['let var: john'], 'E1010:')
714  call CheckDefFailure(['let var: larry'], 'E1010:')
715  call CheckDefFailure(['let var: ned'], 'E1010:')
716  call CheckDefFailure(['let var: pam'], 'E1010:')
717  call CheckDefFailure(['let var: sam'], 'E1010:')
718  call CheckDefFailure(['let var: vim'], 'E1010:')
719
720  call CheckDefFailure(['let Ref: number', 'Ref()'], 'E1085:')
721  call CheckDefFailure(['let Ref: string', 'let res = Ref()'], 'E1085:')
722endfunc
723
724func Test_const()
725  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
726  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
727  call CheckDefFailure(['const two'], 'E1021:')
728  call CheckDefFailure(['const &option'], 'E996:')
729endfunc
730
731def Test_range_no_colon()
732  call CheckDefFailure(['%s/a/b/'], 'E1050:')
733  call CheckDefFailure(['+ s/a/b/'], 'E1050:')
734  call CheckDefFailure(['- s/a/b/'], 'E1050:')
735  call CheckDefFailure(['. s/a/b/'], 'E1050:')
736enddef
737
738
739def Test_block()
740  let outer = 1
741  {
742    let inner = 2
743    assert_equal(1, outer)
744    assert_equal(2, inner)
745  }
746  assert_equal(1, outer)
747enddef
748
749func Test_block_failure()
750  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
751  call CheckDefFailure(['}'], 'E1025:')
752  call CheckDefFailure(['{', 'echo 1'], 'E1026:')
753endfunc
754
755func g:NoSuchFunc()
756  echo 'none'
757endfunc
758
759def Test_try_catch()
760  let l = []
761  try # comment
762    add(l, '1')
763    throw 'wrong'
764    add(l, '2')
765  catch # comment
766    add(l, v:exception)
767  finally # comment
768    add(l, '3')
769  endtry # comment
770  assert_equal(['1', 'wrong', '3'], l)
771
772  l = []
773  try
774    try
775      add(l, '1')
776      throw 'wrong'
777      add(l, '2')
778    catch /right/
779      add(l, v:exception)
780    endtry
781  catch /wrong/
782    add(l, 'caught')
783  finally
784    add(l, 'finally')
785  endtry
786  assert_equal(['1', 'caught', 'finally'], l)
787
788  let n: number
789  try
790    n = l[3]
791  catch /E684:/
792    n = 99
793  endtry
794  assert_equal(99, n)
795
796  try
797    n = g:astring[3]
798  catch /E714:/
799    n = 77
800  endtry
801  assert_equal(77, n)
802
803  try
804    n = l[g:astring]
805  catch /E39:/
806    n = 77
807  endtry
808  assert_equal(77, n)
809
810  try
811    n = s:does_not_exist
812  catch /E121:/
813    n = 111
814  endtry
815  assert_equal(111, n)
816
817  try
818    n = g:does_not_exist
819  catch /E121:/
820    n = 121
821  endtry
822  assert_equal(121, n)
823
824  let d = #{one: 1}
825  try
826    n = d[g:astring]
827  catch /E716:/
828    n = 222
829  endtry
830  assert_equal(222, n)
831
832  try
833    n = -g:astring
834  catch /E39:/
835    n = 233
836  endtry
837  assert_equal(233, n)
838
839  try
840    n = +g:astring
841  catch /E1030:/
842    n = 244
843  endtry
844  assert_equal(244, n)
845
846  try
847    n = +g:alist
848  catch /E745:/
849    n = 255
850  endtry
851  assert_equal(255, n)
852
853  let nd: dict<any>
854  try
855    nd = {g:anumber: 1}
856  catch /E1029:/
857    n = 266
858  endtry
859  assert_equal(266, n)
860
861  try
862    [n] = [1, 2, 3]
863  catch /E1093:/
864    n = 277
865  endtry
866  assert_equal(277, n)
867
868  try
869    &ts = g:astring
870  catch /E1029:/
871    n = 288
872  endtry
873  assert_equal(288, n)
874
875  try
876    &backspace = 'asdf'
877  catch /E474:/
878    n = 299
879  endtry
880  assert_equal(299, n)
881
882  l = [1]
883  try
884    l[3] = 3
885  catch /E684:/
886    n = 300
887  endtry
888  assert_equal(300, n)
889
890  try
891    unlet g:does_not_exist
892  catch /E108:/
893    n = 322
894  endtry
895  assert_equal(322, n)
896
897  try
898    d = {'text': 1, g:astring: 2}
899  catch /E721:/
900    n = 333
901  endtry
902  assert_equal(333, n)
903
904  try
905    l = DeletedFunc()
906  catch /E933:/
907    n = 344
908  endtry
909  assert_equal(344, n)
910
911  try
912    echo len(v:true)
913  catch /E701:/
914    n = 355
915  endtry
916  assert_equal(355, n)
917
918  let P = function('g:NoSuchFunc')
919  delfunc g:NoSuchFunc
920  try
921    echo P()
922  catch /E117:/
923    n = 366
924  endtry
925  assert_equal(366, n)
926
927  try
928    echo g:NoSuchFunc()
929  catch /E117:/
930    n = 377
931  endtry
932  assert_equal(377, n)
933
934  try
935    echo g:alist + 4
936  catch /E745:/
937    n = 388
938  endtry
939  assert_equal(388, n)
940
941  try
942    echo 4 + g:alist
943  catch /E745:/
944    n = 399
945  endtry
946  assert_equal(399, n)
947
948  try
949    echo g:alist.member
950  catch /E715:/
951    n = 400
952  endtry
953  assert_equal(400, n)
954
955  try
956    echo d.member
957  catch /E716:/
958    n = 411
959  endtry
960  assert_equal(411, n)
961enddef
962
963def DeletedFunc(): list<any>
964  return ['delete me']
965enddef
966defcompile
967delfunc DeletedFunc
968
969def ThrowFromDef()
970  throw "getout" # comment
971enddef
972
973func CatchInFunc()
974  try
975    call ThrowFromDef()
976  catch
977    let g:thrown_func = v:exception
978  endtry
979endfunc
980
981def CatchInDef()
982  try
983    ThrowFromDef()
984  catch
985    g:thrown_def = v:exception
986  endtry
987enddef
988
989def ReturnFinally(): string
990  try
991    return 'intry'
992  finally
993    g:in_finally = 'finally'
994  endtry
995  return 'end'
996enddef
997
998def Test_try_catch_nested()
999  CatchInFunc()
1000  assert_equal('getout', g:thrown_func)
1001
1002  CatchInDef()
1003  assert_equal('getout', g:thrown_def)
1004
1005  assert_equal('intry', ReturnFinally())
1006  assert_equal('finally', g:in_finally)
1007enddef
1008
1009def Test_try_catch_match()
1010  let seq = 'a'
1011  try
1012    throw 'something'
1013  catch /nothing/
1014    seq ..= 'x'
1015  catch /some/
1016    seq ..= 'b'
1017  catch /asdf/
1018    seq ..= 'x'
1019  catch ?a\?sdf?
1020    seq ..= 'y'
1021  finally
1022    seq ..= 'c'
1023  endtry
1024  assert_equal('abc', seq)
1025enddef
1026
1027def Test_try_catch_fails()
1028  call CheckDefFailure(['catch'], 'E603:')
1029  call CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:')
1030  call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
1031  call CheckDefFailure(['finally'], 'E606:')
1032  call CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
1033  call CheckDefFailure(['endtry'], 'E602:')
1034  call CheckDefFailure(['while 1', 'endtry'], 'E170:')
1035  call CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
1036  call CheckDefFailure(['if 2', 'endtry'], 'E171:')
1037  call CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
1038
1039  call CheckDefFailure(['throw'], 'E1015:')
1040  call CheckDefFailure(['throw xxx'], 'E1001:')
1041enddef
1042
1043def Test_throw_vimscript()
1044  # only checks line continuation
1045  let lines =<< trim END
1046      vim9script
1047      try
1048        throw 'one'
1049              .. 'two'
1050      catch
1051        assert_equal('onetwo', v:exception)
1052      endtry
1053  END
1054  CheckScriptSuccess(lines)
1055enddef
1056
1057def Test_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'], 'E1013:')
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_overrules_import_fails()
1800  let export_lines =<< trim END
1801      vim9script
1802      export def Func()
1803        echo 'imported'
1804      enddef
1805  END
1806  writefile(export_lines, 'XexportedFunc.vim')
1807
1808  let lines =<< trim END
1809    vim9script
1810    import Func from './XexportedFunc.vim'
1811    def Func()
1812      echo 'local to function'
1813    enddef
1814  END
1815  CheckScriptFailure(lines, 'E1073:')
1816
1817  lines =<< trim END
1818    vim9script
1819    import Func from './XexportedFunc.vim'
1820    def Outer()
1821      def Func()
1822        echo 'local to function'
1823      enddef
1824    enddef
1825    defcompile
1826  END
1827  CheckScriptFailure(lines, 'E1073:')
1828
1829  delete('XexportedFunc.vim')
1830enddef
1831
1832def Test_func_redefine_fails()
1833  let lines =<< trim END
1834    vim9script
1835    def Func()
1836      echo 'one'
1837    enddef
1838    def Func()
1839      echo 'two'
1840    enddef
1841  END
1842  CheckScriptFailure(lines, 'E1073:')
1843
1844  lines =<< trim END
1845    vim9script
1846    def Foo(): string
1847      return 'foo'
1848      enddef
1849    def Func()
1850      let  Foo = {-> 'lambda'}
1851    enddef
1852    defcompile
1853  END
1854  CheckScriptFailure(lines, 'E1073:')
1855enddef
1856
1857def Test_fixed_size_list()
1858  # will be allocated as one piece of memory, check that changes work
1859  let l = [1, 2, 3, 4]
1860  l->remove(0)
1861  l->add(5)
1862  l->insert(99, 1)
1863  assert_equal([2, 99, 3, 4, 5], l)
1864enddef
1865
1866def Test_no_insert_xit()
1867  call CheckDefExecFailure(['a = 1'], 'E1100:')
1868  call CheckDefExecFailure(['c = 1'], 'E1100:')
1869  call CheckDefExecFailure(['i = 1'], 'E1100:')
1870  call CheckDefExecFailure(['t = 1'], 'E1100:')
1871  call CheckDefExecFailure(['x = 1'], 'E1100:')
1872
1873  CheckScriptFailure(['vim9script', 'a = 1'], 'E488:')
1874  CheckScriptFailure(['vim9script', 'a'], 'E1100:')
1875  CheckScriptFailure(['vim9script', 'c = 1'], 'E488:')
1876  CheckScriptFailure(['vim9script', 'c'], 'E1100:')
1877  CheckScriptFailure(['vim9script', 'i = 1'], 'E488:')
1878  CheckScriptFailure(['vim9script', 'i'], 'E1100:')
1879  CheckScriptFailure(['vim9script', 't'], 'E1100:')
1880  CheckScriptFailure(['vim9script', 't = 1'], 'E1100:')
1881  CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:')
1882enddef
1883
1884def IfElse(what: number): string
1885  let res = ''
1886  if what == 1
1887    res = "one"
1888  elseif what == 2
1889    res = "two"
1890  else
1891    res = "three"
1892  endif
1893  return res
1894enddef
1895
1896def Test_if_elseif_else()
1897  assert_equal('one', IfElse(1))
1898  assert_equal('two', IfElse(2))
1899  assert_equal('three', IfElse(3))
1900enddef
1901
1902def Test_if_elseif_else_fails()
1903  call CheckDefFailure(['elseif true'], 'E582:')
1904  call CheckDefFailure(['else'], 'E581:')
1905  call CheckDefFailure(['endif'], 'E580:')
1906  call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
1907  call CheckDefFailure(['if true', 'echo 1'], 'E171:')
1908enddef
1909
1910let g:bool_true = v:true
1911let g:bool_false = v:false
1912
1913def Test_if_const_expr()
1914  let res = false
1915  if true ? true : false
1916    res = true
1917  endif
1918  assert_equal(true, res)
1919
1920  g:glob = 2
1921  if false
1922    execute('g:glob = 3')
1923  endif
1924  assert_equal(2, g:glob)
1925  if true
1926    execute('g:glob = 3')
1927  endif
1928  assert_equal(3, g:glob)
1929
1930  res = false
1931  if g:bool_true ? true : false
1932    res = true
1933  endif
1934  assert_equal(true, res)
1935
1936  res = false
1937  if true ? g:bool_true : false
1938    res = true
1939  endif
1940  assert_equal(true, res)
1941
1942  res = false
1943  if true ? true : g:bool_false
1944    res = true
1945  endif
1946  assert_equal(true, res)
1947
1948  res = false
1949  if true ? false : true
1950    res = true
1951  endif
1952  assert_equal(false, res)
1953
1954  res = false
1955  if false ? false : true
1956    res = true
1957  endif
1958  assert_equal(true, res)
1959
1960  res = false
1961  if false ? true : false
1962    res = true
1963  endif
1964  assert_equal(false, res)
1965
1966  res = false
1967  if has('xyz') ? true : false
1968    res = true
1969  endif
1970  assert_equal(false, res)
1971
1972  res = false
1973  if true && true
1974    res = true
1975  endif
1976  assert_equal(true, res)
1977
1978  res = false
1979  if true && false
1980    res = true
1981  endif
1982  assert_equal(false, res)
1983
1984  res = false
1985  if g:bool_true && false
1986    res = true
1987  endif
1988  assert_equal(false, res)
1989
1990  res = false
1991  if true && g:bool_false
1992    res = true
1993  endif
1994  assert_equal(false, res)
1995
1996  res = false
1997  if false && false
1998    res = true
1999  endif
2000  assert_equal(false, res)
2001
2002  res = false
2003  if true || false
2004    res = true
2005  endif
2006  assert_equal(true, res)
2007
2008  res = false
2009  if g:bool_true || false
2010    res = true
2011  endif
2012  assert_equal(true, res)
2013
2014  res = false
2015  if true || g:bool_false
2016    res = true
2017  endif
2018  assert_equal(true, res)
2019
2020  res = false
2021  if false || false
2022    res = true
2023  endif
2024  assert_equal(false, res)
2025enddef
2026
2027def Test_if_const_expr_fails()
2028  call CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
2029  call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
2030  call CheckDefFailure(["if has('aaa'"], 'E110:')
2031  call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
2032enddef
2033
2034def RunNested(i: number): number
2035  let x: number = 0
2036  if i % 2
2037    if 1
2038      # comment
2039    else
2040      # comment
2041    endif
2042    x += 1
2043  else
2044    x += 1000
2045  endif
2046  return x
2047enddef
2048
2049def Test_nested_if()
2050  assert_equal(1, RunNested(1))
2051  assert_equal(1000, RunNested(2))
2052enddef
2053
2054def Test_execute_cmd()
2055  new
2056  setline(1, 'default')
2057  execute 'call setline(1, "execute-string")'
2058  assert_equal('execute-string', getline(1))
2059
2060  execute "call setline(1, 'execute-string')"
2061  assert_equal('execute-string', getline(1))
2062
2063  let cmd1 = 'call setline(1,'
2064  let cmd2 = '"execute-var")'
2065  execute cmd1 cmd2 # comment
2066  assert_equal('execute-var', getline(1))
2067
2068  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
2069  assert_equal('execute-var-string', getline(1))
2070
2071  let cmd_first = 'call '
2072  let cmd_last = 'setline(1, "execute-var-var")'
2073  execute cmd_first .. cmd_last
2074  assert_equal('execute-var-var', getline(1))
2075  bwipe!
2076
2077  let n = true
2078  execute 'echomsg' (n ? '"true"' : '"no"')
2079  assert_match('^true$', Screenline(&lines))
2080
2081  call CheckDefFailure(['execute xxx'], 'E1001:')
2082  call CheckDefFailure(['execute "cmd"# comment'], 'E488:')
2083enddef
2084
2085def Test_execute_cmd_vimscript()
2086  # only checks line continuation
2087  let lines =<< trim END
2088      vim9script
2089      execute 'g:someVar'
2090                .. ' = ' ..
2091                   '28'
2092      assert_equal(28, g:someVar)
2093      unlet g:someVar
2094  END
2095  CheckScriptSuccess(lines)
2096enddef
2097
2098def Test_echo_cmd()
2099  echo 'some' # comment
2100  echon 'thing'
2101  assert_match('^something$', Screenline(&lines))
2102
2103  echo "some" # comment
2104  echon "thing"
2105  assert_match('^something$', Screenline(&lines))
2106
2107  let str1 = 'some'
2108  let str2 = 'more'
2109  echo str1 str2
2110  assert_match('^some more$', Screenline(&lines))
2111
2112  call CheckDefFailure(['echo "xxx"# comment'], 'E488:')
2113enddef
2114
2115def Test_echomsg_cmd()
2116  echomsg 'some' 'more' # comment
2117  assert_match('^some more$', Screenline(&lines))
2118  echo 'clear'
2119  :1messages
2120  assert_match('^some more$', Screenline(&lines))
2121
2122  call CheckDefFailure(['echomsg "xxx"# comment'], 'E488:')
2123enddef
2124
2125def Test_echomsg_cmd_vimscript()
2126  # only checks line continuation
2127  let lines =<< trim END
2128      vim9script
2129      echomsg 'here'
2130                .. ' is ' ..
2131                   'a message'
2132      assert_match('^here is a message$', Screenline(&lines))
2133  END
2134  CheckScriptSuccess(lines)
2135enddef
2136
2137def Test_echoerr_cmd()
2138  try
2139    echoerr 'something' 'wrong' # comment
2140  catch
2141    assert_match('something wrong', v:exception)
2142  endtry
2143enddef
2144
2145def Test_echoerr_cmd_vimscript()
2146  # only checks line continuation
2147  let lines =<< trim END
2148      vim9script
2149      try
2150        echoerr 'this'
2151                .. ' is ' ..
2152                   'wrong'
2153      catch
2154        assert_match('this is wrong', v:exception)
2155      endtry
2156  END
2157  CheckScriptSuccess(lines)
2158enddef
2159
2160def Test_for_outside_of_function()
2161  let lines =<< trim END
2162    vim9script
2163    new
2164    for var in range(0, 3)
2165      append(line('$'), var)
2166    endfor
2167    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
2168    bwipe!
2169  END
2170  writefile(lines, 'Xvim9for.vim')
2171  source Xvim9for.vim
2172  delete('Xvim9for.vim')
2173enddef
2174
2175def Test_for_loop()
2176  let result = ''
2177  for cnt in range(7)
2178    if cnt == 4
2179      break
2180    endif
2181    if cnt == 2
2182      continue
2183    endif
2184    result ..= cnt .. '_'
2185  endfor
2186  assert_equal('0_1_3_', result)
2187
2188  let concat = ''
2189  for str in eval('["one", "two"]')
2190    concat ..= str
2191  endfor
2192  assert_equal('onetwo', concat)
2193enddef
2194
2195def Test_for_loop_fails()
2196  CheckDefFailure(['for # in range(5)'], 'E690:')
2197  CheckDefFailure(['for i In range(5)'], 'E690:')
2198  CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
2199  CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:')
2200  CheckDefFailure(['for i in "text"'], 'E1013:')
2201  CheckDefFailure(['for i in xxx'], 'E1001:')
2202  CheckDefFailure(['endfor'], 'E588:')
2203  CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
2204enddef
2205
2206def Test_while_loop()
2207  let result = ''
2208  let cnt = 0
2209  while cnt < 555
2210    if cnt == 3
2211      break
2212    endif
2213    cnt += 1
2214    if cnt == 2
2215      continue
2216    endif
2217    result ..= cnt .. '_'
2218  endwhile
2219  assert_equal('1_3_', result)
2220enddef
2221
2222def Test_while_loop_fails()
2223  CheckDefFailure(['while xxx'], 'E1001:')
2224  CheckDefFailure(['endwhile'], 'E588:')
2225  CheckDefFailure(['continue'], 'E586:')
2226  CheckDefFailure(['if true', 'continue'], 'E586:')
2227  CheckDefFailure(['break'], 'E587:')
2228  CheckDefFailure(['if true', 'break'], 'E587:')
2229  CheckDefFailure(['while 1', 'echo 3'], 'E170:')
2230enddef
2231
2232def Test_interrupt_loop()
2233  let caught = false
2234  let x = 0
2235  try
2236    while 1
2237      x += 1
2238      if x == 100
2239        feedkeys("\<C-C>", 'Lt')
2240      endif
2241    endwhile
2242  catch
2243    caught = true
2244    assert_equal(100, x)
2245  endtry
2246  assert_true(caught, 'should have caught an exception')
2247enddef
2248
2249def Test_automatic_line_continuation()
2250  let mylist = [
2251      'one',
2252      'two',
2253      'three',
2254      ] # comment
2255  assert_equal(['one', 'two', 'three'], mylist)
2256
2257  let mydict = {
2258      'one': 1,
2259      'two': 2,
2260      'three':
2261          3,
2262      } # comment
2263  assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
2264  mydict = #{
2265      one: 1,  # comment
2266      two:     # comment
2267           2,  # comment
2268      three: 3 # comment
2269      }
2270  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
2271  mydict = #{
2272      one: 1,
2273      two:
2274           2,
2275      three: 3
2276      }
2277  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
2278
2279  assert_equal(
2280        ['one', 'two', 'three'],
2281        split('one two three')
2282        )
2283enddef
2284
2285def Test_vim9_comment()
2286  CheckScriptSuccess([
2287      'vim9script',
2288      '# something',
2289      ])
2290  CheckScriptFailure([
2291      'vim9script',
2292      ':# something',
2293      ], 'E488:')
2294  CheckScriptFailure([
2295      '# something',
2296      ], 'E488:')
2297  CheckScriptFailure([
2298      ':# something',
2299      ], 'E488:')
2300
2301  { # block start
2302  } # block end
2303  CheckDefFailure([
2304      '{# comment',
2305      ], 'E488:')
2306  CheckDefFailure([
2307      '{',
2308      '}# comment',
2309      ], 'E488:')
2310
2311  echo "yes" # comment
2312  CheckDefFailure([
2313      'echo "yes"# comment',
2314      ], 'E488:')
2315  CheckScriptSuccess([
2316      'vim9script',
2317      'echo "yes" # something',
2318      ])
2319  CheckScriptFailure([
2320      'vim9script',
2321      'echo "yes"# something',
2322      ], 'E121:')
2323  CheckScriptFailure([
2324      'vim9script',
2325      'echo# something',
2326      ], 'E121:')
2327  CheckScriptFailure([
2328      'echo "yes" # something',
2329      ], 'E121:')
2330
2331  exe "echo" # comment
2332  CheckDefFailure([
2333      'exe "echo"# comment',
2334      ], 'E488:')
2335  CheckScriptSuccess([
2336      'vim9script',
2337      'exe "echo" # something',
2338      ])
2339  CheckScriptFailure([
2340      'vim9script',
2341      'exe "echo"# something',
2342      ], 'E121:')
2343  CheckDefFailure([
2344      'exe # comment',
2345      ], 'E1015:')
2346  CheckScriptFailure([
2347      'vim9script',
2348      'exe# something',
2349      ], 'E121:')
2350  CheckScriptFailure([
2351      'exe "echo" # something',
2352      ], 'E121:')
2353
2354  CheckDefFailure([
2355      'try# comment',
2356      '  echo "yes"',
2357      'catch',
2358      'endtry',
2359      ], 'E488:')
2360  CheckScriptFailure([
2361      'vim9script',
2362      'try# comment',
2363      'echo "yes"',
2364      ], 'E488:')
2365  CheckDefFailure([
2366      'try',
2367      '  throw#comment',
2368      'catch',
2369      'endtry',
2370      ], 'E1015:')
2371  CheckDefFailure([
2372      'try',
2373      '  throw "yes"#comment',
2374      'catch',
2375      'endtry',
2376      ], 'E488:')
2377  CheckDefFailure([
2378      'try',
2379      '  echo "yes"',
2380      'catch# comment',
2381      'endtry',
2382      ], 'E488:')
2383  CheckScriptFailure([
2384      'vim9script',
2385      'try',
2386      '  echo "yes"',
2387      'catch# comment',
2388      'endtry',
2389      ], 'E654:')
2390  CheckDefFailure([
2391      'try',
2392      '  echo "yes"',
2393      'catch /pat/# comment',
2394      'endtry',
2395      ], 'E488:')
2396  CheckDefFailure([
2397      'try',
2398      'echo "yes"',
2399      'catch',
2400      'endtry# comment',
2401      ], 'E488:')
2402  CheckScriptFailure([
2403      'vim9script',
2404      'try',
2405      '  echo "yes"',
2406      'catch',
2407      'endtry# comment',
2408      ], 'E488:')
2409
2410  CheckScriptSuccess([
2411      'vim9script',
2412      'hi # comment',
2413      ])
2414  CheckScriptFailure([
2415      'vim9script',
2416      'hi# comment',
2417      ], 'E416:')
2418  CheckScriptSuccess([
2419      'vim9script',
2420      'hi Search # comment',
2421      ])
2422  CheckScriptFailure([
2423      'vim9script',
2424      'hi Search# comment',
2425      ], 'E416:')
2426  CheckScriptSuccess([
2427      'vim9script',
2428      'hi link This Search # comment',
2429      ])
2430  CheckScriptFailure([
2431      'vim9script',
2432      'hi link This That# comment',
2433      ], 'E413:')
2434  CheckScriptSuccess([
2435      'vim9script',
2436      'hi clear This # comment',
2437      'hi clear # comment',
2438      ])
2439  # not tested, because it doesn't give an error but a warning:
2440  # hi clear This# comment',
2441  CheckScriptFailure([
2442      'vim9script',
2443      'hi clear# comment',
2444      ], 'E416:')
2445
2446  CheckScriptSuccess([
2447      'vim9script',
2448      'hi Group term=bold',
2449      'match Group /todo/ # comment',
2450      ])
2451  CheckScriptFailure([
2452      'vim9script',
2453      'hi Group term=bold',
2454      'match Group /todo/# comment',
2455      ], 'E488:')
2456  CheckScriptSuccess([
2457      'vim9script',
2458      'match # comment',
2459      ])
2460  CheckScriptFailure([
2461      'vim9script',
2462      'match# comment',
2463      ], 'E475:')
2464  CheckScriptSuccess([
2465      'vim9script',
2466      'match none # comment',
2467      ])
2468  CheckScriptFailure([
2469      'vim9script',
2470      'match none# comment',
2471      ], 'E475:')
2472
2473  CheckScriptSuccess([
2474      'vim9script',
2475      'menutrans clear # comment',
2476      ])
2477  CheckScriptFailure([
2478      'vim9script',
2479      'menutrans clear# comment text',
2480      ], 'E474:')
2481
2482  CheckScriptSuccess([
2483      'vim9script',
2484      'syntax clear # comment',
2485      ])
2486  CheckScriptFailure([
2487      'vim9script',
2488      'syntax clear# comment text',
2489      ], 'E28:')
2490  CheckScriptSuccess([
2491      'vim9script',
2492      'syntax keyword Word some',
2493      'syntax clear Word # comment',
2494      ])
2495  CheckScriptFailure([
2496      'vim9script',
2497      'syntax keyword Word some',
2498      'syntax clear Word# comment text',
2499      ], 'E28:')
2500
2501  CheckScriptSuccess([
2502      'vim9script',
2503      'syntax list # comment',
2504      ])
2505  CheckScriptFailure([
2506      'vim9script',
2507      'syntax list# comment text',
2508      ], 'E28:')
2509
2510  CheckScriptSuccess([
2511      'vim9script',
2512      'syntax match Word /pat/ oneline # comment',
2513      ])
2514  CheckScriptFailure([
2515      'vim9script',
2516      'syntax match Word /pat/ oneline# comment',
2517      ], 'E475:')
2518
2519  CheckScriptSuccess([
2520      'vim9script',
2521      'syntax keyword Word word # comm[ent',
2522      ])
2523  CheckScriptFailure([
2524      'vim9script',
2525      'syntax keyword Word word# comm[ent',
2526      ], 'E789:')
2527
2528  CheckScriptSuccess([
2529      'vim9script',
2530      'syntax match Word /pat/ # comment',
2531      ])
2532  CheckScriptFailure([
2533      'vim9script',
2534      'syntax match Word /pat/# comment',
2535      ], 'E402:')
2536
2537  CheckScriptSuccess([
2538      'vim9script',
2539      'syntax match Word /pat/ contains=Something # comment',
2540      ])
2541  CheckScriptFailure([
2542      'vim9script',
2543      'syntax match Word /pat/ contains=Something# comment',
2544      ], 'E475:')
2545  CheckScriptFailure([
2546      'vim9script',
2547      'syntax match Word /pat/ contains= # comment',
2548      ], 'E406:')
2549  CheckScriptFailure([
2550      'vim9script',
2551      'syntax match Word /pat/ contains=# comment',
2552      ], 'E475:')
2553
2554  CheckScriptSuccess([
2555      'vim9script',
2556      'syntax region Word start=/pat/ end=/pat/ # comment',
2557      ])
2558  CheckScriptFailure([
2559      'vim9script',
2560      'syntax region Word start=/pat/ end=/pat/# comment',
2561      ], 'E402:')
2562
2563  CheckScriptSuccess([
2564      'vim9script',
2565      'syntax sync # comment',
2566      ])
2567  CheckScriptFailure([
2568      'vim9script',
2569      'syntax sync# comment',
2570      ], 'E404:')
2571  CheckScriptSuccess([
2572      'vim9script',
2573      'syntax sync ccomment # comment',
2574      ])
2575  CheckScriptFailure([
2576      'vim9script',
2577      'syntax sync ccomment# comment',
2578      ], 'E404:')
2579
2580  CheckScriptSuccess([
2581      'vim9script',
2582      'syntax cluster Some contains=Word # comment',
2583      ])
2584  CheckScriptFailure([
2585      'vim9script',
2586      'syntax cluster Some contains=Word# comment',
2587      ], 'E475:')
2588
2589  CheckScriptSuccess([
2590      'vim9script',
2591      'command Echo echo # comment',
2592      'command Echo # comment',
2593      ])
2594  CheckScriptFailure([
2595      'vim9script',
2596      'command Echo echo# comment',
2597      'Echo',
2598      ], 'E121:')
2599  CheckScriptFailure([
2600      'vim9script',
2601      'command Echo# comment',
2602      ], 'E182:')
2603  CheckScriptFailure([
2604      'vim9script',
2605      'command Echo echo',
2606      'command Echo# comment',
2607      ], 'E182:')
2608
2609  CheckScriptSuccess([
2610      'vim9script',
2611      'function # comment',
2612      ])
2613  CheckScriptFailure([
2614      'vim9script',
2615      'function " comment',
2616      ], 'E129:')
2617  CheckScriptFailure([
2618      'vim9script',
2619      'function# comment',
2620      ], 'E129:')
2621  CheckScriptSuccess([
2622      'vim9script',
2623      'function CheckScriptSuccess # comment',
2624      ])
2625  CheckScriptFailure([
2626      'vim9script',
2627      'function CheckScriptSuccess# comment',
2628      ], 'E488:')
2629
2630  CheckScriptSuccess([
2631      'vim9script',
2632      'func g:DeleteMeA()',
2633      'endfunc',
2634      'delfunction g:DeleteMeA # comment',
2635      ])
2636  CheckScriptFailure([
2637      'vim9script',
2638      'func g:DeleteMeB()',
2639      'endfunc',
2640      'delfunction g:DeleteMeB# comment',
2641      ], 'E488:')
2642
2643  CheckScriptSuccess([
2644      'vim9script',
2645      'call execute("ls") # comment',
2646      ])
2647  CheckScriptFailure([
2648      'vim9script',
2649      'call execute("ls")# comment',
2650      ], 'E488:')
2651
2652  CheckScriptFailure([
2653      'def Test() " comment',
2654      'enddef',
2655      ], 'E488:')
2656  CheckScriptFailure([
2657      'vim9script',
2658      'def Test() " comment',
2659      'enddef',
2660      ], 'E488:')
2661
2662  CheckScriptSuccess([
2663      'func Test() " comment',
2664      'endfunc',
2665      ])
2666  CheckScriptSuccess([
2667      'vim9script',
2668      'func Test() " comment',
2669      'endfunc',
2670      ])
2671
2672  CheckScriptSuccess([
2673      'def Test() # comment',
2674      'enddef',
2675      ])
2676  CheckScriptFailure([
2677      'func Test() # comment',
2678      'endfunc',
2679      ], 'E488:')
2680enddef
2681
2682def Test_vim9_comment_gui()
2683  CheckCanRunGui
2684
2685  CheckScriptFailure([
2686      'vim9script',
2687      'gui#comment'
2688      ], 'E499:')
2689  CheckScriptFailure([
2690      'vim9script',
2691      'gui -f#comment'
2692      ], 'E499:')
2693enddef
2694
2695def Test_vim9_comment_not_compiled()
2696  au TabEnter *.vim g:entered = 1
2697  au TabEnter *.x g:entered = 2
2698
2699  edit test.vim
2700  doautocmd TabEnter #comment
2701  assert_equal(1, g:entered)
2702
2703  doautocmd TabEnter f.x
2704  assert_equal(2, g:entered)
2705
2706  g:entered = 0
2707  doautocmd TabEnter f.x #comment
2708  assert_equal(2, g:entered)
2709
2710  assert_fails('doautocmd Syntax#comment', 'E216:')
2711
2712  au! TabEnter
2713  unlet g:entered
2714
2715  CheckScriptSuccess([
2716      'vim9script',
2717      'g:var = 123',
2718      'b:var = 456',
2719      'w:var = 777',
2720      't:var = 888',
2721      'unlet g:var w:var # something',
2722      ])
2723
2724  CheckScriptFailure([
2725      'vim9script',
2726      'let g:var = 123',
2727      ], 'E1016: Cannot declare a global variable:')
2728
2729  CheckScriptFailure([
2730      'vim9script',
2731      'let b:var = 123',
2732      ], 'E1016: Cannot declare a buffer variable:')
2733
2734  CheckScriptFailure([
2735      'vim9script',
2736      'let w:var = 123',
2737      ], 'E1016: Cannot declare a window variable:')
2738
2739  CheckScriptFailure([
2740      'vim9script',
2741      'let t:var = 123',
2742      ], 'E1016: Cannot declare a tab variable:')
2743
2744  CheckScriptFailure([
2745      'vim9script',
2746      'let v:version = 123',
2747      ], 'E1016: Cannot declare a v: variable:')
2748
2749  CheckScriptFailure([
2750      'vim9script',
2751      'let $VARIABLE = "text"',
2752      ], 'E1016: Cannot declare an environment variable:')
2753
2754  CheckScriptFailure([
2755      'vim9script',
2756      'g:var = 123',
2757      'unlet g:var# comment1',
2758      ], 'E108:')
2759
2760  CheckScriptFailure([
2761      'let g:var = 123',
2762      'unlet g:var # something',
2763      ], 'E488:')
2764
2765  CheckScriptSuccess([
2766      'vim9script',
2767      'if 1 # comment2',
2768      '  echo "yes"',
2769      'elseif 2 #comment',
2770      '  echo "no"',
2771      'endif',
2772      ])
2773
2774  CheckScriptFailure([
2775      'vim9script',
2776      'if 1# comment3',
2777      '  echo "yes"',
2778      'endif',
2779      ], 'E15:')
2780
2781  CheckScriptFailure([
2782      'vim9script',
2783      'if 0 # comment4',
2784      '  echo "yes"',
2785      'elseif 2#comment',
2786      '  echo "no"',
2787      'endif',
2788      ], 'E15:')
2789
2790  CheckScriptSuccess([
2791      'vim9script',
2792      'let v = 1 # comment5',
2793      ])
2794
2795  CheckScriptFailure([
2796      'vim9script',
2797      'let v = 1# comment6',
2798      ], 'E15:')
2799
2800  CheckScriptSuccess([
2801      'vim9script',
2802      'new'
2803      'call setline(1, ["# define pat", "last"])',
2804      ':$',
2805      'dsearch /pat/ #comment',
2806      'bwipe!',
2807      ])
2808
2809  CheckScriptFailure([
2810      'vim9script',
2811      'new'
2812      'call setline(1, ["# define pat", "last"])',
2813      ':$',
2814      'dsearch /pat/#comment',
2815      'bwipe!',
2816      ], 'E488:')
2817
2818  CheckScriptFailure([
2819      'vim9script',
2820      'func! SomeFunc()',
2821      ], 'E477:')
2822enddef
2823
2824def Test_finish()
2825  let lines =<< trim END
2826    vim9script
2827    g:res = 'one'
2828    if v:false | finish | endif
2829    g:res = 'two'
2830    finish
2831    g:res = 'three'
2832  END
2833  writefile(lines, 'Xfinished')
2834  source Xfinished
2835  assert_equal('two', g:res)
2836
2837  unlet g:res
2838  delete('Xfinished')
2839enddef
2840
2841def Test_let_func_call()
2842  let lines =<< trim END
2843    vim9script
2844    func GetValue()
2845      if exists('g:count')
2846        let g:count += 1
2847      else
2848        let g:count = 1
2849      endif
2850      return 'this'
2851    endfunc
2852    let val: string = GetValue()
2853    # env var is always a string
2854    let env = $TERM
2855  END
2856  writefile(lines, 'Xfinished')
2857  source Xfinished
2858  # GetValue() is not called during discovery phase
2859  assert_equal(1, g:count)
2860
2861  unlet g:count
2862  delete('Xfinished')
2863enddef
2864
2865def Test_let_missing_type()
2866  let lines =<< trim END
2867    vim9script
2868    let var = g:unknown
2869  END
2870  CheckScriptFailure(lines, 'E121:')
2871
2872  lines =<< trim END
2873    vim9script
2874    let nr: number = 123
2875    let var = nr
2876  END
2877  CheckScriptSuccess(lines)
2878enddef
2879
2880def Test_let_declaration()
2881  let lines =<< trim END
2882    vim9script
2883    let var: string
2884    g:var_uninit = var
2885    var = 'text'
2886    g:var_test = var
2887    # prefixing s: is optional
2888    s:var = 'prefixed'
2889    g:var_prefixed = s:var
2890
2891    let s:other: number
2892    other = 1234
2893    g:other_var = other
2894  END
2895  CheckScriptSuccess(lines)
2896  assert_equal('', g:var_uninit)
2897  assert_equal('text', g:var_test)
2898  assert_equal('prefixed', g:var_prefixed)
2899  assert_equal(1234, g:other_var)
2900
2901  unlet g:var_uninit
2902  unlet g:var_test
2903  unlet g:var_prefixed
2904  unlet g:other_var
2905enddef
2906
2907def Test_let_declaration_fails()
2908  let lines =<< trim END
2909    vim9script
2910    const var: string
2911  END
2912  CheckScriptFailure(lines, 'E1021:')
2913
2914  lines =<< trim END
2915    vim9script
2916    let 9var: string
2917  END
2918  CheckScriptFailure(lines, 'E475:')
2919enddef
2920
2921def Test_let_type_check()
2922  let lines =<< trim END
2923    vim9script
2924    let var: string
2925    var = 1234
2926  END
2927  CheckScriptFailure(lines, 'E1013:')
2928
2929  lines =<< trim END
2930    vim9script
2931    let var:string
2932  END
2933  CheckScriptFailure(lines, 'E1069:')
2934
2935  lines =<< trim END
2936    vim9script
2937    let var: asdf
2938  END
2939  CheckScriptFailure(lines, 'E1010:')
2940
2941  lines =<< trim END
2942    vim9script
2943    let s:l: list<number>
2944    s:l = []
2945  END
2946  CheckScriptSuccess(lines)
2947
2948  lines =<< trim END
2949    vim9script
2950    let s:d: dict<number>
2951    s:d = {}
2952  END
2953  CheckScriptSuccess(lines)
2954enddef
2955
2956def Test_forward_declaration()
2957  let lines =<< trim END
2958    vim9script
2959    def GetValue(): string
2960      return theVal
2961    enddef
2962    let theVal = 'something'
2963    g:initVal = GetValue()
2964    theVal = 'else'
2965    g:laterVal = GetValue()
2966  END
2967  writefile(lines, 'Xforward')
2968  source Xforward
2969  assert_equal('something', g:initVal)
2970  assert_equal('else', g:laterVal)
2971
2972  unlet g:initVal
2973  unlet g:laterVal
2974  delete('Xforward')
2975enddef
2976
2977def Test_source_vim9_from_legacy()
2978  let legacy_lines =<< trim END
2979    source Xvim9_script.vim
2980
2981    call assert_false(exists('local'))
2982    call assert_false(exists('exported'))
2983    call assert_false(exists('s:exported'))
2984    call assert_equal('global', global)
2985    call assert_equal('global', g:global)
2986
2987    " imported variable becomes script-local
2988    import exported from './Xvim9_script.vim'
2989    call assert_equal('exported', s:exported)
2990    call assert_false(exists('exported'))
2991
2992    " imported function becomes script-local
2993    import GetText from './Xvim9_script.vim'
2994    call assert_equal('text', s:GetText())
2995    call assert_false(exists('*GetText'))
2996  END
2997  writefile(legacy_lines, 'Xlegacy_script.vim')
2998
2999  let vim9_lines =<< trim END
3000    vim9script
3001    let local = 'local'
3002    g:global = 'global'
3003    export let exported = 'exported'
3004    export def GetText(): string
3005       return 'text'
3006    enddef
3007  END
3008  writefile(vim9_lines, 'Xvim9_script.vim')
3009
3010  source Xlegacy_script.vim
3011
3012  assert_equal('global', g:global)
3013  unlet g:global
3014
3015  delete('Xlegacy_script.vim')
3016  delete('Xvim9_script.vim')
3017enddef
3018
3019def Test_vim9_copen()
3020  # this was giving an error for setting w:quickfix_title
3021  copen
3022  quit
3023enddef
3024
3025" test using a vim9script that is auto-loaded from an autocmd
3026def Test_vim9_autoload()
3027  let lines =<< trim END
3028     vim9script
3029     def foo#test()
3030         echomsg getreg('"')
3031     enddef
3032  END
3033
3034  mkdir('Xdir/autoload', 'p')
3035  writefile(lines, 'Xdir/autoload/foo.vim')
3036  let save_rtp = &rtp
3037  exe 'set rtp^=' .. getcwd() .. '/Xdir'
3038  augroup test
3039    autocmd TextYankPost * call foo#test()
3040  augroup END
3041
3042  normal Y
3043
3044  augroup test
3045    autocmd!
3046  augroup END
3047  delete('Xdir', 'rf')
3048  &rtp = save_rtp
3049enddef
3050
3051def Test_cmdline_win()
3052  # if the Vim syntax highlighting uses Vim9 constructs they can be used from
3053  # the command line window.
3054  mkdir('rtp/syntax', 'p')
3055  let export_lines =<< trim END
3056    vim9script
3057    export let That = 'yes'
3058  END
3059  writefile(export_lines, 'rtp/syntax/Xexport.vim')
3060  let import_lines =<< trim END
3061    vim9script
3062    import That from './Xexport.vim'
3063  END
3064  writefile(import_lines, 'rtp/syntax/vim.vim')
3065  let save_rtp = &rtp
3066  &rtp = getcwd() .. '/rtp' .. ',' .. &rtp
3067  syntax on
3068  augroup CmdWin
3069    autocmd CmdwinEnter * g:got_there = 'yes'
3070  augroup END
3071  # this will open and also close the cmdline window
3072  feedkeys('q:', 'xt')
3073  assert_equal('yes', g:got_there)
3074
3075  augroup CmdWin
3076    au!
3077  augroup END
3078  &rtp = save_rtp
3079  delete('rtp', 'rf')
3080enddef
3081
3082" Keep this last, it messes up highlighting.
3083def Test_substitute_cmd()
3084  new
3085  setline(1, 'something')
3086  :substitute(some(other(
3087  assert_equal('otherthing', getline(1))
3088  bwipe!
3089
3090  # also when the context is Vim9 script
3091  let lines =<< trim END
3092    vim9script
3093    new
3094    setline(1, 'something')
3095    :substitute(some(other(
3096    assert_equal('otherthing', getline(1))
3097    bwipe!
3098  END
3099  writefile(lines, 'Xvim9lines')
3100  source Xvim9lines
3101
3102  delete('Xvim9lines')
3103enddef
3104
3105" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
3106