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