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