1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source term_util.vim
5source view_util.vim
6source vim9.vim
7source screendump.vim
8
9func Test_def_basic()
10  def SomeFunc(): string
11    return 'yes'
12  enddef
13  call SomeFunc()->assert_equal('yes')
14endfunc
15
16def ReturnString(): string
17  return 'string'
18enddef
19
20def ReturnNumber(): number
21  return 123
22enddef
23
24let g:notNumber = 'string'
25
26def ReturnGlobal(): number
27  return g:notNumber
28enddef
29
30def Test_return_something()
31  ReturnString()->assert_equal('string')
32  ReturnNumber()->assert_equal(123)
33  assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
34enddef
35
36def Test_missing_return()
37  CheckDefFailure(['def Missing(): number',
38                   '  if g:cond',
39                   '    echo "no return"',
40                   '  else',
41                   '    return 0',
42                   '  endif'
43                   'enddef'], 'E1027:')
44  CheckDefFailure(['def Missing(): number',
45                   '  if g:cond',
46                   '    return 1',
47                   '  else',
48                   '    echo "no return"',
49                   '  endif'
50                   'enddef'], 'E1027:')
51  CheckDefFailure(['def Missing(): number',
52                   '  if g:cond',
53                   '    return 1',
54                   '  else',
55                   '    return 2',
56                   '  endif'
57                   '  return 3'
58                   'enddef'], 'E1095:')
59enddef
60
61let s:nothing = 0
62def ReturnNothing()
63  s:nothing = 1
64  if true
65    return
66  endif
67  s:nothing = 2
68enddef
69
70def Test_return_nothing()
71  ReturnNothing()
72  s:nothing->assert_equal(1)
73enddef
74
75func Increment()
76  let g:counter += 1
77endfunc
78
79def Test_call_ufunc_count()
80  g:counter = 1
81  Increment()
82  Increment()
83  Increment()
84  # works with and without :call
85  g:counter->assert_equal(4)
86  eval g:counter->assert_equal(4)
87  unlet g:counter
88enddef
89
90def MyVarargs(arg: string, ...rest: list<string>): string
91  let res = arg
92  for s in rest
93    res ..= ',' .. s
94  endfor
95  return res
96enddef
97
98def Test_call_varargs()
99  MyVarargs('one')->assert_equal('one')
100  MyVarargs('one', 'two')->assert_equal('one,two')
101  MyVarargs('one', 'two', 'three')->assert_equal('one,two,three')
102enddef
103
104def MyDefaultArgs(name = 'string'): string
105  return name
106enddef
107
108def MyDefaultSecond(name: string, second: bool  = true): string
109  return second ? name : 'none'
110enddef
111
112def Test_call_default_args()
113  MyDefaultArgs()->assert_equal('string')
114  MyDefaultArgs('one')->assert_equal('one')
115  assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args')
116
117  MyDefaultSecond('test')->assert_equal('test')
118  MyDefaultSecond('test', true)->assert_equal('test')
119  MyDefaultSecond('test', false)->assert_equal('none')
120
121  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
122  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
123enddef
124
125def Test_nested_function()
126  def Nested(arg: string): string
127    return 'nested ' .. arg
128  enddef
129  Nested('function')->assert_equal('nested function')
130
131  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
132  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
133
134  CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
135  CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
136  CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
137
138  CheckDefFailure([
139        'def Outer()',
140        '  def Inner()',
141        '    # comment',
142        '  enddef',
143        '  def Inner()',
144        '  enddef',
145        'enddef'], 'E1073:')
146  CheckDefFailure([
147        'def Outer()',
148        '  def Inner()',
149        '    # comment',
150        '  enddef',
151        '  def! Inner()',
152        '  enddef',
153        'enddef'], 'E1117:')
154enddef
155
156func Test_call_default_args_from_func()
157  call MyDefaultArgs()->assert_equal('string')
158  call MyDefaultArgs('one')->assert_equal('one')
159  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func')
160endfunc
161
162def Test_nested_global_function()
163  let lines =<< trim END
164      vim9script
165      def Outer()
166          def g:Inner(): string
167              return 'inner'
168          enddef
169      enddef
170      defcompile
171      Outer()
172      g:Inner()->assert_equal('inner')
173      delfunc g:Inner
174      Outer()
175      g:Inner()->assert_equal('inner')
176      delfunc g:Inner
177      Outer()
178      g:Inner()->assert_equal('inner')
179      delfunc g:Inner
180  END
181  CheckScriptSuccess(lines)
182
183  lines =<< trim END
184      vim9script
185      def Outer()
186          def g:Inner(): string
187              return 'inner'
188          enddef
189      enddef
190      defcompile
191      Outer()
192      Outer()
193  END
194  CheckScriptFailure(lines, "E122:")
195
196  lines =<< trim END
197      vim9script
198      def Func()
199        echo 'script'
200      enddef
201      def Outer()
202        def Func()
203          echo 'inner'
204        enddef
205      enddef
206      defcompile
207  END
208  CheckScriptFailure(lines, "E1073:")
209enddef
210
211def Test_global_local_function()
212  let lines =<< trim END
213      vim9script
214      def g:Func(): string
215          return 'global'
216      enddef
217      def Func(): string
218          return 'local'
219      enddef
220      g:Func()->assert_equal('global')
221      Func()->assert_equal('local')
222  END
223  CheckScriptSuccess(lines)
224
225  lines =<< trim END
226      vim9script
227      def g:Funcy()
228        echo 'funcy'
229      enddef
230      s:Funcy()
231  END
232  CheckScriptFailure(lines, 'E117:')
233enddef
234
235def Test_local_function_shadows_global()
236  let lines =<< trim END
237      vim9script
238      def g:Gfunc(): string
239        return 'global'
240      enddef
241      def AnotherFunc(): number
242        let Gfunc = function('len')
243        return Gfunc('testing')
244      enddef
245      g:Gfunc()->assert_equal('global')
246      AnotherFunc()->assert_equal(7)
247      delfunc g:Gfunc
248  END
249  CheckScriptSuccess(lines)
250
251  lines =<< trim END
252      vim9script
253      def g:Func(): string
254        return 'global'
255      enddef
256      def AnotherFunc()
257        g:Func = function('len')
258      enddef
259      AnotherFunc()
260  END
261  CheckScriptFailure(lines, 'E705:')
262  delfunc g:Func
263enddef
264
265func TakesOneArg(arg)
266  echo a:arg
267endfunc
268
269def Test_call_wrong_args()
270  CheckDefFailure(['TakesOneArg()'], 'E119:')
271  CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
272  CheckDefFailure(['bufnr(xxx)'], 'E1001:')
273  CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
274
275  let lines =<< trim END
276    vim9script
277    def Func(s: string)
278      echo s
279    enddef
280    Func([])
281  END
282  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
283
284  lines =<< trim END
285    vim9script
286    def FuncOne(nr: number)
287      echo nr
288    enddef
289    def FuncTwo()
290      FuncOne()
291    enddef
292    defcompile
293  END
294  writefile(lines, 'Xscript')
295  let didCatch = false
296  try
297    source Xscript
298  catch
299    assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception)
300    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
301    didCatch = true
302  endtry
303  assert_true(didCatch)
304
305  lines =<< trim END
306    vim9script
307    def FuncOne(nr: number)
308      echo nr
309    enddef
310    def FuncTwo()
311      FuncOne(1, 2)
312    enddef
313    defcompile
314  END
315  writefile(lines, 'Xscript')
316  didCatch = false
317  try
318    source Xscript
319  catch
320    assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception)
321    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
322    didCatch = true
323  endtry
324  assert_true(didCatch)
325
326  delete('Xscript')
327enddef
328
329" Default arg and varargs
330def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
331  let res = one .. ',' .. two
332  for s in rest
333    res ..= ',' .. s
334  endfor
335  return res
336enddef
337
338def Test_call_def_varargs()
339  assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs')
340  MyDefVarargs('one')->assert_equal('one,foo')
341  MyDefVarargs('one', 'two')->assert_equal('one,two')
342  MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three')
343  CheckDefFailure(['MyDefVarargs("one", 22)'],
344      'E1013: Argument 2: type mismatch, expected string but got number')
345  CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
346      'E1013: Argument 3: type mismatch, expected string but got number')
347
348  let lines =<< trim END
349      vim9script
350      def Func(...l: list<string>)
351        echo l
352      enddef
353      Func('a', 'b', 'c')
354  END
355  CheckScriptSuccess(lines)
356
357  lines =<< trim END
358      vim9script
359      def Func(...l: list<string>)
360        echo l
361      enddef
362      Func()
363  END
364  CheckScriptSuccess(lines)
365
366  lines =<< trim END
367      vim9script
368      def Func(...l: any)
369        echo l
370      enddef
371      Func(0)
372  END
373  CheckScriptSuccess(lines)
374
375  lines =<< trim END
376      vim9script
377      def Func(...l: list<string>)
378        echo l
379      enddef
380      Func(1, 2, 3)
381  END
382  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
383
384  lines =<< trim END
385      vim9script
386      def Func(...l: list<string>)
387        echo l
388      enddef
389      Func('a', 9)
390  END
391  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch')
392
393  lines =<< trim END
394      vim9script
395      def Func(...l: list<string>)
396        echo l
397      enddef
398      Func(1, 'a')
399  END
400  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
401enddef
402
403def Test_call_call()
404  let l = [3, 2, 1]
405  call('reverse', [l])
406  l->assert_equal([1, 2, 3])
407enddef
408
409let s:value = ''
410
411def FuncOneDefArg(opt = 'text')
412  s:value = opt
413enddef
414
415def FuncTwoDefArg(nr = 123, opt = 'text'): string
416  return nr .. opt
417enddef
418
419def FuncVarargs(...arg: list<string>): string
420  return join(arg, ',')
421enddef
422
423def Test_func_type_varargs()
424  let RefDefArg: func(?string)
425  RefDefArg = FuncOneDefArg
426  RefDefArg()
427  s:value->assert_equal('text')
428  RefDefArg('some')
429  s:value->assert_equal('some')
430
431  let RefDef2Arg: func(?number, ?string): string
432  RefDef2Arg = FuncTwoDefArg
433  RefDef2Arg()->assert_equal('123text')
434  RefDef2Arg(99)->assert_equal('99text')
435  RefDef2Arg(77, 'some')->assert_equal('77some')
436
437  CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:')
438  CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:')
439
440  let RefVarargs: func(...list<string>): string
441  RefVarargs = FuncVarargs
442  RefVarargs()->assert_equal('')
443  RefVarargs('one')->assert_equal('one')
444  RefVarargs('one', 'two')->assert_equal('one,two')
445
446  CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:')
447  CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:')
448enddef
449
450" Only varargs
451def MyVarargsOnly(...args: list<string>): string
452  return join(args, ',')
453enddef
454
455def Test_call_varargs_only()
456  MyVarargsOnly()->assert_equal('')
457  MyVarargsOnly('one')->assert_equal('one')
458  MyVarargsOnly('one', 'two')->assert_equal('one,two')
459  CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
460  CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number')
461enddef
462
463def Test_using_var_as_arg()
464  writefile(['def Func(x: number)',  'let x = 234', 'enddef', 'defcompile'], 'Xdef')
465  assert_fails('so Xdef', 'E1006:', '', 1, 'Func')
466  delete('Xdef')
467enddef
468
469def DictArg(arg: dict<string>)
470  arg['key'] = 'value'
471enddef
472
473def ListArg(arg: list<string>)
474  arg[0] = 'value'
475enddef
476
477def Test_assign_to_argument()
478  # works for dict and list
479  let d: dict<string> = {}
480  DictArg(d)
481  d['key']->assert_equal('value')
482  let l: list<string> = []
483  ListArg(l)
484  l[0]->assert_equal('value')
485
486  CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
487enddef
488
489def Test_call_func_defined_later()
490  g:DefinedLater('one')->assert_equal('one')
491  assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
492enddef
493
494func DefinedLater(arg)
495  return a:arg
496endfunc
497
498def Test_call_funcref()
499  g:SomeFunc('abc')->assert_equal(3)
500  assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
501  assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
502
503  let lines =<< trim END
504    vim9script
505    def RetNumber(): number
506      return 123
507    enddef
508    let Funcref: func: number = function('RetNumber')
509    Funcref()->assert_equal(123)
510  END
511  CheckScriptSuccess(lines)
512
513  lines =<< trim END
514    vim9script
515    def RetNumber(): number
516      return 123
517    enddef
518    def Bar(F: func: number): number
519      return F()
520    enddef
521    let Funcref = function('RetNumber')
522    Bar(Funcref)->assert_equal(123)
523  END
524  CheckScriptSuccess(lines)
525
526  lines =<< trim END
527    vim9script
528    def UseNumber(nr: number)
529      echo nr
530    enddef
531    let Funcref: func(number) = function('UseNumber')
532    Funcref(123)
533  END
534  CheckScriptSuccess(lines)
535
536  lines =<< trim END
537    vim9script
538    def UseNumber(nr: number)
539      echo nr
540    enddef
541    let Funcref: func(string) = function('UseNumber')
542  END
543  CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
544
545  lines =<< trim END
546    vim9script
547    def EchoNr(nr = 34)
548      g:echo = nr
549    enddef
550    let Funcref: func(?number) = function('EchoNr')
551    Funcref()
552    g:echo->assert_equal(34)
553    Funcref(123)
554    g:echo->assert_equal(123)
555  END
556  CheckScriptSuccess(lines)
557
558  lines =<< trim END
559    vim9script
560    def EchoList(...l: list<number>)
561      g:echo = l
562    enddef
563    let Funcref: func(...list<number>) = function('EchoList')
564    Funcref()
565    g:echo->assert_equal([])
566    Funcref(1, 2, 3)
567    g:echo->assert_equal([1, 2, 3])
568  END
569  CheckScriptSuccess(lines)
570
571  lines =<< trim END
572    vim9script
573    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
574      g:optarg = opt
575      g:listarg = l
576      return nr
577    enddef
578    let Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
579    Funcref(10)->assert_equal(10)
580    g:optarg->assert_equal(12)
581    g:listarg->assert_equal([])
582
583    Funcref(11, 22)->assert_equal(11)
584    g:optarg->assert_equal(22)
585    g:listarg->assert_equal([])
586
587    Funcref(17, 18, 1, 2, 3)->assert_equal(17)
588    g:optarg->assert_equal(18)
589    g:listarg->assert_equal([1, 2, 3])
590  END
591  CheckScriptSuccess(lines)
592enddef
593
594let SomeFunc = function('len')
595let NotAFunc = 'text'
596
597def CombineFuncrefTypes()
598  # same arguments, different return type
599  let Ref1: func(bool): string
600  let Ref2: func(bool): number
601  let Ref3: func(bool): any
602  Ref3 = g:cond ? Ref1 : Ref2
603
604  # different number of arguments
605  let Refa1: func(bool): number
606  let Refa2: func(bool, number): number
607  let Refa3: func: number
608  Refa3 = g:cond ? Refa1 : Refa2
609
610  # different argument types
611  let Refb1: func(bool, string): number
612  let Refb2: func(string, number): number
613  let Refb3: func(any, any): number
614  Refb3 = g:cond ? Refb1 : Refb2
615enddef
616
617def FuncWithForwardCall()
618  return g:DefinedEvenLater("yes")
619enddef
620
621def DefinedEvenLater(arg: string): string
622  return arg
623enddef
624
625def Test_error_in_nested_function()
626  # Error in called function requires unwinding the call stack.
627  assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
628enddef
629
630def Test_return_type_wrong()
631  CheckScriptFailure([
632        'def Func(): number',
633        'return "a"',
634        'enddef',
635        'defcompile'], 'expected number but got string')
636  CheckScriptFailure([
637        'def Func(): string',
638        'return 1',
639        'enddef',
640        'defcompile'], 'expected string but got number')
641  CheckScriptFailure([
642        'def Func(): void',
643        'return "a"',
644        'enddef',
645        'defcompile'],
646        'E1096: Returning a value in a function without a return type')
647  CheckScriptFailure([
648        'def Func()',
649        'return "a"',
650        'enddef',
651        'defcompile'],
652        'E1096: Returning a value in a function without a return type')
653
654  CheckScriptFailure([
655        'def Func(): number',
656        'return',
657        'enddef',
658        'defcompile'], 'E1003:')
659
660  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
661  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
662  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
663
664  CheckScriptFailure([
665        'vim9script',
666        'def FuncB()',
667        '  return 123',
668        'enddef',
669        'def FuncA()',
670        '   FuncB()',
671        'enddef',
672        'defcompile'], 'E1096:')
673enddef
674
675def Test_arg_type_wrong()
676  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
677  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
678  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
679  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
680enddef
681
682def Test_vim9script_call()
683  let lines =<< trim END
684    vim9script
685    let var = ''
686    def MyFunc(arg: string)
687       var = arg
688    enddef
689    MyFunc('foobar')
690    var->assert_equal('foobar')
691
692    let str = 'barfoo'
693    str->MyFunc()
694    var->assert_equal('barfoo')
695
696    g:value = 'value'
697    g:value->MyFunc()
698    var->assert_equal('value')
699
700    let listvar = []
701    def ListFunc(arg: list<number>)
702       listvar = arg
703    enddef
704    [1, 2, 3]->ListFunc()
705    listvar->assert_equal([1, 2, 3])
706
707    let dictvar = {}
708    def DictFunc(arg: dict<number>)
709       dictvar = arg
710    enddef
711    {'a': 1, 'b': 2}->DictFunc()
712    dictvar->assert_equal(#{a: 1, b: 2})
713    def CompiledDict()
714      {'a': 3, 'b': 4}->DictFunc()
715    enddef
716    CompiledDict()
717    dictvar->assert_equal(#{a: 3, b: 4})
718
719    #{a: 3, b: 4}->DictFunc()
720    dictvar->assert_equal(#{a: 3, b: 4})
721
722    ('text')->MyFunc()
723    var->assert_equal('text')
724    ("some")->MyFunc()
725    var->assert_equal('some')
726
727    # line starting with single quote is not a mark
728    # line starting with double quote can be a method call
729    'asdfasdf'->MyFunc()
730    var->assert_equal('asdfasdf')
731    "xyz"->MyFunc()
732    var->assert_equal('xyz')
733
734    def UseString()
735      'xyork'->MyFunc()
736    enddef
737    UseString()
738    var->assert_equal('xyork')
739
740    def UseString2()
741      "knife"->MyFunc()
742    enddef
743    UseString2()
744    var->assert_equal('knife')
745
746    # prepending a colon makes it a mark
747    new
748    setline(1, ['aaa', 'bbb', 'ccc'])
749    normal! 3Gmt1G
750    :'t
751    getcurpos()[1]->assert_equal(3)
752    bwipe!
753
754    MyFunc(
755        'continued'
756        )
757    assert_equal('continued',
758            var
759            )
760
761    call MyFunc(
762        'more'
763          ..
764          'lines'
765        )
766    assert_equal(
767        'morelines',
768        var)
769  END
770  writefile(lines, 'Xcall.vim')
771  source Xcall.vim
772  delete('Xcall.vim')
773enddef
774
775def Test_vim9script_call_fail_decl()
776  let lines =<< trim END
777    vim9script
778    let var = ''
779    def MyFunc(arg: string)
780       let var = 123
781    enddef
782    defcompile
783  END
784  CheckScriptFailure(lines, 'E1054:')
785enddef
786
787def Test_vim9script_call_fail_type()
788  let lines =<< trim END
789    vim9script
790    def MyFunc(arg: string)
791      echo arg
792    enddef
793    MyFunc(1234)
794  END
795  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
796enddef
797
798def Test_vim9script_call_fail_const()
799  let lines =<< trim END
800    vim9script
801    const var = ''
802    def MyFunc(arg: string)
803       var = 'asdf'
804    enddef
805    defcompile
806  END
807  writefile(lines, 'Xcall_const.vim')
808  assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
809  delete('Xcall_const.vim')
810enddef
811
812" Test that inside :function a Python function can be defined, :def is not
813" recognized.
814func Test_function_python()
815  CheckFeature python3
816  let py = 'python3'
817  execute py "<< EOF"
818def do_something():
819  return 1
820EOF
821endfunc
822
823def Test_delfunc()
824  let lines =<< trim END
825    vim9script
826    def g:GoneSoon()
827      echo 'hello'
828    enddef
829
830    def CallGoneSoon()
831      GoneSoon()
832    enddef
833    defcompile
834
835    delfunc g:GoneSoon
836    CallGoneSoon()
837  END
838  writefile(lines, 'XToDelFunc')
839  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
840  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
841
842  delete('XToDelFunc')
843enddef
844
845def Test_redef_failure()
846  writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
847  so Xdef
848  writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
849  so Xdef
850  writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
851  assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
852  writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
853  so Xdef
854  delete('Xdef')
855
856  g:Func0()->assert_equal(0)
857  g:Func1()->assert_equal('Func1')
858  g:Func2()->assert_equal('Func2')
859
860  delfunc! Func0
861  delfunc! Func1
862  delfunc! Func2
863enddef
864
865def Test_vim9script_func()
866  let lines =<< trim END
867    vim9script
868    func Func(arg)
869      echo a:arg
870    endfunc
871    Func('text')
872  END
873  writefile(lines, 'XVim9Func')
874  so XVim9Func
875
876  delete('XVim9Func')
877enddef
878
879" Test for internal functions returning different types
880func Test_InternalFuncRetType()
881  let lines =<< trim END
882    def RetFloat(): float
883      return ceil(1.456)
884    enddef
885
886    def RetListAny(): list<any>
887      return items({'k': 'v'})
888    enddef
889
890    def RetListString(): list<string>
891      return split('a:b:c', ':')
892    enddef
893
894    def RetListDictAny(): list<dict<any>>
895      return getbufinfo()
896    enddef
897
898    def RetDictNumber(): dict<number>
899      return wordcount()
900    enddef
901
902    def RetDictString(): dict<string>
903      return environ()
904    enddef
905  END
906  call writefile(lines, 'Xscript')
907  source Xscript
908
909  call RetFloat()->assert_equal(2.0)
910  call RetListAny()->assert_equal([['k', 'v']])
911  call RetListString()->assert_equal(['a', 'b', 'c'])
912  call RetListDictAny()->assert_notequal([])
913  call RetDictNumber()->assert_notequal({})
914  call RetDictString()->assert_notequal({})
915  call delete('Xscript')
916endfunc
917
918" Test for passing too many or too few arguments to internal functions
919func Test_internalfunc_arg_error()
920  let l =<< trim END
921    def! FArgErr(): float
922      return ceil(1.1, 2)
923    enddef
924    defcompile
925  END
926  call writefile(l, 'Xinvalidarg')
927  call assert_fails('so Xinvalidarg', 'E118:', '', 1, 'FArgErr')
928  let l =<< trim END
929    def! FArgErr(): float
930      return ceil()
931    enddef
932    defcompile
933  END
934  call writefile(l, 'Xinvalidarg')
935  call assert_fails('so Xinvalidarg', 'E119:', '', 1, 'FArgErr')
936  call delete('Xinvalidarg')
937endfunc
938
939let s:funcResult = 0
940
941def FuncNoArgNoRet()
942  s:funcResult = 11
943enddef
944
945def FuncNoArgRetNumber(): number
946  s:funcResult = 22
947  return 1234
948enddef
949
950def FuncNoArgRetString(): string
951  s:funcResult = 45
952  return 'text'
953enddef
954
955def FuncOneArgNoRet(arg: number)
956  s:funcResult = arg
957enddef
958
959def FuncOneArgRetNumber(arg: number): number
960  s:funcResult = arg
961  return arg
962enddef
963
964def FuncTwoArgNoRet(one: bool, two: number)
965  s:funcResult = two
966enddef
967
968def FuncOneArgRetString(arg: string): string
969  return arg
970enddef
971
972def FuncOneArgRetAny(arg: any): any
973  return arg
974enddef
975
976def Test_func_type()
977  let Ref1: func()
978  s:funcResult = 0
979  Ref1 = FuncNoArgNoRet
980  Ref1()
981  s:funcResult->assert_equal(11)
982
983  let Ref2: func
984  s:funcResult = 0
985  Ref2 = FuncNoArgNoRet
986  Ref2()
987  s:funcResult->assert_equal(11)
988
989  s:funcResult = 0
990  Ref2 = FuncOneArgNoRet
991  Ref2(12)
992  s:funcResult->assert_equal(12)
993
994  s:funcResult = 0
995  Ref2 = FuncNoArgRetNumber
996  Ref2()->assert_equal(1234)
997  s:funcResult->assert_equal(22)
998
999  s:funcResult = 0
1000  Ref2 = FuncOneArgRetNumber
1001  Ref2(13)->assert_equal(13)
1002  s:funcResult->assert_equal(13)
1003enddef
1004
1005def Test_repeat_return_type()
1006  let res = 0
1007  for n in repeat([1], 3)
1008    res += n
1009  endfor
1010  res->assert_equal(3)
1011
1012  res = 0
1013  for n in add([1, 2], 3)
1014    res += n
1015  endfor
1016  res->assert_equal(6)
1017enddef
1018
1019def Test_argv_return_type()
1020  next fileone filetwo
1021  let res = ''
1022  for name in argv()
1023    res ..= name
1024  endfor
1025  res->assert_equal('fileonefiletwo')
1026enddef
1027
1028def Test_func_type_part()
1029  let RefVoid: func: void
1030  RefVoid = FuncNoArgNoRet
1031  RefVoid = FuncOneArgNoRet
1032  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1033  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
1034
1035  let RefAny: func(): any
1036  RefAny = FuncNoArgRetNumber
1037  RefAny = FuncNoArgRetString
1038  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1039  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
1040
1041  let RefNr: func: number
1042  RefNr = FuncNoArgRetNumber
1043  RefNr = FuncOneArgRetNumber
1044  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1045  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
1046
1047  let RefStr: func: string
1048  RefStr = FuncNoArgRetString
1049  RefStr = FuncOneArgRetString
1050  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1051  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
1052enddef
1053
1054def Test_func_type_fails()
1055  CheckDefFailure(['let ref1: func()'], 'E704:')
1056
1057  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1058  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1059  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1060  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1061  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1062  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
1063
1064  CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
1065  CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
1066  CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E1005:')
1067  CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
1068enddef
1069
1070def Test_func_return_type()
1071  let nr: number
1072  nr = FuncNoArgRetNumber()
1073  nr->assert_equal(1234)
1074
1075  nr = FuncOneArgRetAny(122)
1076  nr->assert_equal(122)
1077
1078  let str: string
1079  str = FuncOneArgRetAny('yes')
1080  str->assert_equal('yes')
1081
1082  CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
1083enddef
1084
1085def MultiLine(
1086    arg1: string,
1087    arg2 = 1234,
1088    ...rest: list<string>
1089      ): string
1090  return arg1 .. arg2 .. join(rest, '-')
1091enddef
1092
1093def MultiLineComment(
1094    arg1: string, # comment
1095    arg2 = 1234, # comment
1096    ...rest: list<string> # comment
1097      ): string # comment
1098  return arg1 .. arg2 .. join(rest, '-')
1099enddef
1100
1101def Test_multiline()
1102  MultiLine('text')->assert_equal('text1234')
1103  MultiLine('text', 777)->assert_equal('text777')
1104  MultiLine('text', 777, 'one')->assert_equal('text777one')
1105  MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1106enddef
1107
1108func Test_multiline_not_vim9()
1109  call MultiLine('text')->assert_equal('text1234')
1110  call MultiLine('text', 777)->assert_equal('text777')
1111  call MultiLine('text', 777, 'one')->assert_equal('text777one')
1112  call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1113endfunc
1114
1115
1116" When using CheckScriptFailure() for the below test, E1010 is generated instead
1117" of E1056.
1118func Test_E1056_1059()
1119  let caught_1056 = 0
1120  try
1121    def F():
1122      return 1
1123    enddef
1124  catch /E1056:/
1125    let caught_1056 = 1
1126  endtry
1127  eval caught_1056->assert_equal(1)
1128
1129  let caught_1059 = 0
1130  try
1131    def F5(items : list)
1132      echo 'a'
1133    enddef
1134  catch /E1059:/
1135    let caught_1059 = 1
1136  endtry
1137  eval caught_1059->assert_equal(1)
1138endfunc
1139
1140func DelMe()
1141  echo 'DelMe'
1142endfunc
1143
1144def Test_error_reporting()
1145  # comment lines at the start of the function
1146  let lines =<< trim END
1147    " comment
1148    def Func()
1149      # comment
1150      # comment
1151      invalid
1152    enddef
1153    defcompile
1154  END
1155  writefile(lines, 'Xdef')
1156  try
1157    source Xdef
1158    assert_report('should have failed')
1159  catch /E476:/
1160    v:exception->assert_match('Invalid command: invalid')
1161    v:throwpoint->assert_match(', line 3$')
1162  endtry
1163
1164  # comment lines after the start of the function
1165  lines =<< trim END
1166    " comment
1167    def Func()
1168      let x = 1234
1169      # comment
1170      # comment
1171      invalid
1172    enddef
1173    defcompile
1174  END
1175  writefile(lines, 'Xdef')
1176  try
1177    source Xdef
1178    assert_report('should have failed')
1179  catch /E476:/
1180    v:exception->assert_match('Invalid command: invalid')
1181    v:throwpoint->assert_match(', line 4$')
1182  endtry
1183
1184  lines =<< trim END
1185    vim9script
1186    def Func()
1187      let db = #{foo: 1, bar: 2}
1188      # comment
1189      let x = db.asdf
1190    enddef
1191    defcompile
1192    Func()
1193  END
1194  writefile(lines, 'Xdef')
1195  try
1196    source Xdef
1197    assert_report('should have failed')
1198  catch /E716:/
1199    v:throwpoint->assert_match('_Func, line 3$')
1200  endtry
1201
1202  delete('Xdef')
1203enddef
1204
1205def Test_deleted_function()
1206  CheckDefExecFailure([
1207      'let RefMe: func = function("g:DelMe")',
1208      'delfunc g:DelMe',
1209      'echo RefMe()'], 'E117:')
1210enddef
1211
1212def Test_unknown_function()
1213  CheckDefExecFailure([
1214      'let Ref: func = function("NotExist")',
1215      'delfunc g:NotExist'], 'E700:')
1216enddef
1217
1218def RefFunc(Ref: func(string): string): string
1219  return Ref('more')
1220enddef
1221
1222def Test_closure_simple()
1223  let local = 'some '
1224  RefFunc({s -> local .. s})->assert_equal('some more')
1225enddef
1226
1227def MakeRef()
1228  let local = 'some '
1229  g:Ref = {s -> local .. s}
1230enddef
1231
1232def Test_closure_ref_after_return()
1233  MakeRef()
1234  g:Ref('thing')->assert_equal('some thing')
1235  unlet g:Ref
1236enddef
1237
1238def MakeTwoRefs()
1239  let local = ['some']
1240  g:Extend = {s -> local->add(s)}
1241  g:Read = {-> local}
1242enddef
1243
1244def Test_closure_two_refs()
1245  MakeTwoRefs()
1246  join(g:Read(), ' ')->assert_equal('some')
1247  g:Extend('more')
1248  join(g:Read(), ' ')->assert_equal('some more')
1249  g:Extend('even')
1250  join(g:Read(), ' ')->assert_equal('some more even')
1251
1252  unlet g:Extend
1253  unlet g:Read
1254enddef
1255
1256def ReadRef(Ref: func(): list<string>): string
1257  return join(Ref(), ' ')
1258enddef
1259
1260def ExtendRef(Ref: func(string): list<string>, add: string)
1261  Ref(add)
1262enddef
1263
1264def Test_closure_two_indirect_refs()
1265  MakeTwoRefs()
1266  ReadRef(g:Read)->assert_equal('some')
1267  ExtendRef(g:Extend, 'more')
1268  ReadRef(g:Read)->assert_equal('some more')
1269  ExtendRef(g:Extend, 'even')
1270  ReadRef(g:Read)->assert_equal('some more even')
1271
1272  unlet g:Extend
1273  unlet g:Read
1274enddef
1275
1276def MakeArgRefs(theArg: string)
1277  let local = 'loc_val'
1278  g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
1279enddef
1280
1281def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
1282  let local = 'the_loc'
1283  g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
1284enddef
1285
1286def Test_closure_using_argument()
1287  MakeArgRefs('arg_val')
1288  g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
1289
1290  MakeArgRefsVarargs('arg_val', 'one', 'two')
1291  g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
1292
1293  unlet g:UseArg
1294  unlet g:UseVararg
1295enddef
1296
1297def MakeGetAndAppendRefs()
1298  let local = 'a'
1299
1300  def Append(arg: string)
1301    local ..= arg
1302  enddef
1303  g:Append = Append
1304
1305  def Get(): string
1306    return local
1307  enddef
1308  g:Get = Get
1309enddef
1310
1311def Test_closure_append_get()
1312  MakeGetAndAppendRefs()
1313  g:Get()->assert_equal('a')
1314  g:Append('-b')
1315  g:Get()->assert_equal('a-b')
1316  g:Append('-c')
1317  g:Get()->assert_equal('a-b-c')
1318
1319  unlet g:Append
1320  unlet g:Get
1321enddef
1322
1323def Test_nested_closure()
1324  let local = 'text'
1325  def Closure(arg: string): string
1326    return local .. arg
1327  enddef
1328  Closure('!!!')->assert_equal('text!!!')
1329enddef
1330
1331func GetResult(Ref)
1332  return a:Ref('some')
1333endfunc
1334
1335def Test_call_closure_not_compiled()
1336  let text = 'text'
1337  g:Ref = {s ->  s .. text}
1338  GetResult(g:Ref)->assert_equal('sometext')
1339enddef
1340
1341def Test_double_closure_fails()
1342  let lines =<< trim END
1343    vim9script
1344    def Func()
1345    let var = 0
1346    for i in range(2)
1347	timer_start(0, {-> var})
1348    endfor
1349    enddef
1350    Func()
1351  END
1352  CheckScriptFailure(lines, 'Multiple closures not supported yet')
1353enddef
1354
1355def Test_sort_return_type()
1356  let res: list<number>
1357  res = [1, 2, 3]->sort()
1358enddef
1359
1360def Test_sort_argument()
1361  let res = ['b', 'a', 'c']->sort('i')
1362  res->assert_equal(['a', 'b', 'c'])
1363enddef
1364
1365def Test_getqflist_return_type()
1366  let l = getqflist()
1367  l->assert_equal([])
1368
1369  let d = getqflist(#{items: 0})
1370  d->assert_equal(#{items: []})
1371enddef
1372
1373def Test_getloclist_return_type()
1374  let l = getloclist(1)
1375  l->assert_equal([])
1376
1377  let d = getloclist(1, #{items: 0})
1378  d->assert_equal(#{items: []})
1379enddef
1380
1381def Test_copy_return_type()
1382  let l = copy([1, 2, 3])
1383  let res = 0
1384  for n in l
1385    res += n
1386  endfor
1387  res->assert_equal(6)
1388
1389  let dl = deepcopy([1, 2, 3])
1390  res = 0
1391  for n in dl
1392    res += n
1393  endfor
1394  res->assert_equal(6)
1395
1396  dl = deepcopy([1, 2, 3], true)
1397enddef
1398
1399def Test_extend_return_type()
1400  let l = extend([1, 2], [3])
1401  let res = 0
1402  for n in l
1403    res += n
1404  endfor
1405  res->assert_equal(6)
1406enddef
1407
1408def Test_garbagecollect()
1409  garbagecollect(true)
1410enddef
1411
1412def Test_insert_return_type()
1413  let l = insert([2, 1], 3)
1414  let res = 0
1415  for n in l
1416    res += n
1417  endfor
1418  res->assert_equal(6)
1419enddef
1420
1421def Test_keys_return_type()
1422  const var: list<string> = #{a: 1, b: 2}->keys()
1423  var->assert_equal(['a', 'b'])
1424enddef
1425
1426def Test_reverse_return_type()
1427  let l = reverse([1, 2, 3])
1428  let res = 0
1429  for n in l
1430    res += n
1431  endfor
1432  res->assert_equal(6)
1433enddef
1434
1435def Test_remove_return_type()
1436  let l = remove(#{one: [1, 2], two: [3, 4]}, 'one')
1437  let res = 0
1438  for n in l
1439    res += n
1440  endfor
1441  res->assert_equal(3)
1442enddef
1443
1444def Test_filter_return_type()
1445  let l = filter([1, 2, 3], {-> 1})
1446  let res = 0
1447  for n in l
1448    res += n
1449  endfor
1450  res->assert_equal(6)
1451enddef
1452
1453def Test_bufnr()
1454  let buf = bufnr()
1455  bufnr('%')->assert_equal(buf)
1456
1457  buf = bufnr('Xdummy', true)
1458  buf->assert_notequal(-1)
1459  exe 'bwipe! ' .. buf
1460enddef
1461
1462def Test_col()
1463  new
1464  setline(1, 'asdf')
1465  col([1, '$'])->assert_equal(5)
1466enddef
1467
1468def Test_char2nr()
1469  char2nr('あ', true)->assert_equal(12354)
1470enddef
1471
1472def Test_getreg_return_type()
1473  let s1: string = getreg('"')
1474  let s2: string = getreg('"', 1)
1475  let s3: list<string> = getreg('"', 1, 1)
1476enddef
1477
1478def Wrong_dict_key_type(items: list<number>): list<number>
1479  return filter(items, {_, val -> get({val: 1}, 'x')})
1480enddef
1481
1482def Test_wrong_dict_key_type()
1483  assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1012:')
1484enddef
1485
1486def Line_continuation_in_def(dir: string = ''): string
1487    let path: string = empty(dir)
1488            \ ? 'empty'
1489            \ : 'full'
1490    return path
1491enddef
1492
1493def Test_line_continuation_in_def()
1494  Line_continuation_in_def('.')->assert_equal('full')
1495enddef
1496
1497def Line_continuation_in_lambda(): list<string>
1498  let x = range(97, 100)
1499      ->map({_, v -> nr2char(v)
1500          ->toupper()})
1501      ->reverse()
1502  return x
1503enddef
1504
1505def Test_line_continuation_in_lambda()
1506  Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
1507enddef
1508
1509func Test_silent_echo()
1510  CheckScreendump
1511
1512  let lines =<< trim END
1513    vim9script
1514    def EchoNothing()
1515      silent echo ''
1516    enddef
1517    defcompile
1518  END
1519  call writefile(lines, 'XTest_silent_echo')
1520
1521  " Check that the balloon shows up after a mouse move
1522  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
1523  call term_sendkeys(buf, ":abc")
1524  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
1525
1526  " clean up
1527  call StopVimInTerminal(buf)
1528  call delete('XTest_silent_echo')
1529endfunc
1530
1531""""""" builtin functions that behave differently in Vim9
1532
1533def Test_bufname()
1534  split SomeFile
1535  bufname('%')->assert_equal('SomeFile')
1536  edit OtherFile
1537  bufname('#')->assert_equal('SomeFile')
1538  close
1539enddef
1540
1541def Test_bufwinid()
1542  let origwin = win_getid()
1543  below split SomeFile
1544  let SomeFileID = win_getid()
1545  below split OtherFile
1546  below split SomeFile
1547  bufwinid('SomeFile')->assert_equal(SomeFileID)
1548
1549  win_gotoid(origwin)
1550  only
1551  bwipe SomeFile
1552  bwipe OtherFile
1553enddef
1554
1555def Test_count()
1556  count('ABC ABC ABC', 'b', true)->assert_equal(3)
1557  count('ABC ABC ABC', 'b', false)->assert_equal(0)
1558enddef
1559
1560def Test_expand()
1561  split SomeFile
1562  expand('%', true, true)->assert_equal(['SomeFile'])
1563  close
1564enddef
1565
1566def Test_getbufinfo()
1567  let bufinfo = getbufinfo(bufnr())
1568  getbufinfo('%')->assert_equal(bufinfo)
1569
1570  edit Xtestfile1
1571  hide edit Xtestfile2
1572  hide enew
1573  getbufinfo(#{bufloaded: true, buflisted: true, bufmodified: false})
1574      ->len()->assert_equal(3)
1575  bwipe Xtestfile1 Xtestfile2
1576enddef
1577
1578def Test_getbufline()
1579  e SomeFile
1580  let buf = bufnr()
1581  e #
1582  let lines = ['aaa', 'bbb', 'ccc']
1583  setbufline(buf, 1, lines)
1584  getbufline('#', 1, '$')->assert_equal(lines)
1585
1586  bwipe!
1587enddef
1588
1589def Test_getchangelist()
1590  new
1591  setline(1, 'some text')
1592  let changelist = bufnr()->getchangelist()
1593  getchangelist('%')->assert_equal(changelist)
1594  bwipe!
1595enddef
1596
1597def Test_getchar()
1598  while getchar(0)
1599  endwhile
1600  getchar(true)->assert_equal(0)
1601enddef
1602
1603def Test_getcompletion()
1604  set wildignore=*.vim,*~
1605  let l = getcompletion('run', 'file', true)
1606  l->assert_equal([])
1607  set wildignore&
1608enddef
1609
1610def Test_getreg()
1611  let lines = ['aaa', 'bbb', 'ccc']
1612  setreg('a', lines)
1613  getreg('a', true, true)->assert_equal(lines)
1614enddef
1615
1616def Test_glob()
1617  glob('runtest.vim', true, true, true)->assert_equal(['runtest.vim'])
1618enddef
1619
1620def Test_globpath()
1621  globpath('.', 'runtest.vim', true, true, true)->assert_equal(['./runtest.vim'])
1622enddef
1623
1624def Test_has()
1625  has('eval', true)->assert_equal(1)
1626enddef
1627
1628def Test_hasmapto()
1629  hasmapto('foobar', 'i', true)->assert_equal(0)
1630  iabbrev foo foobar
1631  hasmapto('foobar', 'i', true)->assert_equal(1)
1632  iunabbrev foo
1633enddef
1634
1635def Test_index()
1636  index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
1637enddef
1638
1639def Test_list2str_str2list_utf8()
1640  let s = "\u3042\u3044"
1641  let l = [0x3042, 0x3044]
1642  str2list(s, true)->assert_equal(l)
1643  list2str(l, true)->assert_equal(s)
1644enddef
1645
1646def SID(): number
1647  return expand('<SID>')
1648          ->matchstr('<SNR>\zs\d\+\ze_$')
1649          ->str2nr()
1650enddef
1651
1652def Test_maparg()
1653  let lnum = str2nr(expand('<sflnum>'))
1654  map foo bar
1655  maparg('foo', '', false, true)->assert_equal(#{
1656        lnum: lnum + 1,
1657        script: 0,
1658        mode: ' ',
1659        silent: 0,
1660        noremap: 0,
1661        lhs: 'foo',
1662        lhsraw: 'foo',
1663        nowait: 0,
1664        expr: 0,
1665        sid: SID(),
1666        rhs: 'bar',
1667        buffer: 0})
1668  unmap foo
1669enddef
1670
1671def Test_mapcheck()
1672  iabbrev foo foobar
1673  mapcheck('foo', 'i', true)->assert_equal('foobar')
1674  iunabbrev foo
1675enddef
1676
1677def Test_nr2char()
1678  nr2char(97, true)->assert_equal('a')
1679enddef
1680
1681def Test_readdir()
1682   eval expand('sautest')->readdir({e -> e[0] !=# '.'})
1683   eval expand('sautest')->readdirex({e -> e.name[0] !=# '.'})
1684enddef
1685
1686def Test_search()
1687  new
1688  setline(1, ['foo', 'bar'])
1689  let val = 0
1690  # skip expr returns boolean
1691  search('bar', 'W', 0, 0, {-> val == 1})->assert_equal(2)
1692  :1
1693  search('bar', 'W', 0, 0, {-> val == 0})->assert_equal(0)
1694  # skip expr returns number, only 0 and 1 are accepted
1695  :1
1696  search('bar', 'W', 0, 0, {-> 0})->assert_equal(2)
1697  :1
1698  search('bar', 'W', 0, 0, {-> 1})->assert_equal(0)
1699  assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:')
1700  assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:')
1701enddef
1702
1703def Test_searchcount()
1704  new
1705  setline(1, "foo bar")
1706  :/foo
1707  searchcount(#{recompute: true})
1708      ->assert_equal(#{
1709          exact_match: 1,
1710          current: 1,
1711          total: 1,
1712          maxcount: 99,
1713          incomplete: 0})
1714  bwipe!
1715enddef
1716
1717def Test_searchdecl()
1718  searchdecl('blah', true, true)->assert_equal(1)
1719enddef
1720
1721def Test_setbufvar()
1722  setbufvar(bufnr('%'), '&syntax', 'vim')
1723  &syntax->assert_equal('vim')
1724  setbufvar(bufnr('%'), '&ts', 16)
1725  &ts->assert_equal(16)
1726  settabwinvar(1, 1, '&syntax', 'vam')
1727  &syntax->assert_equal('vam')
1728  settabwinvar(1, 1, '&ts', 15)
1729  &ts->assert_equal(15)
1730  setlocal ts=8
1731
1732  setbufvar('%', 'myvar', 123)
1733  getbufvar('%', 'myvar')->assert_equal(123)
1734enddef
1735
1736def Test_setloclist()
1737  let items = [#{filename: '/tmp/file', lnum: 1, valid: true}]
1738  let what = #{items: items}
1739  setqflist([], ' ', what)
1740  setloclist(0, [], ' ', what)
1741enddef
1742
1743def Test_setreg()
1744  setreg('a', ['aaa', 'bbb', 'ccc'])
1745  let reginfo = getreginfo('a')
1746  setreg('a', reginfo)
1747  getreginfo('a')->assert_equal(reginfo)
1748enddef
1749
1750def Test_spellsuggest()
1751  if !has('spell')
1752    MissingFeature 'spell'
1753  else
1754    spellsuggest('marrch', 1, true)->assert_equal(['March'])
1755  endif
1756enddef
1757
1758def Test_split()
1759  split('  aa  bb  ', '\W\+', true)->assert_equal(['', 'aa', 'bb', ''])
1760enddef
1761
1762def Test_str2nr()
1763  str2nr("1'000'000", 10, true)->assert_equal(1000000)
1764enddef
1765
1766def Test_strchars()
1767  strchars("A\u20dd", true)->assert_equal(1)
1768enddef
1769
1770def Test_submatch()
1771  let pat = 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)'
1772  let Rep = {-> range(10)->map({_, v -> submatch(v, true)})->string()}
1773  let actual = substitute('A123456789', pat, Rep, '')
1774  let expected = "[['A123456789'], ['1'], ['2'], ['3'], ['4'], ['5'], ['6'], ['7'], ['8'], ['9']]"
1775  actual->assert_equal(expected)
1776enddef
1777
1778def Test_synID()
1779  new
1780  setline(1, "text")
1781  synID(1, 1, true)->assert_equal(0)
1782  bwipe!
1783enddef
1784
1785def Test_term_gettty()
1786  if !has('terminal')
1787    MissingFeature 'terminal'
1788  else
1789    let buf = Run_shell_in_terminal({})
1790    term_gettty(buf, true)->assert_notequal('')
1791    StopShellInTerminal(buf)
1792  endif
1793enddef
1794
1795def Test_term_start()
1796  if !has('terminal')
1797    MissingFeature 'terminal'
1798  else
1799    botright new
1800    let winnr = winnr()
1801    term_start(&shell, #{curwin: true})
1802    winnr()->assert_equal(winnr)
1803    bwipe!
1804  endif
1805enddef
1806
1807def Test_timer_paused()
1808  let id = timer_start(50, {-> 0})
1809  timer_pause(id, true)
1810  let info = timer_info(id)
1811  info[0]['paused']->assert_equal(1)
1812  timer_stop(id)
1813enddef
1814
1815def Test_win_splitmove()
1816  split
1817  win_splitmove(1, 2, #{vertical: true, rightbelow: true})
1818  close
1819enddef
1820
1821""""""" end of builtin functions
1822
1823def Fibonacci(n: number): number
1824  if n < 2
1825    return n
1826  else
1827    return Fibonacci(n - 1) + Fibonacci(n - 2)
1828  endif
1829enddef
1830
1831def Test_recursive_call()
1832  Fibonacci(20)->assert_equal(6765)
1833enddef
1834
1835def TreeWalk(dir: string): list<any>
1836  return readdir(dir)->map({_, val ->
1837            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
1838               ? {val: TreeWalk(dir .. '/' .. val)}
1839               : val
1840             })
1841enddef
1842
1843def Test_closure_in_map()
1844  mkdir('XclosureDir/tdir', 'p')
1845  writefile(['111'], 'XclosureDir/file1')
1846  writefile(['222'], 'XclosureDir/file2')
1847  writefile(['333'], 'XclosureDir/tdir/file3')
1848
1849  TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {'tdir': ['file3']}])
1850
1851  delete('XclosureDir', 'rf')
1852enddef
1853
1854def Test_partial_call()
1855  let Xsetlist = function('setloclist', [0])
1856  Xsetlist([], ' ', {'title': 'test'})
1857  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1858
1859  Xsetlist = function('setloclist', [0, [], ' '])
1860  Xsetlist({'title': 'test'})
1861  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1862
1863  Xsetlist = function('setqflist')
1864  Xsetlist([], ' ', {'title': 'test'})
1865  getqflist({'title': 1})->assert_equal({'title': 'test'})
1866
1867  Xsetlist = function('setqflist', [[], ' '])
1868  Xsetlist({'title': 'test'})
1869  getqflist({'title': 1})->assert_equal({'title': 'test'})
1870enddef
1871
1872def Test_cmd_modifier()
1873  tab echo '0'
1874  CheckDefFailure(['5tab echo 3'], 'E16:')
1875enddef
1876
1877def Test_restore_modifiers()
1878  # check that when compiling a :def function command modifiers are not messed
1879  # up.
1880  let lines =<< trim END
1881      vim9script
1882      set eventignore=
1883      autocmd QuickFixCmdPost * copen
1884      def AutocmdsDisabled()
1885          eval 0
1886      enddef
1887      func Func()
1888        noautocmd call s:AutocmdsDisabled()
1889        let g:ei_after = &eventignore
1890      endfunc
1891      Func()
1892  END
1893  CheckScriptSuccess(lines)
1894  g:ei_after->assert_equal('')
1895enddef
1896
1897def StackTop()
1898  eval 1
1899  eval 2
1900  # call not on fourth line
1901  StackBot()
1902enddef
1903
1904def StackBot()
1905  # throw an error
1906  eval [][0]
1907enddef
1908
1909def Test_callstack_def()
1910  try
1911    StackTop()
1912  catch
1913    v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
1914  endtry
1915enddef
1916
1917
1918" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1919