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