1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source view_util.vim
5source vim9.vim
6
7def Test_syntax()
8  let var = 234
9  let other: list<string> = ['asdf']
10enddef
11
12let s:appendToMe = 'xxx'
13let s:addToMe = 111
14let g:existing = 'yes'
15let g:inc_counter = 1
16let $SOME_ENV_VAR = 'some'
17let g:alist = [7]
18let g:astring = 'text'
19
20def Test_assignment()
21  let bool1: bool = true
22  assert_equal(v:true, bool1)
23  let bool2: bool = false
24  assert_equal(v:false, bool2)
25
26  call CheckDefFailure(['let x:string'], 'E1069:')
27  call CheckDefFailure(['let x:string = "x"'], 'E1069:')
28  call CheckDefFailure(['let a:string = "x"'], 'E1069:')
29
30  let a: number = 6
31  assert_equal(6, a)
32
33  if has('channel')
34    let chan1: channel
35    let job1: job
36    let job2: job = job_start('willfail')
37  endif
38  if has('float')
39    let float1: float = 3.4
40  endif
41  let Funky1: func
42  let Funky2: func = function('len')
43  let Party2: func = funcref('g:Test_syntax')
44
45  g:newvar = 'new'
46  assert_equal('new', g:newvar)
47
48  assert_equal('yes', g:existing)
49  g:existing = 'no'
50  assert_equal('no', g:existing)
51
52  v:char = 'abc'
53  assert_equal('abc', v:char)
54
55  $ENVVAR = 'foobar'
56  assert_equal('foobar', $ENVVAR)
57  $ENVVAR = ''
58
59  s:appendToMe ..= 'yyy'
60  assert_equal('xxxyyy', s:appendToMe)
61  s:addToMe += 222
62  assert_equal(333, s:addToMe)
63  s:newVar = 'new'
64  assert_equal('new', s:newVar)
65
66  set ts=7
67  &ts += 1
68  assert_equal(8, &ts)
69  &ts -= 3
70  assert_equal(5, &ts)
71  &ts *= 2
72  assert_equal(10, &ts)
73  &ts /= 3
74  assert_equal(3, &ts)
75  set ts=10
76  &ts %= 4
77  assert_equal(2, &ts)
78  call CheckDefFailure(['&notex += 3'], 'E113:')
79  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
80  call CheckDefFailure(['&ts = [7]'], 'E1013:')
81  call CheckDefExecFailure(['&ts = g:alist'], 'E1029: Expected number but got list')
82  call CheckDefFailure(['&ts = "xx"'], 'E1013:')
83  call CheckDefExecFailure(['&ts = g:astring'], 'E1029: Expected number but got string')
84  call CheckDefFailure(['&path += 3'], 'E1013:')
85  call CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
86  # test freeing ISN_STOREOPT
87  call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
88  &ts = 8
89
90  g:inc_counter += 1
91  assert_equal(2, g:inc_counter)
92
93  $SOME_ENV_VAR ..= 'more'
94  assert_equal('somemore', $SOME_ENV_VAR)
95  call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:')
96  call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:')
97
98  @a = 'areg'
99  @a ..= 'add'
100  assert_equal('aregadd', @a)
101  call CheckDefFailure(['@a += "more"'], 'E1013:')
102  call CheckDefFailure(['@a += 123'], 'E1013:')
103
104  v:errmsg = 'none'
105  v:errmsg ..= 'again'
106  assert_equal('noneagain', v:errmsg)
107  call CheckDefFailure(['v:errmsg += "more"'], 'E1013:')
108  call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
109enddef
110
111def Test_assignment_list()
112  let list1: list<bool> = [false, true, false]
113  let list2: list<number> = [1, 2, 3]
114  let list3: list<string> = ['sdf', 'asdf']
115  let list4: list<any> = ['yes', true, 1234]
116  let list5: list<blob> = [0z01, 0z02]
117
118  let listS: list<string> = []
119  let listN: list<number> = []
120
121  assert_equal([1, 2, 3], list2)
122  list2[-1] = 99
123  assert_equal([1, 2, 99], list2)
124  list2[-2] = 88
125  assert_equal([1, 88, 99], list2)
126  list2[-3] = 77
127  assert_equal([77, 88, 99], list2)
128  call CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
129
130  # type becomes list<any>
131  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
132enddef
133
134def Test_assignment_dict()
135  let dict1: dict<bool> = #{one: false, two: true}
136  let dict2: dict<number> = #{one: 1, two: 2}
137  let dict3: dict<string> = #{key: 'value'}
138  let dict4: dict<any> = #{one: 1, two: '2'}
139  let dict5: dict<blob> = #{one: 0z01, two: 0z02}
140
141  call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:')
142
143  # type becomes dict<any>
144  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
145enddef
146
147def Test_assignment_local()
148  " Test in a separated file in order not to the current buffer/window/tab is
149  " changed.
150  let script_lines: list<string> =<< trim END
151    let b:existing = 'yes'
152    let w:existing = 'yes'
153    let t:existing = 'yes'
154
155    def Test_assignment_local_internal()
156      b:newvar = 'new'
157      assert_equal('new', b:newvar)
158      assert_equal('yes', b:existing)
159      b:existing = 'no'
160      assert_equal('no', b:existing)
161      b:existing ..= 'NO'
162      assert_equal('noNO', b:existing)
163
164      w:newvar = 'new'
165      assert_equal('new', w:newvar)
166      assert_equal('yes', w:existing)
167      w:existing = 'no'
168      assert_equal('no', w:existing)
169      w:existing ..= 'NO'
170      assert_equal('noNO', w:existing)
171
172      t:newvar = 'new'
173      assert_equal('new', t:newvar)
174      assert_equal('yes', t:existing)
175      t:existing = 'no'
176      assert_equal('no', t:existing)
177      t:existing ..= 'NO'
178      assert_equal('noNO', t:existing)
179    enddef
180    call Test_assignment_local_internal()
181  END
182  call CheckScriptSuccess(script_lines)
183enddef
184
185def Test_assignment_default()
186
187  # Test default values.
188  let thebool: bool
189  assert_equal(v:false, thebool)
190
191  let thenumber: number
192  assert_equal(0, thenumber)
193
194  if has('float')
195    let thefloat: float
196    assert_equal(0.0, thefloat)
197  endif
198
199  let thestring: string
200  assert_equal('', thestring)
201
202  let theblob: blob
203  assert_equal(0z, theblob)
204
205  let Thefunc: func
206  assert_equal(test_null_function(), Thefunc)
207
208  let thelist: list<any>
209  assert_equal([], thelist)
210
211  let thedict: dict<any>
212  assert_equal({}, thedict)
213
214  if has('channel')
215    let thejob: job
216    assert_equal(test_null_job(), thejob)
217
218    let thechannel: channel
219    assert_equal(test_null_channel(), thechannel)
220  endif
221
222  let nr = 1234 | nr = 5678
223  assert_equal(5678, nr)
224enddef
225
226def Test_assignment_var_list()
227  let v1: string
228  let v2: string
229  let vrem: list<string>
230  [v1] = ['aaa']
231  assert_equal('aaa', v1)
232
233  [v1, v2] = ['one', 'two']
234  assert_equal('one', v1)
235  assert_equal('two', v2)
236
237  [v1, v2; vrem] = ['one', 'two']
238  assert_equal('one', v1)
239  assert_equal('two', v2)
240  assert_equal([], vrem)
241
242  [v1, v2; vrem] = ['one', 'two', 'three']
243  assert_equal('one', v1)
244  assert_equal('two', v2)
245  assert_equal(['three'], vrem)
246enddef
247
248def Mess(): string
249  v:foldstart = 123
250  return 'xxx'
251enddef
252
253def Test_assignment_failure()
254  call CheckDefFailure(['let var=234'], 'E1004:')
255  call CheckDefFailure(['let var =234'], 'E1004:')
256  call CheckDefFailure(['let var= 234'], 'E1004:')
257
258  call CheckDefFailure(['let true = 1'], 'E1034:')
259  call CheckDefFailure(['let false = 1'], 'E1034:')
260
261  call CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
262  call CheckDefExecFailure(['let a: number',
263                            '[a] = test_null_list()'], 'E1093:')
264  call CheckDefExecFailure(['let a: number',
265                            '[a] = []'], 'E1093:')
266  call CheckDefExecFailure(['let x: number',
267                            'let y: number',
268                            '[x, y] = [1]'], 'E1093:')
269  call CheckDefExecFailure(['let x: number',
270                            'let y: number',
271                            'let z: list<number>',
272                            '[x, y; z] = [1]'], 'E1093:')
273
274  call CheckDefFailure(['let somevar'], "E1022:")
275  call CheckDefFailure(['let &option'], 'E1052:')
276  call CheckDefFailure(['&g:option = 5'], 'E113:')
277
278  call CheckDefFailure(['let $VAR = 5'], 'E1065:')
279
280  call CheckDefFailure(['let @~ = 5'], 'E354:')
281  call CheckDefFailure(['let @a = 5'], 'E1066:')
282
283  call CheckDefFailure(['let g:var = 5'], 'E1016:')
284  call CheckDefFailure(['let w:var = 5'], 'E1079:')
285  call CheckDefFailure(['let b:var = 5'], 'E1078:')
286  call CheckDefFailure(['let t:var = 5'], 'E1080:')
287
288  call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
289  call CheckDefFailure(['let xnr += 4'], 'E1020:')
290
291  call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef', 'defcompile'], 'E1050:')
292
293  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
294  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
295
296  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
297  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
298
299  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
300  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
301
302  call CheckDefFailure(['let var: dict <number>'], 'E1068:')
303  call CheckDefFailure(['let var: dict<number'], 'E1009:')
304
305  call assert_fails('s/^/\=Mess()/n', 'E794:')
306  call CheckDefFailure(['let var: dict<number'], 'E1009:')
307enddef
308
309def Test_unlet()
310  g:somevar = 'yes'
311  assert_true(exists('g:somevar'))
312  unlet g:somevar
313  assert_false(exists('g:somevar'))
314  unlet! g:somevar
315
316  call CheckScriptFailure([
317        'vim9script',
318        'let svar = 123',
319        'unlet svar',
320        ], 'E1081:')
321  call CheckScriptFailure([
322        'vim9script',
323        'let svar = 123',
324        'unlet s:svar',
325        ], 'E1081:')
326  call CheckScriptFailure([
327        'vim9script',
328        'let svar = 123',
329        'def Func()',
330        '  unlet svar',
331        'enddef',
332        'defcompile',
333        ], 'E1081:')
334  call CheckScriptFailure([
335        'vim9script',
336        'let svar = 123',
337        'def Func()',
338        '  unlet s:svar',
339        'enddef',
340        'defcompile',
341        ], 'E1081:')
342
343  $ENVVAR = 'foobar'
344  assert_equal('foobar', $ENVVAR)
345  unlet $ENVVAR
346  assert_equal('', $ENVVAR)
347enddef
348
349def Test_delfunction()
350  " Check function is defined in script namespace
351  CheckScriptSuccess([
352      'vim9script',
353      'func CheckMe()',
354      '  return 123',
355      'endfunc',
356      'assert_equal(123, s:CheckMe())',
357      ])
358
359  " Check function in script namespace cannot be deleted
360  CheckScriptFailure([
361      'vim9script',
362      'func DeleteMe1()',
363      'endfunc',
364      'delfunction DeleteMe1',
365      ], 'E1084:')
366  CheckScriptFailure([
367      'vim9script',
368      'func DeleteMe2()',
369      'endfunc',
370      'def DoThat()',
371      '  delfunction DeleteMe2',
372      'enddef',
373      'DoThat()',
374      ], 'E1084:')
375  CheckScriptFailure([
376      'vim9script',
377      'def DeleteMe3()',
378      'enddef',
379      'delfunction DeleteMe3',
380      ], 'E1084:')
381  CheckScriptFailure([
382      'vim9script',
383      'def DeleteMe4()',
384      'enddef',
385      'def DoThat()',
386      '  delfunction DeleteMe4',
387      'enddef',
388      'DoThat()',
389      ], 'E1084:')
390enddef
391
392func Test_wrong_type()
393  call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
394  call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
395  call CheckDefFailure(['let var: dict<nothing>'], 'E1010:')
396  call CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:')
397
398  call CheckDefFailure(['let var: dict<number'], 'E1009:')
399  call CheckDefFailure(['let var: dict<list<number>'], 'E1009:')
400
401  call CheckDefFailure(['let var: ally'], 'E1010:')
402  call CheckDefFailure(['let var: bram'], 'E1010:')
403  call CheckDefFailure(['let var: cathy'], 'E1010:')
404  call CheckDefFailure(['let var: dom'], 'E1010:')
405  call CheckDefFailure(['let var: freddy'], 'E1010:')
406  call CheckDefFailure(['let var: john'], 'E1010:')
407  call CheckDefFailure(['let var: larry'], 'E1010:')
408  call CheckDefFailure(['let var: ned'], 'E1010:')
409  call CheckDefFailure(['let var: pam'], 'E1010:')
410  call CheckDefFailure(['let var: sam'], 'E1010:')
411  call CheckDefFailure(['let var: vim'], 'E1010:')
412
413  call CheckDefFailure(['let Ref: number', 'Ref()'], 'E1085:')
414  call CheckDefFailure(['let Ref: string', 'let res = Ref()'], 'E1085:')
415endfunc
416
417func Test_const()
418  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
419  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
420  call CheckDefFailure(['const two'], 'E1021:')
421  call CheckDefFailure(['const &option'], 'E996:')
422endfunc
423
424def Test_block()
425  let outer = 1
426  {
427    let inner = 2
428    assert_equal(1, outer)
429    assert_equal(2, inner)
430  }
431  assert_equal(1, outer)
432enddef
433
434func Test_block_failure()
435  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
436  call CheckDefFailure(['}'], 'E1025:')
437  call CheckDefFailure(['{', 'echo 1'], 'E1026:')
438endfunc
439
440def Test_cmd_modifier()
441  tab echo '0'
442  call CheckDefFailure(['5tab echo 3'], 'E16:')
443enddef
444
445def Test_try_catch()
446  let l = []
447  try # comment
448    add(l, '1')
449    throw 'wrong'
450    add(l, '2')
451  catch # comment
452    add(l, v:exception)
453  finally # comment
454    add(l, '3')
455  endtry # comment
456  assert_equal(['1', 'wrong', '3'], l)
457enddef
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  finally
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 Test_try_catch_match()
500  let seq = 'a'
501  try
502    throw 'something'
503  catch /nothing/
504    seq ..= 'x'
505  catch /some/
506    seq ..= 'b'
507  catch /asdf/
508    seq ..= 'x'
509  catch ?a\?sdf?
510    seq ..= 'y'
511  finally
512    seq ..= 'c'
513  endtry
514  assert_equal('abc', seq)
515enddef
516
517def Test_try_catch_fails()
518  call CheckDefFailure(['catch'], 'E603:')
519  call CheckDefFailure(['try', 'echo 0', 'catch','catch'], 'E1033:')
520  call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
521  call CheckDefFailure(['finally'], 'E606:')
522  call CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
523  call CheckDefFailure(['endtry'], 'E602:')
524  call CheckDefFailure(['while 1', 'endtry'], 'E170:')
525  call CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
526  call CheckDefFailure(['if 2', 'endtry'], 'E171:')
527  call CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
528
529  call CheckDefFailure(['throw'], 'E1015:')
530  call CheckDefFailure(['throw xxx'], 'E1001:')
531enddef
532
533if has('channel')
534  let someJob = test_null_job()
535
536  def FuncWithError()
537    echomsg g:someJob
538  enddef
539
540  func Test_convert_emsg_to_exception()
541    try
542      call FuncWithError()
543    catch
544      call assert_match('Vim:E908:', v:exception)
545    endtry
546  endfunc
547endif
548
549let s:export_script_lines =<< trim END
550  vim9script
551  let name: string = 'bob'
552  def Concat(arg: string): string
553    return name .. arg
554  enddef
555  g:result = Concat('bie')
556  g:localname = name
557
558  export const CONST = 1234
559  export let exported = 9876
560  export let exp_name = 'John'
561  export def Exported(): string
562    return 'Exported'
563  enddef
564END
565
566def Test_vim9_import_export()
567  let import_script_lines =<< trim END
568    vim9script
569    import {exported, Exported} from './Xexport.vim'
570    g:imported = exported
571    exported += 3
572    g:imported_added = exported
573    g:imported_func = Exported()
574
575    import {exp_name} from './Xexport.vim'
576    g:imported_name = exp_name
577    exp_name ..= ' Doe'
578    g:imported_name_appended = exp_name
579    g:imported_later = exported
580  END
581
582  writefile(import_script_lines, 'Ximport.vim')
583  writefile(s:export_script_lines, 'Xexport.vim')
584
585  source Ximport.vim
586
587  assert_equal('bobbie', g:result)
588  assert_equal('bob', g:localname)
589  assert_equal(9876, g:imported)
590  assert_equal(9879, g:imported_added)
591  assert_equal(9879, g:imported_later)
592  assert_equal('Exported', g:imported_func)
593  assert_equal('John', g:imported_name)
594  assert_equal('John Doe', g:imported_name_appended)
595  assert_false(exists('g:name'))
596
597  unlet g:result
598  unlet g:localname
599  unlet g:imported
600  unlet g:imported_added
601  unlet g:imported_later
602  unlet g:imported_func
603  unlet g:imported_name g:imported_name_appended
604  delete('Ximport.vim')
605
606  let import_in_def_lines =<< trim END
607    vim9script
608    def ImportInDef()
609      import exported from './Xexport.vim'
610      g:imported = exported
611      exported += 7
612      g:imported_added = exported
613    enddef
614    ImportInDef()
615  END
616  writefile(import_in_def_lines, 'Ximport2.vim')
617  source Ximport2.vim
618  " TODO: this should be 9879
619  assert_equal(9876, g:imported)
620  assert_equal(9883, g:imported_added)
621  unlet g:imported
622  unlet g:imported_added
623  delete('Ximport2.vim')
624
625  let import_star_as_lines =<< trim END
626    vim9script
627    import * as Export from './Xexport.vim'
628    def UseExport()
629      g:imported = Export.exported
630    enddef
631    UseExport()
632  END
633  writefile(import_star_as_lines, 'Ximport.vim')
634  source Ximport.vim
635  assert_equal(9883, g:imported)
636
637  let import_star_as_lines_no_dot =<< trim END
638    vim9script
639    import * as Export from './Xexport.vim'
640    def Func()
641      let dummy = 1
642      let imported = Export + dummy
643    enddef
644    defcompile
645  END
646  writefile(import_star_as_lines_no_dot, 'Ximport.vim')
647  assert_fails('source Ximport.vim', 'E1060:')
648
649  let import_star_as_lines_dot_space =<< trim END
650    vim9script
651    import * as Export from './Xexport.vim'
652    def Func()
653      let imported = Export . exported
654    enddef
655    defcompile
656  END
657  writefile(import_star_as_lines_dot_space, 'Ximport.vim')
658  assert_fails('source Ximport.vim', 'E1074:')
659
660  let import_star_as_lines_missing_name =<< trim END
661    vim9script
662    import * as Export from './Xexport.vim'
663    def Func()
664      let imported = Export.
665    enddef
666    defcompile
667  END
668  writefile(import_star_as_lines_missing_name, 'Ximport.vim')
669  assert_fails('source Ximport.vim', 'E1048:')
670
671  let import_star_lines =<< trim END
672    vim9script
673    import * from './Xexport.vim'
674  END
675  writefile(import_star_lines, 'Ximport.vim')
676  assert_fails('source Ximport.vim', 'E1045:')
677
678  " try to import something that exists but is not exported
679  let import_not_exported_lines =<< trim END
680    vim9script
681    import name from './Xexport.vim'
682  END
683  writefile(import_not_exported_lines, 'Ximport.vim')
684  assert_fails('source Ximport.vim', 'E1049:')
685
686  " try to import something that is already defined
687  let import_already_defined =<< trim END
688    vim9script
689    let exported = 'something'
690    import exported from './Xexport.vim'
691  END
692  writefile(import_already_defined, 'Ximport.vim')
693  assert_fails('source Ximport.vim', 'E1073:')
694
695  " try to import something that is already defined
696  import_already_defined =<< trim END
697    vim9script
698    let exported = 'something'
699    import * as exported from './Xexport.vim'
700  END
701  writefile(import_already_defined, 'Ximport.vim')
702  assert_fails('source Ximport.vim', 'E1073:')
703
704  " try to import something that is already defined
705  import_already_defined =<< trim END
706    vim9script
707    let exported = 'something'
708    import {exported} from './Xexport.vim'
709  END
710  writefile(import_already_defined, 'Ximport.vim')
711  assert_fails('source Ximport.vim', 'E1073:')
712
713  " import a very long name, requires making a copy
714  let import_long_name_lines =<< trim END
715    vim9script
716    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
717  END
718  writefile(import_long_name_lines, 'Ximport.vim')
719  assert_fails('source Ximport.vim', 'E1048:')
720
721  let import_no_from_lines =<< trim END
722    vim9script
723    import name './Xexport.vim'
724  END
725  writefile(import_no_from_lines, 'Ximport.vim')
726  assert_fails('source Ximport.vim', 'E1070:')
727
728  let import_invalid_string_lines =<< trim END
729    vim9script
730    import name from Xexport.vim
731  END
732  writefile(import_invalid_string_lines, 'Ximport.vim')
733  assert_fails('source Ximport.vim', 'E1071:')
734
735  let import_wrong_name_lines =<< trim END
736    vim9script
737    import name from './XnoExport.vim'
738  END
739  writefile(import_wrong_name_lines, 'Ximport.vim')
740  assert_fails('source Ximport.vim', 'E1053:')
741
742  let import_missing_comma_lines =<< trim END
743    vim9script
744    import {exported name} from './Xexport.vim'
745  END
746  writefile(import_missing_comma_lines, 'Ximport3.vim')
747  assert_fails('source Ximport3.vim', 'E1046:')
748
749  delete('Ximport.vim')
750  delete('Ximport3.vim')
751  delete('Xexport.vim')
752
753  " Check that in a Vim9 script 'cpo' is set to the Vim default.
754  set cpo&vi
755  let cpo_before = &cpo
756  let lines =<< trim END
757    vim9script
758    g:cpo_in_vim9script = &cpo
759  END
760  writefile(lines, 'Xvim9_script')
761  source Xvim9_script
762  assert_equal(cpo_before, &cpo)
763  set cpo&vim
764  assert_equal(&cpo, g:cpo_in_vim9script)
765  delete('Xvim9_script')
766enddef
767
768def Test_vim9script_fails()
769  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
770  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
771  CheckScriptFailure(['export let some = 123'], 'E1042:')
772  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:')
773  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
774  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
775
776  assert_fails('vim9script', 'E1038')
777  assert_fails('export something', 'E1043')
778enddef
779
780def Test_vim9script_reload_import()
781  let lines =<< trim END
782    vim9script
783    const var = ''
784    let valone = 1234
785    def MyFunc(arg: string)
786       valone = 5678
787    enddef
788  END
789  let morelines =<< trim END
790    let valtwo = 222
791    export def GetValtwo(): number
792      return valtwo
793    enddef
794  END
795  writefile(lines + morelines, 'Xreload.vim')
796  source Xreload.vim
797  source Xreload.vim
798  source Xreload.vim
799
800  let testlines =<< trim END
801    vim9script
802    def TheFunc()
803      import GetValtwo from './Xreload.vim'
804      assert_equal(222, GetValtwo())
805    enddef
806    TheFunc()
807  END
808  writefile(testlines, 'Ximport.vim')
809  source Ximport.vim
810
811  " Test that when not using "morelines" GetValtwo() and valtwo are still
812  " defined, because import doesn't reload a script.
813  writefile(lines, 'Xreload.vim')
814  source Ximport.vim
815
816  " cannot declare a var twice
817  lines =<< trim END
818    vim9script
819    let valone = 1234
820    let valone = 5678
821  END
822  writefile(lines, 'Xreload.vim')
823  assert_fails('source Xreload.vim', 'E1041:')
824
825  delete('Xreload.vim')
826  delete('Ximport.vim')
827enddef
828
829def Test_vim9script_reload_delfunc()
830  let first_lines =<< trim END
831    vim9script
832    def FuncYes(): string
833      return 'yes'
834    enddef
835  END
836  let withno_lines =<< trim END
837    def FuncNo(): string
838      return 'no'
839    enddef
840    def g:DoCheck(no_exists: bool)
841      assert_equal('yes', FuncYes())
842      assert_equal('no', FuncNo())
843    enddef
844  END
845  let nono_lines =<< trim END
846    def g:DoCheck(no_exists: bool)
847      assert_equal('yes', FuncYes())
848      assert_fails('call FuncNo()', 'E117:')
849    enddef
850  END
851
852  # FuncNo() is defined
853  writefile(first_lines + withno_lines, 'Xreloaded.vim')
854  source Xreloaded.vim
855  g:DoCheck(true)
856
857  # FuncNo() is not redefined
858  writefile(first_lines + nono_lines, 'Xreloaded.vim')
859  source Xreloaded.vim
860  g:DoCheck()
861
862  # FuncNo() is back
863  writefile(first_lines + withno_lines, 'Xreloaded.vim')
864  source Xreloaded.vim
865  g:DoCheck()
866
867  delete('Xreloaded.vim')
868enddef
869
870def Test_vim9script_reload_delvar()
871  # write the script with a script-local variable
872  let lines =<< trim END
873    vim9script
874    let var = 'string'
875  END
876  writefile(lines, 'XreloadVar.vim')
877  source XreloadVar.vim
878
879  # now write the script using the same variable locally - works
880  lines =<< trim END
881    vim9script
882    def Func()
883      let var = 'string'
884    enddef
885  END
886  writefile(lines, 'XreloadVar.vim')
887  source XreloadVar.vim
888
889  delete('XreloadVar.vim')
890enddef
891
892def Test_import_absolute()
893  let import_lines = [
894        'vim9script',
895        'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
896        'def UseExported()',
897        '  g:imported_abs = exported',
898        '  exported = 8888',
899        '  g:imported_after = exported',
900        'enddef',
901        'UseExported()',
902        'g:import_disassembled = execute("disass UseExported")',
903        ]
904  writefile(import_lines, 'Ximport_abs.vim')
905  writefile(s:export_script_lines, 'Xexport_abs.vim')
906
907  source Ximport_abs.vim
908
909  assert_equal(9876, g:imported_abs)
910  assert_equal(8888, g:imported_after)
911  assert_match('<SNR>\d\+_UseExported.*' ..
912          'g:imported_abs = exported.*' ..
913          '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
914          '1 STOREG g:imported_abs.*' ..
915          'exported = 8888.*' ..
916          '3 STORESCRIPT exported in .*Xexport_abs.vim.*' ..
917          'g:imported_after = exported.*' ..
918          '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
919          '5 STOREG g:imported_after.*',
920        g:import_disassembled)
921  unlet g:imported_abs
922  unlet g:import_disassembled
923
924  delete('Ximport_abs.vim')
925  delete('Xexport_abs.vim')
926enddef
927
928def Test_import_rtp()
929  let import_lines = [
930        'vim9script',
931        'import exported from "Xexport_rtp.vim"',
932        'g:imported_rtp = exported',
933        ]
934  writefile(import_lines, 'Ximport_rtp.vim')
935  mkdir('import')
936  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
937
938  let save_rtp = &rtp
939  &rtp = getcwd()
940  source Ximport_rtp.vim
941  &rtp = save_rtp
942
943  assert_equal(9876, g:imported_rtp)
944  unlet g:imported_rtp
945
946  delete('Ximport_rtp.vim')
947  delete('import', 'rf')
948enddef
949
950def Test_import_compile_error()
951  let export_lines = [
952        'vim9script',
953        'export def ExpFunc(): string',
954        '  return notDefined',
955        'enddef',
956        ]
957  writefile(export_lines, 'Xexported.vim')
958
959  let import_lines = [
960        'vim9script',
961        'import ExpFunc from "./Xexported.vim"',
962        'def ImpFunc()',
963        '  echo ExpFunc()',
964        'enddef',
965        'defcompile',
966        ]
967  writefile(import_lines, 'Ximport.vim')
968
969  try
970    source Ximport.vim
971  catch /E1001/
972    " Error should be fore the Xexported.vim file.
973    assert_match('E1001: variable not found: notDefined', v:exception)
974    assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint)
975  endtry
976
977  delete('Xexported.vim')
978  delete('Ximport.vim')
979enddef
980
981def Test_fixed_size_list()
982  " will be allocated as one piece of memory, check that changes work
983  let l = [1, 2, 3, 4]
984  l->remove(0)
985  l->add(5)
986  l->insert(99, 1)
987  assert_equal([2, 99, 3, 4, 5], l)
988enddef
989
990def IfElse(what: number): string
991  let res = ''
992  if what == 1
993    res = "one"
994  elseif what == 2
995    res = "two"
996  else
997    res = "three"
998  endif
999  return res
1000enddef
1001
1002def Test_if_elseif_else()
1003  assert_equal('one', IfElse(1))
1004  assert_equal('two', IfElse(2))
1005  assert_equal('three', IfElse(3))
1006enddef
1007
1008def Test_if_elseif_else_fails()
1009  call CheckDefFailure(['elseif true'], 'E582:')
1010  call CheckDefFailure(['else'], 'E581:')
1011  call CheckDefFailure(['endif'], 'E580:')
1012  call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
1013  call CheckDefFailure(['if true', 'echo 1'], 'E171:')
1014enddef
1015
1016let g:bool_true = v:true
1017let g:bool_false = v:false
1018
1019def Test_if_const_expr()
1020  let res = false
1021  if true ? true : false
1022    res = true
1023  endif
1024  assert_equal(true, res)
1025
1026  g:glob = 2
1027  if false
1028    execute('let g:glob = 3')
1029  endif
1030  assert_equal(2, g:glob)
1031  if true
1032    execute('let g:glob = 3')
1033  endif
1034  assert_equal(3, g:glob)
1035
1036  res = false
1037  if g:bool_true ? true : false
1038    res = true
1039  endif
1040  assert_equal(true, res)
1041
1042  res = false
1043  if true ? g:bool_true : false
1044    res = true
1045  endif
1046  assert_equal(true, res)
1047
1048  res = false
1049  if true ? true : g:bool_false
1050    res = true
1051  endif
1052  assert_equal(true, res)
1053
1054  res = false
1055  if true ? false : true
1056    res = true
1057  endif
1058  assert_equal(false, res)
1059
1060  res = false
1061  if false ? false : true
1062    res = true
1063  endif
1064  assert_equal(true, res)
1065
1066  res = false
1067  if false ? true : false
1068    res = true
1069  endif
1070  assert_equal(false, res)
1071
1072  res = false
1073  if has('xyz') ? true : false
1074    res = true
1075  endif
1076  assert_equal(false, res)
1077
1078  res = false
1079  if true && true
1080    res = true
1081  endif
1082  assert_equal(true, res)
1083
1084  res = false
1085  if true && false
1086    res = true
1087  endif
1088  assert_equal(false, res)
1089
1090  res = false
1091  if g:bool_true && false
1092    res = true
1093  endif
1094  assert_equal(false, res)
1095
1096  res = false
1097  if true && g:bool_false
1098    res = true
1099  endif
1100  assert_equal(false, res)
1101
1102  res = false
1103  if false && false
1104    res = true
1105  endif
1106  assert_equal(false, res)
1107
1108  res = false
1109  if true || false
1110    res = true
1111  endif
1112  assert_equal(true, res)
1113
1114  res = false
1115  if g:bool_true || false
1116    res = true
1117  endif
1118  assert_equal(true, res)
1119
1120  res = false
1121  if true || g:bool_false
1122    res = true
1123  endif
1124  assert_equal(true, res)
1125
1126  res = false
1127  if false || false
1128    res = true
1129  endif
1130  assert_equal(false, res)
1131enddef
1132
1133def Test_if_const_expr_fails()
1134  call CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
1135  call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
1136  call CheckDefFailure(["if has('aaa'"], 'E110:')
1137  call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
1138enddef
1139
1140def Test_execute_cmd()
1141  new
1142  setline(1, 'default')
1143  execute 'call setline(1, "execute-string")'
1144  assert_equal('execute-string', getline(1))
1145
1146  execute "call setline(1, 'execute-string')"
1147  assert_equal('execute-string', getline(1))
1148
1149  let cmd1 = 'call setline(1,'
1150  let cmd2 = '"execute-var")'
1151  execute cmd1 cmd2 # comment
1152  assert_equal('execute-var', getline(1))
1153
1154  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
1155  assert_equal('execute-var-string', getline(1))
1156
1157  let cmd_first = 'call '
1158  let cmd_last = 'setline(1, "execute-var-var")'
1159  execute cmd_first .. cmd_last
1160  assert_equal('execute-var-var', getline(1))
1161  bwipe!
1162
1163  call CheckDefFailure(['execute xxx'], 'E1001:')
1164  call CheckDefFailure(['execute "cmd"# comment'], 'E488:')
1165enddef
1166
1167def Test_echo_cmd()
1168  echo 'some' # comment
1169  echon 'thing'
1170  assert_match('^something$', Screenline(&lines))
1171
1172  echo "some" # comment
1173  echon "thing"
1174  assert_match('^something$', Screenline(&lines))
1175
1176  let str1 = 'some'
1177  let str2 = 'more'
1178  echo str1 str2
1179  assert_match('^some more$', Screenline(&lines))
1180
1181  call CheckDefFailure(['echo "xxx"# comment'], 'E488:')
1182enddef
1183
1184def Test_echomsg_cmd()
1185  echomsg 'some' 'more' # comment
1186  assert_match('^some more$', Screenline(&lines))
1187  echo 'clear'
1188  1messages
1189  assert_match('^some more$', Screenline(&lines))
1190
1191  call CheckDefFailure(['echomsg "xxx"# comment'], 'E488:')
1192enddef
1193
1194def Test_echoerr_cmd()
1195  try
1196    echoerr 'something' 'wrong' # comment
1197  catch
1198    assert_match('something wrong', v:exception)
1199  endtry
1200enddef
1201
1202def Test_for_outside_of_function()
1203  let lines =<< trim END
1204    vim9script
1205    new
1206    for var in range(0, 3)
1207      append(line('$'), var)
1208    endfor
1209    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
1210    bwipe!
1211  END
1212  writefile(lines, 'Xvim9for.vim')
1213  source Xvim9for.vim
1214  delete('Xvim9for.vim')
1215enddef
1216
1217def Test_for_loop()
1218  let result = ''
1219  for cnt in range(7)
1220    if cnt == 4
1221      break
1222    endif
1223    if cnt == 2
1224      continue
1225    endif
1226    result ..= cnt .. '_'
1227  endfor
1228  assert_equal('0_1_3_', result)
1229enddef
1230
1231def Test_for_loop_fails()
1232  CheckDefFailure(['for # in range(5)'], 'E690:')
1233  CheckDefFailure(['for i In range(5)'], 'E690:')
1234  CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
1235  CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:')
1236  CheckDefFailure(['for i in "text"'], 'E1024:')
1237  CheckDefFailure(['for i in xxx'], 'E1001:')
1238  CheckDefFailure(['endfor'], 'E588:')
1239  CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
1240enddef
1241
1242def Test_while_loop()
1243  let result = ''
1244  let cnt = 0
1245  while cnt < 555
1246    if cnt == 3
1247      break
1248    endif
1249    cnt += 1
1250    if cnt == 2
1251      continue
1252    endif
1253    result ..= cnt .. '_'
1254  endwhile
1255  assert_equal('1_3_', result)
1256enddef
1257
1258def Test_while_loop_fails()
1259  CheckDefFailure(['while xxx'], 'E1001:')
1260  CheckDefFailure(['endwhile'], 'E588:')
1261  CheckDefFailure(['continue'], 'E586:')
1262  CheckDefFailure(['if true', 'continue'], 'E586:')
1263  CheckDefFailure(['break'], 'E587:')
1264  CheckDefFailure(['if true', 'break'], 'E587:')
1265  CheckDefFailure(['while 1', 'echo 3'], 'E170:')
1266enddef
1267
1268def Test_interrupt_loop()
1269  let caught = false
1270  let x = 0
1271  try
1272    while 1
1273      x += 1
1274      if x == 100
1275        feedkeys("\<C-C>", 'Lt')
1276      endif
1277    endwhile
1278  catch
1279    caught = true
1280    assert_equal(100, x)
1281  endtry
1282  assert_true(caught, 'should have caught an exception')
1283enddef
1284
1285def Test_automatic_line_continuation()
1286  let mylist = [
1287      'one',
1288      'two',
1289      'three',
1290      ] " comment
1291  assert_equal(['one', 'two', 'three'], mylist)
1292
1293  let mydict = {
1294      'one': 1,
1295      'two': 2,
1296      'three':
1297          3,
1298      } " comment
1299  assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
1300  mydict = #{
1301      one: 1,  # comment
1302      two:     # comment
1303           2,  # comment
1304      three: 3 # comment
1305      }
1306  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
1307  mydict = #{
1308      one: 1,
1309      two:
1310           2,
1311      three: 3
1312      }
1313  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
1314
1315  assert_equal(
1316        ['one', 'two', 'three'],
1317        split('one two three')
1318        )
1319enddef
1320
1321def Test_vim9_comment()
1322  CheckScriptSuccess([
1323      'vim9script',
1324      '# something',
1325      ])
1326  CheckScriptFailure([
1327      'vim9script',
1328      ':# something',
1329      ], 'E488:')
1330  CheckScriptFailure([
1331      '# something',
1332      ], 'E488:')
1333  CheckScriptFailure([
1334      ':# something',
1335      ], 'E488:')
1336
1337  { # block start
1338  } # block end
1339  CheckDefFailure([
1340      '{# comment',
1341      ], 'E488:')
1342  CheckDefFailure([
1343      '{',
1344      '}# comment',
1345      ], 'E488:')
1346
1347  echo "yes" # comment
1348  CheckDefFailure([
1349      'echo "yes"# comment',
1350      ], 'E488:')
1351  CheckScriptSuccess([
1352      'vim9script',
1353      'echo "yes" # something',
1354      ])
1355  CheckScriptFailure([
1356      'vim9script',
1357      'echo "yes"# something',
1358      ], 'E121:')
1359  CheckScriptFailure([
1360      'vim9script',
1361      'echo# something',
1362      ], 'E121:')
1363  CheckScriptFailure([
1364      'echo "yes" # something',
1365      ], 'E121:')
1366
1367  exe "echo" # comment
1368  CheckDefFailure([
1369      'exe "echo"# comment',
1370      ], 'E488:')
1371  CheckScriptSuccess([
1372      'vim9script',
1373      'exe "echo" # something',
1374      ])
1375  CheckScriptFailure([
1376      'vim9script',
1377      'exe "echo"# something',
1378      ], 'E121:')
1379  CheckDefFailure([
1380      'exe # comment',
1381      ], 'E1015:')
1382  CheckScriptFailure([
1383      'vim9script',
1384      'exe# something',
1385      ], 'E121:')
1386  CheckScriptFailure([
1387      'exe "echo" # something',
1388      ], 'E121:')
1389
1390  CheckDefFailure([
1391      'try# comment',
1392      '  echo "yes"',
1393      'catch',
1394      'endtry',
1395      ], 'E488:')
1396  CheckScriptFailure([
1397      'vim9script',
1398      'try# comment',
1399      'echo "yes"',
1400      ], 'E488:')
1401  CheckDefFailure([
1402      'try',
1403      '  throw#comment',
1404      'catch',
1405      'endtry',
1406      ], 'E1015:')
1407  CheckDefFailure([
1408      'try',
1409      '  throw "yes"#comment',
1410      'catch',
1411      'endtry',
1412      ], 'E488:')
1413  CheckDefFailure([
1414      'try',
1415      '  echo "yes"',
1416      'catch# comment',
1417      'endtry',
1418      ], 'E488:')
1419  CheckScriptFailure([
1420      'vim9script',
1421      'try',
1422      '  echo "yes"',
1423      'catch# comment',
1424      'endtry',
1425      ], 'E654:')
1426  CheckDefFailure([
1427      'try',
1428      '  echo "yes"',
1429      'catch /pat/# comment',
1430      'endtry',
1431      ], 'E488:')
1432  CheckDefFailure([
1433      'try',
1434      'echo "yes"',
1435      'catch',
1436      'endtry# comment',
1437      ], 'E488:')
1438  CheckScriptFailure([
1439      'vim9script',
1440      'try',
1441      '  echo "yes"',
1442      'catch',
1443      'endtry# comment',
1444      ], 'E600:')
1445
1446  CheckScriptSuccess([
1447      'vim9script',
1448      'hi # comment',
1449      ])
1450  CheckScriptFailure([
1451      'vim9script',
1452      'hi# comment',
1453      ], 'E416:')
1454  CheckScriptSuccess([
1455      'vim9script',
1456      'hi Search # comment',
1457      ])
1458  CheckScriptFailure([
1459      'vim9script',
1460      'hi Search# comment',
1461      ], 'E416:')
1462  CheckScriptSuccess([
1463      'vim9script',
1464      'hi link This Search # comment',
1465      ])
1466  CheckScriptFailure([
1467      'vim9script',
1468      'hi link This That# comment',
1469      ], 'E413:')
1470  CheckScriptSuccess([
1471      'vim9script',
1472      'hi clear This # comment',
1473      'hi clear # comment',
1474      ])
1475  " not tested, because it doesn't give an error but a warning:
1476  " hi clear This# comment',
1477  CheckScriptFailure([
1478      'vim9script',
1479      'hi clear# comment',
1480      ], 'E416:')
1481
1482  CheckScriptSuccess([
1483      'vim9script',
1484      'hi Group term=bold',
1485      'match Group /todo/ # comment',
1486      ])
1487  CheckScriptFailure([
1488      'vim9script',
1489      'hi Group term=bold',
1490      'match Group /todo/# comment',
1491      ], 'E488:')
1492  CheckScriptSuccess([
1493      'vim9script',
1494      'match # comment',
1495      ])
1496  CheckScriptFailure([
1497      'vim9script',
1498      'match# comment',
1499      ], 'E475:')
1500  CheckScriptSuccess([
1501      'vim9script',
1502      'match none # comment',
1503      ])
1504  CheckScriptFailure([
1505      'vim9script',
1506      'match none# comment',
1507      ], 'E475:')
1508
1509  CheckScriptSuccess([
1510      'vim9script',
1511      'menutrans clear # comment',
1512      ])
1513  CheckScriptFailure([
1514      'vim9script',
1515      'menutrans clear# comment text',
1516      ], 'E474:')
1517
1518  CheckScriptSuccess([
1519      'vim9script',
1520      'syntax clear # comment',
1521      ])
1522  CheckScriptFailure([
1523      'vim9script',
1524      'syntax clear# comment text',
1525      ], 'E28:')
1526  CheckScriptSuccess([
1527      'vim9script',
1528      'syntax keyword Word some',
1529      'syntax clear Word # comment',
1530      ])
1531  CheckScriptFailure([
1532      'vim9script',
1533      'syntax keyword Word some',
1534      'syntax clear Word# comment text',
1535      ], 'E28:')
1536
1537  CheckScriptSuccess([
1538      'vim9script',
1539      'syntax list # comment',
1540      ])
1541  CheckScriptFailure([
1542      'vim9script',
1543      'syntax list# comment text',
1544      ], 'E28:')
1545
1546  CheckScriptSuccess([
1547      'vim9script',
1548      'syntax match Word /pat/ oneline # comment',
1549      ])
1550  CheckScriptFailure([
1551      'vim9script',
1552      'syntax match Word /pat/ oneline# comment',
1553      ], 'E475:')
1554
1555  CheckScriptSuccess([
1556      'vim9script',
1557      'syntax keyword Word word # comm[ent',
1558      ])
1559  CheckScriptFailure([
1560      'vim9script',
1561      'syntax keyword Word word# comm[ent',
1562      ], 'E789:')
1563
1564  CheckScriptSuccess([
1565      'vim9script',
1566      'syntax match Word /pat/ # comment',
1567      ])
1568  CheckScriptFailure([
1569      'vim9script',
1570      'syntax match Word /pat/# comment',
1571      ], 'E402:')
1572
1573  CheckScriptSuccess([
1574      'vim9script',
1575      'syntax match Word /pat/ contains=Something # comment',
1576      ])
1577  CheckScriptFailure([
1578      'vim9script',
1579      'syntax match Word /pat/ contains=Something# comment',
1580      ], 'E475:')
1581  CheckScriptFailure([
1582      'vim9script',
1583      'syntax match Word /pat/ contains= # comment',
1584      ], 'E406:')
1585  CheckScriptFailure([
1586      'vim9script',
1587      'syntax match Word /pat/ contains=# comment',
1588      ], 'E475:')
1589
1590  CheckScriptSuccess([
1591      'vim9script',
1592      'syntax region Word start=/pat/ end=/pat/ # comment',
1593      ])
1594  CheckScriptFailure([
1595      'vim9script',
1596      'syntax region Word start=/pat/ end=/pat/# comment',
1597      ], 'E475:')
1598
1599  CheckScriptSuccess([
1600      'vim9script',
1601      'syntax sync # comment',
1602      ])
1603  CheckScriptFailure([
1604      'vim9script',
1605      'syntax sync# comment',
1606      ], 'E404:')
1607  CheckScriptSuccess([
1608      'vim9script',
1609      'syntax sync ccomment # comment',
1610      ])
1611  CheckScriptFailure([
1612      'vim9script',
1613      'syntax sync ccomment# comment',
1614      ], 'E404:')
1615
1616  CheckScriptSuccess([
1617      'vim9script',
1618      'syntax cluster Some contains=Word # comment',
1619      ])
1620  CheckScriptFailure([
1621      'vim9script',
1622      'syntax cluster Some contains=Word# comment',
1623      ], 'E475:')
1624
1625  CheckScriptSuccess([
1626      'vim9script',
1627      'command Echo echo # comment',
1628      'command Echo # comment',
1629      ])
1630  CheckScriptFailure([
1631      'vim9script',
1632      'command Echo echo# comment',
1633      'Echo',
1634      ], 'E121:')
1635  CheckScriptFailure([
1636      'vim9script',
1637      'command Echo# comment',
1638      ], 'E182:')
1639  CheckScriptFailure([
1640      'vim9script',
1641      'command Echo echo',
1642      'command Echo# comment',
1643      ], 'E182:')
1644
1645  CheckScriptSuccess([
1646      'vim9script',
1647      'function # comment',
1648      ])
1649  CheckScriptFailure([
1650      'vim9script',
1651      'function# comment',
1652      ], 'E129:')
1653  CheckScriptSuccess([
1654      'vim9script',
1655      'function CheckScriptSuccess # comment',
1656      ])
1657  CheckScriptFailure([
1658      'vim9script',
1659      'function CheckScriptSuccess# comment',
1660      ], 'E488:')
1661
1662  CheckScriptSuccess([
1663      'vim9script',
1664      'func g:DeleteMeA()',
1665      'endfunc',
1666      'delfunction g:DeleteMeA # comment',
1667      ])
1668  CheckScriptFailure([
1669      'vim9script',
1670      'func g:DeleteMeB()',
1671      'endfunc',
1672      'delfunction g:DeleteMeB# comment',
1673      ], 'E488:')
1674
1675  CheckScriptSuccess([
1676      'vim9script',
1677      'call execute("ls") # comment',
1678      ])
1679  CheckScriptFailure([
1680      'vim9script',
1681      'call execute("ls")# comment',
1682      ], 'E488:')
1683enddef
1684
1685def Test_vim9_comment_gui()
1686  CheckCanRunGui
1687
1688  CheckScriptFailure([
1689      'vim9script',
1690      'gui#comment'
1691      ], 'E499:')
1692  CheckScriptFailure([
1693      'vim9script',
1694      'gui -f#comment'
1695      ], 'E499:')
1696enddef
1697
1698def Test_vim9_comment_not_compiled()
1699  au TabEnter *.vim let g:entered = 1
1700  au TabEnter *.x let g:entered = 2
1701
1702  edit test.vim
1703  doautocmd TabEnter #comment
1704  assert_equal(1, g:entered)
1705
1706  doautocmd TabEnter f.x
1707  assert_equal(2, g:entered)
1708
1709  g:entered = 0
1710  doautocmd TabEnter f.x #comment
1711  assert_equal(2, g:entered)
1712
1713  assert_fails('doautocmd Syntax#comment', 'E216:')
1714
1715  au! TabEnter
1716  unlet g:entered
1717
1718  CheckScriptSuccess([
1719      'vim9script',
1720      'let g:var = 123',
1721      'let w:var = 777',
1722      'unlet g:var w:var # something',
1723      ])
1724
1725  CheckScriptFailure([
1726      'vim9script',
1727      'let g:var = 123',
1728      'unlet g:var# comment1',
1729      ], 'E108:')
1730
1731  CheckScriptFailure([
1732      'let g:var = 123',
1733      'unlet g:var # something',
1734      ], 'E488:')
1735
1736  CheckScriptSuccess([
1737      'vim9script',
1738      'if 1 # comment2',
1739      '  echo "yes"',
1740      'elseif 2 #comment',
1741      '  echo "no"',
1742      'endif',
1743      ])
1744
1745  CheckScriptFailure([
1746      'vim9script',
1747      'if 1# comment3',
1748      '  echo "yes"',
1749      'endif',
1750      ], 'E15:')
1751
1752  CheckScriptFailure([
1753      'vim9script',
1754      'if 0 # comment4',
1755      '  echo "yes"',
1756      'elseif 2#comment',
1757      '  echo "no"',
1758      'endif',
1759      ], 'E15:')
1760
1761  CheckScriptSuccess([
1762      'vim9script',
1763      'let v = 1 # comment5',
1764      ])
1765
1766  CheckScriptFailure([
1767      'vim9script',
1768      'let v = 1# comment6',
1769      ], 'E15:')
1770
1771  CheckScriptSuccess([
1772      'vim9script',
1773      'new'
1774      'call setline(1, ["# define pat", "last"])',
1775      '$',
1776      'dsearch /pat/ #comment',
1777      'bwipe!',
1778      ])
1779
1780  CheckScriptFailure([
1781      'vim9script',
1782      'new'
1783      'call setline(1, ["# define pat", "last"])',
1784      '$',
1785      'dsearch /pat/#comment',
1786      'bwipe!',
1787      ], 'E488:')
1788
1789  CheckScriptFailure([
1790      'vim9script',
1791      'func! SomeFunc()',
1792      ], 'E477:')
1793enddef
1794
1795def Test_finish()
1796  let lines =<< trim END
1797    vim9script
1798    let g:res = 'one'
1799    if v:false | finish | endif
1800    let g:res = 'two'
1801    finish
1802    let g:res = 'three'
1803  END
1804  writefile(lines, 'Xfinished')
1805  source Xfinished
1806  assert_equal('two', g:res)
1807
1808  unlet g:res
1809  delete('Xfinished')
1810enddef
1811
1812def Test_let_func_call()
1813  let lines =<< trim END
1814    vim9script
1815    func GetValue()
1816      if exists('g:count')
1817        let g:count += 1
1818      else
1819        let g:count = 1
1820      endif
1821      return 'this'
1822    endfunc
1823    let val: string = GetValue()
1824    " env var is always a string
1825    let env = $TERM
1826  END
1827  writefile(lines, 'Xfinished')
1828  source Xfinished
1829  " GetValue() is not called during discovery phase
1830  assert_equal(1, g:count)
1831
1832  unlet g:count
1833  delete('Xfinished')
1834enddef
1835
1836def Test_let_missing_type()
1837  let lines =<< trim END
1838    vim9script
1839    let var = g:unknown
1840  END
1841  CheckScriptFailure(lines, 'E121:')
1842
1843  lines =<< trim END
1844    vim9script
1845    let nr: number = 123
1846    let var = nr
1847  END
1848  CheckScriptSuccess(lines)
1849enddef
1850
1851def Test_let_declaration()
1852  let lines =<< trim END
1853    vim9script
1854    let var: string
1855    g:var_uninit = var
1856    var = 'text'
1857    g:var_test = var
1858    " prefixing s: is optional
1859    s:var = 'prefixed'
1860    g:var_prefixed = s:var
1861
1862    let s:other: number
1863    other = 1234
1864    g:other_var = other
1865  END
1866  CheckScriptSuccess(lines)
1867  assert_equal('', g:var_uninit)
1868  assert_equal('text', g:var_test)
1869  assert_equal('prefixed', g:var_prefixed)
1870  assert_equal(1234, g:other_var)
1871
1872  unlet g:var_uninit
1873  unlet g:var_test
1874  unlet g:var_prefixed
1875  unlet g:other_var
1876enddef
1877
1878def Test_let_type_check()
1879  let lines =<< trim END
1880    vim9script
1881    let var: string
1882    var = 1234
1883  END
1884  CheckScriptFailure(lines, 'E1013:')
1885
1886  lines =<< trim END
1887    vim9script
1888    let var:string
1889  END
1890  CheckScriptFailure(lines, 'E1069:')
1891enddef
1892
1893def Test_forward_declaration()
1894  let lines =<< trim END
1895    vim9script
1896    def GetValue(): string
1897      return theVal
1898    enddef
1899    let theVal = 'something'
1900    g:initVal = GetValue()
1901    theVal = 'else'
1902    g:laterVal = GetValue()
1903  END
1904  writefile(lines, 'Xforward')
1905  source Xforward
1906  assert_equal('something', g:initVal)
1907  assert_equal('else', g:laterVal)
1908
1909  unlet g:initVal
1910  unlet g:laterVal
1911  delete('Xforward')
1912enddef
1913
1914def Test_source_vim9_from_legacy()
1915  let legacy_lines =<< trim END
1916    source Xvim9_script.vim
1917
1918    call assert_false(exists('local'))
1919    call assert_false(exists('exported'))
1920    call assert_false(exists('s:exported'))
1921    call assert_equal('global', global)
1922    call assert_equal('global', g:global)
1923
1924    " imported variable becomes script-local
1925    import exported from './Xvim9_script.vim'
1926    call assert_equal('exported', s:exported)
1927    call assert_false(exists('exported'))
1928
1929    " imported function becomes script-local
1930    import GetText from './Xvim9_script.vim'
1931    call assert_equal('text', s:GetText())
1932    call assert_false(exists('*GetText'))
1933  END
1934  writefile(legacy_lines, 'Xlegacy_script.vim')
1935
1936  let vim9_lines =<< trim END
1937    vim9script
1938    let local = 'local'
1939    g:global = 'global'
1940    export let exported = 'exported'
1941    export def GetText(): string
1942       return 'text'
1943    enddef
1944  END
1945  writefile(vim9_lines, 'Xvim9_script.vim')
1946
1947  source Xlegacy_script.vim
1948
1949  assert_equal('global', g:global)
1950"  unlet g:global
1951
1952  delete('Xlegacy_script.vim')
1953  delete('Xvim9_script.vim')
1954enddef
1955
1956" Keep this last, it messes up highlighting.
1957def Test_substitute_cmd()
1958  new
1959  setline(1, 'something')
1960  :substitute(some(other(
1961  assert_equal('otherthing', getline(1))
1962  bwipe!
1963
1964  " also when the context is Vim9 script
1965  let lines =<< trim END
1966    vim9script
1967    new
1968    setline(1, 'something')
1969    :substitute(some(other(
1970    assert_equal('otherthing', getline(1))
1971    bwipe!
1972  END
1973  writefile(lines, 'Xvim9lines')
1974  source Xvim9lines
1975
1976  delete('Xvim9lines')
1977enddef
1978
1979" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1980