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