1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source view_util.vim
5
6" Check that "lines" inside ":def" results in an "error" message.
7func CheckDefFailure(lines, error)
8  call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
9  call assert_fails('so Xdef', a:error, a:lines)
10  call delete('Xdef')
11endfunc
12
13def CheckScriptFailure(lines: list<string>, error: string)
14  writefile(lines, 'Xdef')
15  assert_fails('so Xdef', error, lines)
16  delete('Xdef')
17enddef
18
19def CheckScriptSuccess(lines: list<string>)
20  writefile(lines, 'Xdef')
21  so Xdef
22  delete('Xdef')
23enddef
24
25def Test_syntax()
26  let var = 234
27  let other: list<string> = ['asdf']
28enddef
29
30let s:appendToMe = 'xxx'
31let s:addToMe = 111
32let g:existing = 'yes'
33let g:inc_counter = 1
34let $SOME_ENV_VAR = 'some'
35
36def Test_assignment()
37  let bool1: bool = true
38  assert_equal(v:true, bool1)
39  let bool2: bool = false
40  assert_equal(v:false, bool2)
41
42  let list1: list<bool> = [false, true, false]
43  let list2: list<number> = [1, 2, 3]
44  let list3: list<string> = ['sdf', 'asdf']
45  let list4: list<any> = ['yes', true, 1234]
46  let list5: list<blob> = [0z01, 0z02]
47
48  let listS: list<string> = []
49  let listN: list<number> = []
50
51  let dict1: dict<bool> = #{one: false, two: true}
52  let dict2: dict<number> = #{one: 1, two: 2}
53  let dict3: dict<string> = #{key: 'value'}
54  let dict4: dict<any> = #{one: 1, two: '2'}
55  let dict5: dict<blob> = #{one: 0z01, tw: 0z02}
56
57  let a: number = 6
58  assert_equal(6, a)
59
60  if has('channel')
61    let chan1: channel
62    let job1: job
63    let job2: job = job_start('willfail')
64  endif
65  if has('float')
66    let float1: float = 3.4
67  endif
68  let Funky1: func
69  let Funky2: func = function('len')
70  let Party2: func = funcref('Test_syntax')
71
72  # type becomes list<any>
73  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
74  # type becomes dict<any>
75  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
76
77  g:newvar = 'new'
78  assert_equal('new', g:newvar)
79
80  assert_equal('yes', g:existing)
81  g:existing = 'no'
82  assert_equal('no', g:existing)
83
84  v:char = 'abc'
85  assert_equal('abc', v:char)
86
87  $ENVVAR = 'foobar'
88  assert_equal('foobar', $ENVVAR)
89  $ENVVAR = ''
90
91  s:appendToMe ..= 'yyy'
92  assert_equal('xxxyyy', s:appendToMe)
93  s:addToMe += 222
94  assert_equal(333, s:addToMe)
95  s:newVar = 'new'
96  assert_equal('new', s:newVar)
97
98  set ts=7
99  &ts += 1
100  assert_equal(8, &ts)
101  &ts -= 3
102  assert_equal(5, &ts)
103  &ts *= 2
104  assert_equal(10, &ts)
105  &ts /= 3
106  assert_equal(3, &ts)
107  set ts=10
108  &ts %= 4
109  assert_equal(2, &ts)
110  call CheckDefFailure(['&notex += 3'], 'E113:')
111  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
112  call CheckDefFailure(['&path += 3'], 'E1013:')
113  # test freeing ISN_STOREOPT
114  call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
115  &ts = 8
116
117  g:inc_counter += 1
118  assert_equal(2, g:inc_counter)
119
120  $SOME_ENV_VAR ..= 'more'
121  assert_equal('somemore', $SOME_ENV_VAR)
122  call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:')
123  call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:')
124
125  @a = 'areg'
126  @a ..= 'add'
127  assert_equal('aregadd', @a)
128  call CheckDefFailure(['@a += "more"'], 'E1013:')
129  call CheckDefFailure(['@a += 123'], 'E1013:')
130
131  v:errmsg = 'none'
132  v:errmsg ..= 'again'
133  assert_equal('noneagain', v:errmsg)
134  call CheckDefFailure(['v:errmsg += "more"'], 'E1013:')
135  call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
136enddef
137
138def Test_assignment_local()
139  " Test in a separated file in order not to the current buffer/window/tab is
140  " changed.
141  let script_lines: list<string> =<< trim END
142    let b:existing = 'yes'
143    let w:existing = 'yes'
144    let t:existing = 'yes'
145
146    def Test_assignment_local_internal()
147      b:newvar = 'new'
148      assert_equal('new', b:newvar)
149      assert_equal('yes', b:existing)
150      b:existing = 'no'
151      assert_equal('no', b:existing)
152
153      w:newvar = 'new'
154      assert_equal('new', w:newvar)
155      assert_equal('yes', w:existing)
156      w:existing = 'no'
157      assert_equal('no', w:existing)
158
159      t:newvar = 'new'
160      assert_equal('new', t:newvar)
161      assert_equal('yes', t:existing)
162      t:existing = 'no'
163      assert_equal('no', t:existing)
164    enddef
165    call Test_assignment_local_internal()
166  END
167  call CheckScriptSuccess(script_lines)
168enddef
169
170def Test_assignment_default()
171
172  # Test default values.
173  let thebool: bool
174  assert_equal(v:false, thebool)
175
176  let thenumber: number
177  assert_equal(0, thenumber)
178
179  if has('float')
180    let thefloat: float
181    assert_equal(0.0, thefloat)
182  endif
183
184  let thestring: string
185  assert_equal('', thestring)
186
187  let theblob: blob
188  assert_equal(0z, theblob)
189
190  let Thefunc: func
191  assert_equal(test_null_function(), Thefunc)
192
193  let thelist: list<any>
194  assert_equal([], thelist)
195
196  let thedict: dict<any>
197  assert_equal({}, thedict)
198
199  if has('channel')
200    let thejob: job
201    assert_equal(test_null_job(), thejob)
202
203    let thechannel: channel
204    assert_equal(test_null_channel(), thechannel)
205  endif
206
207  let nr = 1234 | nr = 5678
208  assert_equal(5678, nr)
209enddef
210
211def Mess(): string
212  v:foldstart = 123
213  return 'xxx'
214enddef
215
216def Test_assignment_failure()
217  call CheckDefFailure(['let var=234'], 'E1004:')
218  call CheckDefFailure(['let var =234'], 'E1004:')
219  call CheckDefFailure(['let var= 234'], 'E1004:')
220
221  call CheckDefFailure(['let true = 1'], 'E1034:')
222  call CheckDefFailure(['let false = 1'], 'E1034:')
223
224  call CheckDefFailure(['let [a; b; c] = g:list'], 'E452:')
225
226  call CheckDefFailure(['let somevar'], "E1022:")
227  call CheckDefFailure(['let &option'], 'E1052:')
228  call CheckDefFailure(['&g:option = 5'], 'E113:')
229
230  call CheckDefFailure(['let $VAR = 5'], 'E1065:')
231
232  call CheckDefFailure(['let @~ = 5'], 'E354:')
233  call CheckDefFailure(['let @a = 5'], 'E1066:')
234
235  call CheckDefFailure(['let g:var = 5'], 'E1016:')
236  call CheckDefFailure(['let w:var = 5'], 'E1079:')
237  call CheckDefFailure(['let b:var = 5'], 'E1078:')
238  call CheckDefFailure(['let t:var = 5'], 'E1080:')
239
240  call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
241  call CheckDefFailure(['let xnr += 4'], 'E1020:')
242
243  call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef'], 'E1050:')
244
245  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
246  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
247
248  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
249  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
250
251  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
252  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
253
254  call CheckDefFailure(['let var: dict <number>'], 'E1068:')
255  call CheckDefFailure(['let var: dict<number'], 'E1009:')
256
257  call assert_fails('s/^/\=Mess()/n', 'E794:')
258  call CheckDefFailure(['let var: dict<number'], 'E1009:')
259enddef
260
261def Test_unlet()
262  g:somevar = 'yes'
263  assert_true(exists('g:somevar'))
264  unlet g:somevar
265  assert_false(exists('g:somevar'))
266  unlet! g:somevar
267
268  call CheckScriptFailure([
269        'vim9script',
270        'let svar = 123',
271        'unlet svar',
272        ], 'E1081:')
273  call CheckScriptFailure([
274        'vim9script',
275        'let svar = 123',
276        'unlet s:svar',
277        ], 'E1081:')
278  call CheckScriptFailure([
279        'vim9script',
280        'let svar = 123',
281        'def Func()',
282        '  unlet svar',
283        'enddef',
284        ], 'E1081:')
285  call CheckScriptFailure([
286        'vim9script',
287        'let svar = 123',
288        'def Func()',
289        '  unlet s:svar',
290        'enddef',
291        ], 'E1081:')
292
293  $ENVVAR = 'foobar'
294  assert_equal('foobar', $ENVVAR)
295  unlet $ENVVAR
296  assert_equal('', $ENVVAR)
297enddef
298
299func Test_wrong_type()
300  call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
301  call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
302  call CheckDefFailure(['let var: dict<nothing>'], 'E1010:')
303  call CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:')
304
305  call CheckDefFailure(['let var: dict<number'], 'E1009:')
306  call CheckDefFailure(['let var: dict<list<number>'], 'E1009:')
307
308  call CheckDefFailure(['let var: ally'], 'E1010:')
309  call CheckDefFailure(['let var: bram'], 'E1010:')
310  call CheckDefFailure(['let var: cathy'], 'E1010:')
311  call CheckDefFailure(['let var: dom'], 'E1010:')
312  call CheckDefFailure(['let var: freddy'], 'E1010:')
313  call CheckDefFailure(['let var: john'], 'E1010:')
314  call CheckDefFailure(['let var: larry'], 'E1010:')
315  call CheckDefFailure(['let var: ned'], 'E1010:')
316  call CheckDefFailure(['let var: pam'], 'E1010:')
317  call CheckDefFailure(['let var: sam'], 'E1010:')
318  call CheckDefFailure(['let var: vim'], 'E1010:')
319endfunc
320
321func Test_const()
322  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
323  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
324  call CheckDefFailure(['const two'], 'E1021:')
325  call CheckDefFailure(['const &option'], 'E996:')
326endfunc
327
328def Test_block()
329  let outer = 1
330  {
331    let inner = 2
332    assert_equal(1, outer)
333    assert_equal(2, inner)
334  }
335  assert_equal(1, outer)
336enddef
337
338func Test_block_failure()
339  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
340  call CheckDefFailure(['}'], 'E1025:')
341  call CheckDefFailure(['{', 'echo 1'], 'E1026:')
342endfunc
343
344def Test_cmd_modifier()
345  tab echo '0'
346  call CheckDefFailure(['5tab echo 3'], 'E16:')
347enddef
348
349def Test_try_catch()
350  let l = []
351  try # comment
352    add(l, '1')
353    throw 'wrong'
354    add(l, '2')
355  catch # comment
356    add(l, v:exception)
357  finally # comment
358    add(l, '3')
359  endtry # comment
360  assert_equal(['1', 'wrong', '3'], l)
361enddef
362
363def ThrowFromDef()
364  throw 'getout'
365enddef
366
367func CatchInFunc()
368  try
369    call ThrowFromDef()
370  catch
371    let g:thrown_func = v:exception
372  endtry
373endfunc
374
375def CatchInDef()
376  try
377    ThrowFromDef()
378  catch
379    g:thrown_def = v:exception
380  endtry
381enddef
382
383def ReturnFinally(): string
384  try
385    return 'intry'
386  finally
387    g:in_finally = 'finally'
388  endtry
389  return 'end'
390enddef
391
392def Test_try_catch_nested()
393  CatchInFunc()
394  assert_equal('getout', g:thrown_func)
395
396  CatchInDef()
397  assert_equal('getout', g:thrown_def)
398
399  assert_equal('intry', ReturnFinally())
400  assert_equal('finally', g:in_finally)
401enddef
402
403def Test_try_catch_match()
404  let seq = 'a'
405  try
406    throw 'something'
407  catch /nothing/
408    seq ..= 'x'
409  catch /some/
410    seq ..= 'b'
411  catch /asdf/
412    seq ..= 'x'
413  catch ?a\?sdf?
414    seq ..= 'y'
415  finally
416    seq ..= 'c'
417  endtry
418  assert_equal('abc', seq)
419enddef
420
421def Test_try_catch_fails()
422  call CheckDefFailure(['catch'], 'E603:')
423  call CheckDefFailure(['try', 'echo 0', 'catch','catch'], 'E1033:')
424  call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
425  call CheckDefFailure(['finally'], 'E606:')
426  call CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
427  call CheckDefFailure(['endtry'], 'E602:')
428  call CheckDefFailure(['while 1', 'endtry'], 'E170:')
429  call CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
430  call CheckDefFailure(['if 2', 'endtry'], 'E171:')
431  call CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
432
433  call CheckDefFailure(['throw'], 'E471:')
434  call CheckDefFailure(['throw xxx'], 'E1001:')
435enddef
436
437let s:export_script_lines =<< trim END
438  vim9script
439  let name: string = 'bob'
440  def Concat(arg: string): string
441    return name .. arg
442  enddef
443  let g:result = Concat('bie')
444  let g:localname = name
445
446  export const CONST = 1234
447  export let exported = 9876
448  export let exp_name = 'John'
449  export def Exported(): string
450    return 'Exported'
451  enddef
452END
453
454def Test_vim9_import_export()
455  let import_script_lines =<< trim END
456    vim9script
457    import {exported, Exported} from './Xexport.vim'
458    g:imported = exported
459    exported += 3
460    g:imported_added = exported
461    g:imported_func = Exported()
462
463    import {exp_name} from './Xexport.vim'
464    g:imported_name = exp_name
465    exp_name ..= ' Doe'
466    g:imported_name_appended = exp_name
467    g:imported_later = exported
468  END
469
470  writefile(import_script_lines, 'Ximport.vim')
471  writefile(s:export_script_lines, 'Xexport.vim')
472
473  source Ximport.vim
474
475  assert_equal('bobbie', g:result)
476  assert_equal('bob', g:localname)
477  assert_equal(9876, g:imported)
478  assert_equal(9879, g:imported_added)
479  assert_equal(9879, g:imported_later)
480  assert_equal('Exported', g:imported_func)
481  assert_equal('John', g:imported_name)
482  assert_equal('John Doe', g:imported_name_appended)
483  assert_false(exists('g:name'))
484
485  unlet g:result
486  unlet g:localname
487  unlet g:imported
488  unlet g:imported_added
489  unlet g:imported_later
490  unlet g:imported_func
491  unlet g:imported_name g:imported_name_appended
492  delete('Ximport.vim')
493
494  let import_in_def_lines =<< trim END
495    vim9script
496    def ImportInDef()
497      import exported from './Xexport.vim'
498      g:imported = exported
499      exported += 7
500      g:imported_added = exported
501    enddef
502    ImportInDef()
503  END
504  writefile(import_in_def_lines, 'Ximport2.vim')
505  source Ximport2.vim
506  " TODO: this should be 9879
507  assert_equal(9876, g:imported)
508  assert_equal(9883, g:imported_added)
509  unlet g:imported
510  unlet g:imported_added
511  delete('Ximport2.vim')
512
513  let import_star_as_lines =<< trim END
514    vim9script
515    import * as Export from './Xexport.vim'
516    def UseExport()
517      g:imported = Export.exported
518    enddef
519    UseExport()
520  END
521  writefile(import_star_as_lines, 'Ximport.vim')
522  source Ximport.vim
523  assert_equal(9883, g:imported)
524
525  let import_star_as_lines_no_dot =<< trim END
526    vim9script
527    import * as Export from './Xexport.vim'
528    def Func()
529      let dummy = 1
530      let imported = Export + dummy
531    enddef
532  END
533  writefile(import_star_as_lines_no_dot, 'Ximport.vim')
534  assert_fails('source Ximport.vim', 'E1060:')
535
536  let import_star_as_lines_dot_space =<< trim END
537    vim9script
538    import * as Export from './Xexport.vim'
539    def Func()
540      let imported = Export . exported
541    enddef
542  END
543  writefile(import_star_as_lines_dot_space, 'Ximport.vim')
544  assert_fails('source Ximport.vim', 'E1074:')
545
546  let import_star_as_lines_missing_name =<< trim END
547    vim9script
548    import * as Export from './Xexport.vim'
549    def Func()
550      let imported = Export.
551    enddef
552  END
553  writefile(import_star_as_lines_missing_name, 'Ximport.vim')
554  assert_fails('source Ximport.vim', 'E1048:')
555
556  let import_star_lines =<< trim END
557    vim9script
558    import * from './Xexport.vim'
559    g:imported = exported
560  END
561  writefile(import_star_lines, 'Ximport.vim')
562  assert_fails('source Ximport.vim', 'E1045:')
563
564  " try to import something that exists but is not exported
565  let import_not_exported_lines =<< trim END
566    vim9script
567    import name from './Xexport.vim'
568  END
569  writefile(import_not_exported_lines, 'Ximport.vim')
570  assert_fails('source Ximport.vim', 'E1049:')
571
572  " try to import something that is already defined
573  let import_already_defined =<< trim END
574    vim9script
575    let exported = 'something'
576    import exported from './Xexport.vim'
577  END
578  writefile(import_already_defined, 'Ximport.vim')
579  assert_fails('source Ximport.vim', 'E1073:')
580
581  " try to import something that is already defined
582  import_already_defined =<< trim END
583    vim9script
584    let exported = 'something'
585    import * as exported from './Xexport.vim'
586  END
587  writefile(import_already_defined, 'Ximport.vim')
588  assert_fails('source Ximport.vim', 'E1073:')
589
590  " try to import something that is already defined
591  import_already_defined =<< trim END
592    vim9script
593    let exported = 'something'
594    import {exported} from './Xexport.vim'
595  END
596  writefile(import_already_defined, 'Ximport.vim')
597  assert_fails('source Ximport.vim', 'E1073:')
598
599  " import a very long name, requires making a copy
600  let import_long_name_lines =<< trim END
601    vim9script
602    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
603  END
604  writefile(import_long_name_lines, 'Ximport.vim')
605  assert_fails('source Ximport.vim', 'E1048:')
606
607  let import_no_from_lines =<< trim END
608    vim9script
609    import name './Xexport.vim'
610  END
611  writefile(import_no_from_lines, 'Ximport.vim')
612  assert_fails('source Ximport.vim', 'E1070:')
613
614  let import_invalid_string_lines =<< trim END
615    vim9script
616    import name from Xexport.vim
617  END
618  writefile(import_invalid_string_lines, 'Ximport.vim')
619  assert_fails('source Ximport.vim', 'E1071:')
620
621  let import_wrong_name_lines =<< trim END
622    vim9script
623    import name from './XnoExport.vim'
624  END
625  writefile(import_wrong_name_lines, 'Ximport.vim')
626  assert_fails('source Ximport.vim', 'E1053:')
627
628  let import_missing_comma_lines =<< trim END
629    vim9script
630    import {exported name} from './Xexport.vim'
631  END
632  writefile(import_missing_comma_lines, 'Ximport3.vim')
633  assert_fails('source Ximport3.vim', 'E1046:')
634
635  delete('Ximport.vim')
636  delete('Ximport3.vim')
637  delete('Xexport.vim')
638
639  " Check that in a Vim9 script 'cpo' is set to the Vim default.
640  set cpo&vi
641  let cpo_before = &cpo
642  let lines =<< trim END
643    vim9script
644    g:cpo_in_vim9script = &cpo
645  END
646  writefile(lines, 'Xvim9_script')
647  source Xvim9_script
648  assert_equal(cpo_before, &cpo)
649  set cpo&vim
650  assert_equal(&cpo, g:cpo_in_vim9script)
651  delete('Xvim9_script')
652enddef
653
654def Test_vim9script_fails()
655  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
656  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
657  CheckScriptFailure(['export let some = 123'], 'E1042:')
658  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
659  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
660  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
661
662  assert_fails('vim9script', 'E1038')
663  assert_fails('export something', 'E1043')
664enddef
665
666def Test_vim9script_reload()
667  let lines =<< trim END
668    vim9script
669    const var = ''
670    let valone = 1234
671    def MyFunc(arg: string)
672       valone = 5678
673    enddef
674  END
675  let morelines =<< trim END
676    let valtwo = 222
677    export def GetValtwo(): number
678      return valtwo
679    enddef
680  END
681  writefile(lines + morelines,
682            'Xreload.vim')
683  source Xreload.vim
684  source Xreload.vim
685  source Xreload.vim
686
687  let testlines =<< trim END
688    vim9script
689    def TheFunc()
690      import GetValtwo from './Xreload.vim'
691      assert_equal(222, GetValtwo())
692    enddef
693    TheFunc()
694  END
695  writefile(testlines, 'Ximport.vim')
696  source Ximport.vim
697
698  " test that when not using "morelines" valtwo is still defined
699  " need to source Xreload.vim again, import doesn't reload a script
700  writefile(lines, 'Xreload.vim')
701  source Xreload.vim
702  source Ximport.vim
703
704  " cannot declare a var twice
705  lines =<< trim END
706    vim9script
707    let valone = 1234
708    let valone = 5678
709  END
710  writefile(lines, 'Xreload.vim')
711  assert_fails('source Xreload.vim', 'E1041:')
712
713  delete('Xreload.vim')
714  delete('Ximport.vim')
715enddef
716
717def Test_import_absolute()
718  let import_lines = [
719        'vim9script',
720        'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
721        'def UseExported()',
722        '  g:imported_abs = exported',
723        '  exported = 8888',
724        '  g:imported_after = exported',
725        'enddef',
726        'UseExported()',
727        'g:import_disassembled = execute("disass UseExported")',
728        ]
729  writefile(import_lines, 'Ximport_abs.vim')
730  writefile(s:export_script_lines, 'Xexport_abs.vim')
731
732  source Ximport_abs.vim
733
734  assert_equal(9876, g:imported_abs)
735  assert_equal(8888, g:imported_after)
736  assert_match('<SNR>\d\+_UseExported.*' ..
737          'g:imported_abs = exported.*' ..
738          '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
739          '1 STOREG g:imported_abs.*' ..
740          'exported = 8888.*' ..
741          '3 STORESCRIPT exported in .*Xexport_abs.vim.*' ..
742          'g:imported_after = exported.*' ..
743          '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' ..
744          '5 STOREG g:imported_after.*',
745        g:import_disassembled)
746  unlet g:imported_abs
747  unlet g:import_disassembled
748
749  delete('Ximport_abs.vim')
750  delete('Xexport_abs.vim')
751enddef
752
753def Test_import_rtp()
754  let import_lines = [
755        'vim9script',
756        'import exported from "Xexport_rtp.vim"',
757        'g:imported_rtp = exported',
758        ]
759  writefile(import_lines, 'Ximport_rtp.vim')
760  mkdir('import')
761  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
762
763  let save_rtp = &rtp
764  &rtp = getcwd()
765  source Ximport_rtp.vim
766  &rtp = save_rtp
767
768  assert_equal(9876, g:imported_rtp)
769  unlet g:imported_rtp
770
771  delete('Ximport_rtp.vim')
772  delete('import/Xexport_rtp.vim')
773  delete('import', 'd')
774enddef
775
776def Test_fixed_size_list()
777  " will be allocated as one piece of memory, check that changes work
778  let l = [1, 2, 3, 4]
779  l->remove(0)
780  l->add(5)
781  l->insert(99, 1)
782  assert_equal([2, 99, 3, 4, 5], l)
783enddef
784
785def IfElse(what: number): string
786  let res = ''
787  if what == 1
788    res = "one"
789  elseif what == 2
790    res = "two"
791  else
792    res = "three"
793  endif
794  return res
795enddef
796
797def Test_if_elseif_else()
798  assert_equal('one', IfElse(1))
799  assert_equal('two', IfElse(2))
800  assert_equal('three', IfElse(3))
801enddef
802
803def Test_if_elseif_else_fails()
804  call CheckDefFailure(['elseif true'], 'E582:')
805  call CheckDefFailure(['else'], 'E581:')
806  call CheckDefFailure(['endif'], 'E580:')
807  call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
808  call CheckDefFailure(['if true', 'echo 1'], 'E171:')
809enddef
810
811let g:bool_true = v:true
812let g:bool_false = v:false
813
814def Test_if_const_expr()
815  let res = false
816  if true ? true : false
817    res = true
818  endif
819  assert_equal(true, res)
820
821  g:glob = 2
822  if false
823    execute('let g:glob = 3')
824  endif
825  assert_equal(2, g:glob)
826  if true
827    execute('let g:glob = 3')
828  endif
829  assert_equal(3, g:glob)
830
831  res = false
832  if g:bool_true ? true : false
833    res = true
834  endif
835  assert_equal(true, res)
836
837  res = false
838  if true ? g:bool_true : false
839    res = true
840  endif
841  assert_equal(true, res)
842
843  res = false
844  if true ? true : g:bool_false
845    res = true
846  endif
847  assert_equal(true, res)
848
849  res = false
850  if true ? false : true
851    res = true
852  endif
853  assert_equal(false, res)
854
855  res = false
856  if false ? false : true
857    res = true
858  endif
859  assert_equal(true, res)
860
861  res = false
862  if false ? true : false
863    res = true
864  endif
865  assert_equal(false, res)
866
867  res = false
868  if has('xyz') ? true : false
869    res = true
870  endif
871  assert_equal(false, res)
872
873  res = false
874  if true && true
875    res = true
876  endif
877  assert_equal(true, res)
878
879  res = false
880  if true && false
881    res = true
882  endif
883  assert_equal(false, res)
884
885  res = false
886  if g:bool_true && false
887    res = true
888  endif
889  assert_equal(false, res)
890
891  res = false
892  if true && g:bool_false
893    res = true
894  endif
895  assert_equal(false, res)
896
897  res = false
898  if false && false
899    res = true
900  endif
901  assert_equal(false, res)
902
903  res = false
904  if true || false
905    res = true
906  endif
907  assert_equal(true, res)
908
909  res = false
910  if g:bool_true || false
911    res = true
912  endif
913  assert_equal(true, res)
914
915  res = false
916  if true || g:bool_false
917    res = true
918  endif
919  assert_equal(true, res)
920
921  res = false
922  if false || false
923    res = true
924  endif
925  assert_equal(false, res)
926enddef
927
928def Test_if_const_expr_fails()
929  call CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
930  call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
931  call CheckDefFailure(["if has('aaa'"], 'E110:')
932  call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
933enddef
934
935def Test_execute_cmd()
936  new
937  setline(1, 'default')
938  execute 'call setline(1, "execute-string")'
939  assert_equal('execute-string', getline(1))
940  let cmd1 = 'call setline(1,'
941  let cmd2 = '"execute-var")'
942  execute cmd1 cmd2
943  assert_equal('execute-var', getline(1))
944  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
945  assert_equal('execute-var-string', getline(1))
946  let cmd_first = 'call '
947  let cmd_last = 'setline(1, "execute-var-var")'
948  execute cmd_first .. cmd_last
949  assert_equal('execute-var-var', getline(1))
950  bwipe!
951
952  call CheckDefFailure(['execute xxx'], 'E1001:')
953enddef
954
955def Test_echo_cmd()
956  echo 'some'
957  echon 'thing'
958  assert_match('^something$', Screenline(&lines))
959
960  let str1 = 'some'
961  let str2 = 'more'
962  echo str1 str2
963  assert_match('^some more$', Screenline(&lines))
964enddef
965
966def Test_for_outside_of_function()
967  let lines =<< trim END
968    vim9script
969    new
970    for var in range(0, 3)
971      append(line('$'), var)
972    endfor
973    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
974    bwipe!
975  END
976  writefile(lines, 'Xvim9for.vim')
977  source Xvim9for.vim
978  delete('Xvim9for.vim')
979enddef
980
981def Test_for_loop()
982  let result = ''
983  for cnt in range(7)
984    if cnt == 4
985      break
986    endif
987    if cnt == 2
988      continue
989    endif
990    result ..= cnt .. '_'
991  endfor
992  assert_equal('0_1_3_', result)
993enddef
994
995def Test_for_loop_fails()
996  CheckDefFailure(['for # in range(5)'], 'E690:')
997  CheckDefFailure(['for i In range(5)'], 'E690:')
998  CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
999  CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef'], 'E1006:')
1000  CheckDefFailure(['for i in "text"'], 'E1024:')
1001  CheckDefFailure(['for i in xxx'], 'E1001:')
1002  CheckDefFailure(['endfor'], 'E588:')
1003  CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
1004enddef
1005
1006def Test_while_loop()
1007  let result = ''
1008  let cnt = 0
1009  while cnt < 555
1010    if cnt == 3
1011      break
1012    endif
1013    cnt += 1
1014    if cnt == 2
1015      continue
1016    endif
1017    result ..= cnt .. '_'
1018  endwhile
1019  assert_equal('1_3_', result)
1020enddef
1021
1022def Test_while_loop_fails()
1023  CheckDefFailure(['while xxx'], 'E1001:')
1024  CheckDefFailure(['endwhile'], 'E588:')
1025  CheckDefFailure(['continue'], 'E586:')
1026  CheckDefFailure(['if true', 'continue'], 'E586:')
1027  CheckDefFailure(['break'], 'E587:')
1028  CheckDefFailure(['if true', 'break'], 'E587:')
1029  CheckDefFailure(['while 1', 'echo 3'], 'E170:')
1030enddef
1031
1032def Test_interrupt_loop()
1033  let caught = false
1034  let x = 0
1035  try
1036    while 1
1037      x += 1
1038      if x == 100
1039        feedkeys("\<C-C>", 'Lt')
1040      endif
1041    endwhile
1042  catch
1043    caught = true
1044    assert_equal(100, x)
1045  endtry
1046  assert_true(caught, 'should have caught an exception')
1047enddef
1048
1049def Test_automatic_line_continuation()
1050  let mylist = [
1051      'one',
1052      'two',
1053      'three',
1054      ] " comment
1055  assert_equal(['one', 'two', 'three'], mylist)
1056
1057  let mydict = {
1058      'one': 1,
1059      'two': 2,
1060      'three':
1061          3,
1062      } " comment
1063  assert_equal({'one': 1, 'two': 2, 'three': 3}, mydict)
1064  mydict = #{
1065      one: 1,  # comment
1066      two:     # comment
1067           2,  # comment
1068      three: 3 # comment
1069      }
1070  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
1071  mydict = #{
1072      one: 1,
1073      two:
1074           2,
1075      three: 3
1076      }
1077  assert_equal(#{one: 1, two: 2, three: 3}, mydict)
1078
1079  assert_equal(
1080        ['one', 'two', 'three'],
1081        split('one two three')
1082        )
1083enddef
1084
1085def Test_vim9_comment()
1086  CheckScriptSuccess([
1087      'vim9script',
1088      '# something',
1089      ])
1090  CheckScriptFailure([
1091      'vim9script',
1092      ':# something',
1093      ], 'E488:')
1094  CheckScriptFailure([
1095      '# something',
1096      ], 'E488:')
1097  CheckScriptFailure([
1098      ':# something',
1099      ], 'E488:')
1100
1101  { # block start
1102  } # block end
1103  CheckDefFailure([
1104      '{# comment',
1105      ], 'E488:')
1106  CheckDefFailure([
1107      '{',
1108      '}# comment',
1109      ], 'E488:')
1110
1111  echo "yes" # comment
1112  CheckDefFailure([
1113      'echo "yes"# comment',
1114      ], 'E488:')
1115  CheckScriptSuccess([
1116      'vim9script',
1117      'echo "yes" # something',
1118      ])
1119  CheckScriptFailure([
1120      'vim9script',
1121      'echo "yes"# something',
1122      ], 'E121:')
1123  CheckScriptFailure([
1124      'vim9script',
1125      'echo# something',
1126      ], 'E121:')
1127  CheckScriptFailure([
1128      'echo "yes" # something',
1129      ], 'E121:')
1130
1131  exe "echo" # comment
1132  CheckDefFailure([
1133      'exe "echo"# comment',
1134      ], 'E488:')
1135  CheckScriptSuccess([
1136      'vim9script',
1137      'exe "echo" # something',
1138      ])
1139  CheckScriptFailure([
1140      'vim9script',
1141      'exe "echo"# something',
1142      ], 'E121:')
1143  CheckDefFailure([
1144      'exe # comment',
1145      ], 'E1015:')
1146  CheckScriptFailure([
1147      'vim9script',
1148      'exe# something',
1149      ], 'E121:')
1150  CheckScriptFailure([
1151      'exe "echo" # something',
1152      ], 'E121:')
1153
1154  CheckDefFailure([
1155      'try# comment',
1156      '  echo "yes"',
1157      'catch',
1158      'endtry',
1159      ], 'E488:')
1160  CheckScriptFailure([
1161      'vim9script',
1162      'try# comment',
1163      'echo "yes"',
1164      ], 'E488:')
1165  CheckDefFailure([
1166      'try',
1167      '  echo "yes"',
1168      'catch# comment',
1169      'endtry',
1170      ], 'E488:')
1171  CheckScriptFailure([
1172      'vim9script',
1173      'try',
1174      '  echo "yes"',
1175      'catch# comment',
1176      'endtry',
1177      ], 'E654:')
1178  CheckDefFailure([
1179      'try',
1180      '  echo "yes"',
1181      'catch /pat/# comment',
1182      'endtry',
1183      ], 'E488:')
1184  CheckScriptFailure([
1185      'vim9script',
1186      'try',
1187      '  throw "pat"',
1188      'catch /pat/# comment',
1189      'endtry',
1190      ], 'E605:')
1191  CheckDefFailure([
1192      'try',
1193      'echo "yes"',
1194      'catch',
1195      'endtry# comment',
1196      ], 'E488:')
1197  CheckScriptFailure([
1198      'vim9script',
1199      'try',
1200      '  echo "yes"',
1201      'catch',
1202      'endtry# comment',
1203      ], 'E600:')
1204
1205  CheckScriptSuccess([
1206      'vim9script',
1207      'hi # comment',
1208      ])
1209  CheckScriptFailure([
1210      'vim9script',
1211      'hi# comment',
1212      ], 'E416:')
1213  CheckScriptSuccess([
1214      'vim9script',
1215      'hi Search # comment',
1216      ])
1217  CheckScriptFailure([
1218      'vim9script',
1219      'hi Search# comment',
1220      ], 'E416:')
1221  CheckScriptSuccess([
1222      'vim9script',
1223      'hi link This Search # comment',
1224      ])
1225  CheckScriptFailure([
1226      'vim9script',
1227      'hi link This That# comment',
1228      ], 'E413:')
1229  CheckScriptSuccess([
1230      'vim9script',
1231      'hi clear This # comment',
1232      'hi clear # comment',
1233      ])
1234  " not tested, because it doesn't give an error but a warning:
1235  " hi clear This# comment',
1236  CheckScriptFailure([
1237      'vim9script',
1238      'hi clear# comment',
1239      ], 'E416:')
1240
1241  CheckScriptSuccess([
1242      'vim9script',
1243      'hi Group term=bold',
1244      'match Group /todo/ # comment',
1245      ])
1246  CheckScriptFailure([
1247      'vim9script',
1248      'hi Group term=bold',
1249      'match Group /todo/# comment',
1250      ], 'E488:')
1251  CheckScriptSuccess([
1252      'vim9script',
1253      'match # comment',
1254      ])
1255  CheckScriptFailure([
1256      'vim9script',
1257      'match# comment',
1258      ], 'E475:')
1259  CheckScriptSuccess([
1260      'vim9script',
1261      'match none # comment',
1262      ])
1263  CheckScriptFailure([
1264      'vim9script',
1265      'match none# comment',
1266      ], 'E475:')
1267
1268  CheckScriptSuccess([
1269      'vim9script',
1270      'menutrans clear # comment',
1271      ])
1272  CheckScriptFailure([
1273      'vim9script',
1274      'menutrans clear# comment text',
1275      ], 'E474:')
1276
1277  CheckScriptSuccess([
1278      'vim9script',
1279      'syntax clear # comment',
1280      ])
1281  CheckScriptFailure([
1282      'vim9script',
1283      'syntax clear# comment text',
1284      ], 'E28:')
1285  CheckScriptSuccess([
1286      'vim9script',
1287      'syntax keyword Word some',
1288      'syntax clear Word # comment',
1289      ])
1290  CheckScriptFailure([
1291      'vim9script',
1292      'syntax keyword Word some',
1293      'syntax clear Word# comment text',
1294      ], 'E28:')
1295
1296  CheckScriptSuccess([
1297      'vim9script',
1298      'syntax list # comment',
1299      ])
1300  CheckScriptFailure([
1301      'vim9script',
1302      'syntax list# comment text',
1303      ], 'E28:')
1304
1305  CheckScriptSuccess([
1306      'vim9script',
1307      'syntax match Word /pat/ oneline # comment',
1308      ])
1309  CheckScriptFailure([
1310      'vim9script',
1311      'syntax match Word /pat/ oneline# comment',
1312      ], 'E475:')
1313
1314  CheckScriptSuccess([
1315      'vim9script',
1316      'syntax keyword Word word # comm[ent',
1317      ])
1318  CheckScriptFailure([
1319      'vim9script',
1320      'syntax keyword Word word# comm[ent',
1321      ], 'E789:')
1322
1323  CheckScriptSuccess([
1324      'vim9script',
1325      'syntax match Word /pat/ # comment',
1326      ])
1327  CheckScriptFailure([
1328      'vim9script',
1329      'syntax match Word /pat/# comment',
1330      ], 'E402:')
1331
1332  CheckScriptSuccess([
1333      'vim9script',
1334      'syntax match Word /pat/ contains=Something # comment',
1335      ])
1336  CheckScriptFailure([
1337      'vim9script',
1338      'syntax match Word /pat/ contains=Something# comment',
1339      ], 'E475:')
1340  CheckScriptFailure([
1341      'vim9script',
1342      'syntax match Word /pat/ contains= # comment',
1343      ], 'E406:')
1344  CheckScriptFailure([
1345      'vim9script',
1346      'syntax match Word /pat/ contains=# comment',
1347      ], 'E475:')
1348
1349  CheckScriptSuccess([
1350      'vim9script',
1351      'syntax region Word start=/pat/ end=/pat/ # comment',
1352      ])
1353  CheckScriptFailure([
1354      'vim9script',
1355      'syntax region Word start=/pat/ end=/pat/# comment',
1356      ], 'E475:')
1357
1358  CheckScriptSuccess([
1359      'vim9script',
1360      'syntax sync # comment',
1361      ])
1362  CheckScriptFailure([
1363      'vim9script',
1364      'syntax sync# comment',
1365      ], 'E404:')
1366  CheckScriptSuccess([
1367      'vim9script',
1368      'syntax sync ccomment # comment',
1369      ])
1370  CheckScriptFailure([
1371      'vim9script',
1372      'syntax sync ccomment# comment',
1373      ], 'E404:')
1374
1375  CheckScriptSuccess([
1376      'vim9script',
1377      'syntax cluster Some contains=Word # comment',
1378      ])
1379  CheckScriptFailure([
1380      'vim9script',
1381      'syntax cluster Some contains=Word# comment',
1382      ], 'E475:')
1383enddef
1384
1385def Test_vim9_comment_gui()
1386  CheckCanRunGui
1387
1388  CheckScriptFailure([
1389      'vim9script',
1390      'gui#comment'
1391      ], 'E499:')
1392  CheckScriptFailure([
1393      'vim9script',
1394      'gui -f#comment'
1395      ], 'E499:')
1396enddef
1397
1398def Test_vim9_comment_not_compiled()
1399  au TabEnter *.vim let g:entered = 1
1400  au TabEnter *.x let g:entered = 2
1401
1402  edit test.vim
1403  doautocmd TabEnter #comment
1404  assert_equal(1, g:entered)
1405
1406  doautocmd TabEnter f.x
1407  assert_equal(2, g:entered)
1408
1409  g:entered = 0
1410  doautocmd TabEnter f.x #comment
1411  assert_equal(2, g:entered)
1412
1413  assert_fails('doautocmd Syntax#comment', 'E216:')
1414
1415  au! TabEnter
1416  unlet g:entered
1417
1418  CheckScriptSuccess([
1419      'vim9script',
1420      'let g:var = 123',
1421      'let w:var = 777',
1422      'unlet g:var w:var # something',
1423      ])
1424
1425  CheckScriptFailure([
1426      'vim9script',
1427      'let g:var = 123',
1428      'unlet g:var# comment',
1429      ], 'E108:')
1430
1431  CheckScriptFailure([
1432      'let g:var = 123',
1433      'unlet g:var # something',
1434      ], 'E488:')
1435
1436  CheckScriptSuccess([
1437      'vim9script',
1438      'if 1 # comment',
1439      '  echo "yes"',
1440      'elseif 2 #comment',
1441      '  echo "no"',
1442      'endif',
1443      ])
1444
1445  CheckScriptFailure([
1446      'vim9script',
1447      'if 1# comment',
1448      '  echo "yes"',
1449      'endif',
1450      ], 'E15:')
1451
1452  CheckScriptFailure([
1453      'vim9script',
1454      'if 0 # comment',
1455      '  echo "yes"',
1456      'elseif 2#comment',
1457      '  echo "no"',
1458      'endif',
1459      ], 'E15:')
1460
1461  CheckScriptSuccess([
1462      'vim9script',
1463      'let # comment',
1464      ])
1465
1466  CheckScriptFailure([
1467      'vim9script',
1468      'let# comment',
1469      ], 'E121:')
1470
1471  CheckScriptSuccess([
1472      'vim9script',
1473      'let v:version # comment',
1474      ])
1475
1476  CheckScriptFailure([
1477      'vim9script',
1478      'let v:version# comment',
1479      ], 'E121:')
1480
1481  CheckScriptSuccess([
1482      'vim9script',
1483      'new'
1484      'call setline(1, ["# define pat", "last"])',
1485      '$',
1486      'dsearch /pat/ #comment',
1487      'bwipe!',
1488      ])
1489
1490  CheckScriptFailure([
1491      'vim9script',
1492      'new'
1493      'call setline(1, ["# define pat", "last"])',
1494      '$',
1495      'dsearch /pat/#comment',
1496      'bwipe!',
1497      ], 'E488:')
1498enddef
1499
1500" Keep this last, it messes up highlighting.
1501def Test_substitute_cmd()
1502  new
1503  setline(1, 'something')
1504  :substitute(some(other(
1505  assert_equal('otherthing', getline(1))
1506  bwipe!
1507
1508  " also when the context is Vim9 script
1509  let lines =<< trim END
1510    vim9script
1511    new
1512    setline(1, 'something')
1513    :substitute(some(other(
1514    assert_equal('otherthing', getline(1))
1515    bwipe!
1516  END
1517  writefile(lines, 'Xvim9lines')
1518  source Xvim9lines
1519
1520  delete('Xvim9lines')
1521enddef
1522
1523" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1524