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
489" These argument names are reserved in legacy functions.
490def WithReservedNames(firstline: string, lastline: string): string
491  return firstline .. lastline
492enddef
493
494def Test_argument_names()
495  assert_equal('OK', WithReservedNames('O', 'K'))
496enddef
497
498def Test_call_func_defined_later()
499  g:DefinedLater('one')->assert_equal('one')
500  assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
501enddef
502
503func DefinedLater(arg)
504  return a:arg
505endfunc
506
507def Test_call_funcref()
508  g:SomeFunc('abc')->assert_equal(3)
509  assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
510  assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
511
512  let lines =<< trim END
513    vim9script
514    def RetNumber(): number
515      return 123
516    enddef
517    let Funcref: func: number = function('RetNumber')
518    Funcref()->assert_equal(123)
519  END
520  CheckScriptSuccess(lines)
521
522  lines =<< trim END
523    vim9script
524    def RetNumber(): number
525      return 123
526    enddef
527    def Bar(F: func: number): number
528      return F()
529    enddef
530    let Funcref = function('RetNumber')
531    Bar(Funcref)->assert_equal(123)
532  END
533  CheckScriptSuccess(lines)
534
535  lines =<< trim END
536    vim9script
537    def UseNumber(nr: number)
538      echo nr
539    enddef
540    let Funcref: func(number) = function('UseNumber')
541    Funcref(123)
542  END
543  CheckScriptSuccess(lines)
544
545  lines =<< trim END
546    vim9script
547    def UseNumber(nr: number)
548      echo nr
549    enddef
550    let Funcref: func(string) = function('UseNumber')
551  END
552  CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
553
554  lines =<< trim END
555    vim9script
556    def EchoNr(nr = 34)
557      g:echo = nr
558    enddef
559    let Funcref: func(?number) = function('EchoNr')
560    Funcref()
561    g:echo->assert_equal(34)
562    Funcref(123)
563    g:echo->assert_equal(123)
564  END
565  CheckScriptSuccess(lines)
566
567  lines =<< trim END
568    vim9script
569    def EchoList(...l: list<number>)
570      g:echo = l
571    enddef
572    let Funcref: func(...list<number>) = function('EchoList')
573    Funcref()
574    g:echo->assert_equal([])
575    Funcref(1, 2, 3)
576    g:echo->assert_equal([1, 2, 3])
577  END
578  CheckScriptSuccess(lines)
579
580  lines =<< trim END
581    vim9script
582    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
583      g:optarg = opt
584      g:listarg = l
585      return nr
586    enddef
587    let Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
588    Funcref(10)->assert_equal(10)
589    g:optarg->assert_equal(12)
590    g:listarg->assert_equal([])
591
592    Funcref(11, 22)->assert_equal(11)
593    g:optarg->assert_equal(22)
594    g:listarg->assert_equal([])
595
596    Funcref(17, 18, 1, 2, 3)->assert_equal(17)
597    g:optarg->assert_equal(18)
598    g:listarg->assert_equal([1, 2, 3])
599  END
600  CheckScriptSuccess(lines)
601enddef
602
603let SomeFunc = function('len')
604let NotAFunc = 'text'
605
606def CombineFuncrefTypes()
607  # same arguments, different return type
608  let Ref1: func(bool): string
609  let Ref2: func(bool): number
610  let Ref3: func(bool): any
611  Ref3 = g:cond ? Ref1 : Ref2
612
613  # different number of arguments
614  let Refa1: func(bool): number
615  let Refa2: func(bool, number): number
616  let Refa3: func: number
617  Refa3 = g:cond ? Refa1 : Refa2
618
619  # different argument types
620  let Refb1: func(bool, string): number
621  let Refb2: func(string, number): number
622  let Refb3: func(any, any): number
623  Refb3 = g:cond ? Refb1 : Refb2
624enddef
625
626def FuncWithForwardCall()
627  return g:DefinedEvenLater("yes")
628enddef
629
630def DefinedEvenLater(arg: string): string
631  return arg
632enddef
633
634def Test_error_in_nested_function()
635  # Error in called function requires unwinding the call stack.
636  assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
637enddef
638
639def Test_return_type_wrong()
640  CheckScriptFailure([
641        'def Func(): number',
642        'return "a"',
643        'enddef',
644        'defcompile'], 'expected number but got string')
645  CheckScriptFailure([
646        'def Func(): string',
647        'return 1',
648        'enddef',
649        'defcompile'], 'expected string but got number')
650  CheckScriptFailure([
651        'def Func(): void',
652        'return "a"',
653        'enddef',
654        'defcompile'],
655        'E1096: Returning a value in a function without a return type')
656  CheckScriptFailure([
657        'def Func()',
658        'return "a"',
659        'enddef',
660        'defcompile'],
661        'E1096: Returning a value in a function without a return type')
662
663  CheckScriptFailure([
664        'def Func(): number',
665        'return',
666        'enddef',
667        'defcompile'], 'E1003:')
668
669  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
670  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
671  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
672
673  CheckScriptFailure([
674        'vim9script',
675        'def FuncB()',
676        '  return 123',
677        'enddef',
678        'def FuncA()',
679        '   FuncB()',
680        'enddef',
681        'defcompile'], 'E1096:')
682enddef
683
684def Test_arg_type_wrong()
685  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
686  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
687  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
688  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
689enddef
690
691def Test_vim9script_call()
692  let lines =<< trim END
693    vim9script
694    let var = ''
695    def MyFunc(arg: string)
696       var = arg
697    enddef
698    MyFunc('foobar')
699    var->assert_equal('foobar')
700
701    let str = 'barfoo'
702    str->MyFunc()
703    var->assert_equal('barfoo')
704
705    g:value = 'value'
706    g:value->MyFunc()
707    var->assert_equal('value')
708
709    let listvar = []
710    def ListFunc(arg: list<number>)
711       listvar = arg
712    enddef
713    [1, 2, 3]->ListFunc()
714    listvar->assert_equal([1, 2, 3])
715
716    let dictvar = {}
717    def DictFunc(arg: dict<number>)
718       dictvar = arg
719    enddef
720    {'a': 1, 'b': 2}->DictFunc()
721    dictvar->assert_equal(#{a: 1, b: 2})
722    def CompiledDict()
723      {'a': 3, 'b': 4}->DictFunc()
724    enddef
725    CompiledDict()
726    dictvar->assert_equal(#{a: 3, b: 4})
727
728    #{a: 3, b: 4}->DictFunc()
729    dictvar->assert_equal(#{a: 3, b: 4})
730
731    ('text')->MyFunc()
732    var->assert_equal('text')
733    ("some")->MyFunc()
734    var->assert_equal('some')
735
736    # line starting with single quote is not a mark
737    # line starting with double quote can be a method call
738    'asdfasdf'->MyFunc()
739    var->assert_equal('asdfasdf')
740    "xyz"->MyFunc()
741    var->assert_equal('xyz')
742
743    def UseString()
744      'xyork'->MyFunc()
745    enddef
746    UseString()
747    var->assert_equal('xyork')
748
749    def UseString2()
750      "knife"->MyFunc()
751    enddef
752    UseString2()
753    var->assert_equal('knife')
754
755    # prepending a colon makes it a mark
756    new
757    setline(1, ['aaa', 'bbb', 'ccc'])
758    normal! 3Gmt1G
759    :'t
760    getcurpos()[1]->assert_equal(3)
761    bwipe!
762
763    MyFunc(
764        'continued'
765        )
766    assert_equal('continued',
767            var
768            )
769
770    call MyFunc(
771        'more'
772          ..
773          'lines'
774        )
775    assert_equal(
776        'morelines',
777        var)
778  END
779  writefile(lines, 'Xcall.vim')
780  source Xcall.vim
781  delete('Xcall.vim')
782enddef
783
784def Test_vim9script_call_fail_decl()
785  let lines =<< trim END
786    vim9script
787    let var = ''
788    def MyFunc(arg: string)
789       let var = 123
790    enddef
791    defcompile
792  END
793  CheckScriptFailure(lines, 'E1054:')
794enddef
795
796def Test_vim9script_call_fail_type()
797  let lines =<< trim END
798    vim9script
799    def MyFunc(arg: string)
800      echo arg
801    enddef
802    MyFunc(1234)
803  END
804  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
805enddef
806
807def Test_vim9script_call_fail_const()
808  let lines =<< trim END
809    vim9script
810    const var = ''
811    def MyFunc(arg: string)
812       var = 'asdf'
813    enddef
814    defcompile
815  END
816  writefile(lines, 'Xcall_const.vim')
817  assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
818  delete('Xcall_const.vim')
819enddef
820
821" Test that inside :function a Python function can be defined, :def is not
822" recognized.
823func Test_function_python()
824  CheckFeature python3
825  let py = 'python3'
826  execute py "<< EOF"
827def do_something():
828  return 1
829EOF
830endfunc
831
832def Test_delfunc()
833  let lines =<< trim END
834    vim9script
835    def g:GoneSoon()
836      echo 'hello'
837    enddef
838
839    def CallGoneSoon()
840      GoneSoon()
841    enddef
842    defcompile
843
844    delfunc g:GoneSoon
845    CallGoneSoon()
846  END
847  writefile(lines, 'XToDelFunc')
848  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
849  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
850
851  delete('XToDelFunc')
852enddef
853
854def Test_redef_failure()
855  writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
856  so Xdef
857  writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
858  so Xdef
859  writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
860  assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
861  writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
862  so Xdef
863  delete('Xdef')
864
865  g:Func0()->assert_equal(0)
866  g:Func1()->assert_equal('Func1')
867  g:Func2()->assert_equal('Func2')
868
869  delfunc! Func0
870  delfunc! Func1
871  delfunc! Func2
872enddef
873
874def Test_vim9script_func()
875  let lines =<< trim END
876    vim9script
877    func Func(arg)
878      echo a:arg
879    endfunc
880    Func('text')
881  END
882  writefile(lines, 'XVim9Func')
883  so XVim9Func
884
885  delete('XVim9Func')
886enddef
887
888" Test for internal functions returning different types
889func Test_InternalFuncRetType()
890  let lines =<< trim END
891    def RetFloat(): float
892      return ceil(1.456)
893    enddef
894
895    def RetListAny(): list<any>
896      return items({'k': 'v'})
897    enddef
898
899    def RetListString(): list<string>
900      return split('a:b:c', ':')
901    enddef
902
903    def RetListDictAny(): list<dict<any>>
904      return getbufinfo()
905    enddef
906
907    def RetDictNumber(): dict<number>
908      return wordcount()
909    enddef
910
911    def RetDictString(): dict<string>
912      return environ()
913    enddef
914  END
915  call writefile(lines, 'Xscript')
916  source Xscript
917
918  call RetFloat()->assert_equal(2.0)
919  call RetListAny()->assert_equal([['k', 'v']])
920  call RetListString()->assert_equal(['a', 'b', 'c'])
921  call RetListDictAny()->assert_notequal([])
922  call RetDictNumber()->assert_notequal({})
923  call RetDictString()->assert_notequal({})
924  call delete('Xscript')
925endfunc
926
927" Test for passing too many or too few arguments to internal functions
928func Test_internalfunc_arg_error()
929  let l =<< trim END
930    def! FArgErr(): float
931      return ceil(1.1, 2)
932    enddef
933    defcompile
934  END
935  call writefile(l, 'Xinvalidarg')
936  call assert_fails('so Xinvalidarg', 'E118:', '', 1, 'FArgErr')
937  let l =<< trim END
938    def! FArgErr(): float
939      return ceil()
940    enddef
941    defcompile
942  END
943  call writefile(l, 'Xinvalidarg')
944  call assert_fails('so Xinvalidarg', 'E119:', '', 1, 'FArgErr')
945  call delete('Xinvalidarg')
946endfunc
947
948let s:funcResult = 0
949
950def FuncNoArgNoRet()
951  s:funcResult = 11
952enddef
953
954def FuncNoArgRetNumber(): number
955  s:funcResult = 22
956  return 1234
957enddef
958
959def FuncNoArgRetString(): string
960  s:funcResult = 45
961  return 'text'
962enddef
963
964def FuncOneArgNoRet(arg: number)
965  s:funcResult = arg
966enddef
967
968def FuncOneArgRetNumber(arg: number): number
969  s:funcResult = arg
970  return arg
971enddef
972
973def FuncTwoArgNoRet(one: bool, two: number)
974  s:funcResult = two
975enddef
976
977def FuncOneArgRetString(arg: string): string
978  return arg
979enddef
980
981def FuncOneArgRetAny(arg: any): any
982  return arg
983enddef
984
985def Test_func_type()
986  let Ref1: func()
987  s:funcResult = 0
988  Ref1 = FuncNoArgNoRet
989  Ref1()
990  s:funcResult->assert_equal(11)
991
992  let Ref2: func
993  s:funcResult = 0
994  Ref2 = FuncNoArgNoRet
995  Ref2()
996  s:funcResult->assert_equal(11)
997
998  s:funcResult = 0
999  Ref2 = FuncOneArgNoRet
1000  Ref2(12)
1001  s:funcResult->assert_equal(12)
1002
1003  s:funcResult = 0
1004  Ref2 = FuncNoArgRetNumber
1005  Ref2()->assert_equal(1234)
1006  s:funcResult->assert_equal(22)
1007
1008  s:funcResult = 0
1009  Ref2 = FuncOneArgRetNumber
1010  Ref2(13)->assert_equal(13)
1011  s:funcResult->assert_equal(13)
1012enddef
1013
1014def Test_repeat_return_type()
1015  let res = 0
1016  for n in repeat([1], 3)
1017    res += n
1018  endfor
1019  res->assert_equal(3)
1020
1021  res = 0
1022  for n in add([1, 2], 3)
1023    res += n
1024  endfor
1025  res->assert_equal(6)
1026enddef
1027
1028def Test_argv_return_type()
1029  next fileone filetwo
1030  let res = ''
1031  for name in argv()
1032    res ..= name
1033  endfor
1034  res->assert_equal('fileonefiletwo')
1035enddef
1036
1037def Test_func_type_part()
1038  let RefVoid: func: void
1039  RefVoid = FuncNoArgNoRet
1040  RefVoid = FuncOneArgNoRet
1041  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1042  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
1043
1044  let RefAny: func(): any
1045  RefAny = FuncNoArgRetNumber
1046  RefAny = FuncNoArgRetString
1047  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1048  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
1049
1050  let RefNr: func: number
1051  RefNr = FuncNoArgRetNumber
1052  RefNr = FuncOneArgRetNumber
1053  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1054  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
1055
1056  let RefStr: func: string
1057  RefStr = FuncNoArgRetString
1058  RefStr = FuncOneArgRetString
1059  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1060  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
1061enddef
1062
1063def Test_func_type_fails()
1064  CheckDefFailure(['let ref1: func()'], 'E704:')
1065
1066  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1067  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1068  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1069  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1070  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1071  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
1072
1073  CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
1074  CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
1075  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:')
1076  CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
1077enddef
1078
1079def Test_func_return_type()
1080  let nr: number
1081  nr = FuncNoArgRetNumber()
1082  nr->assert_equal(1234)
1083
1084  nr = FuncOneArgRetAny(122)
1085  nr->assert_equal(122)
1086
1087  let str: string
1088  str = FuncOneArgRetAny('yes')
1089  str->assert_equal('yes')
1090
1091  CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
1092enddef
1093
1094def MultiLine(
1095    arg1: string,
1096    arg2 = 1234,
1097    ...rest: list<string>
1098      ): string
1099  return arg1 .. arg2 .. join(rest, '-')
1100enddef
1101
1102def MultiLineComment(
1103    arg1: string, # comment
1104    arg2 = 1234, # comment
1105    ...rest: list<string> # comment
1106      ): string # comment
1107  return arg1 .. arg2 .. join(rest, '-')
1108enddef
1109
1110def Test_multiline()
1111  MultiLine('text')->assert_equal('text1234')
1112  MultiLine('text', 777)->assert_equal('text777')
1113  MultiLine('text', 777, 'one')->assert_equal('text777one')
1114  MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1115enddef
1116
1117func Test_multiline_not_vim9()
1118  call MultiLine('text')->assert_equal('text1234')
1119  call MultiLine('text', 777)->assert_equal('text777')
1120  call MultiLine('text', 777, 'one')->assert_equal('text777one')
1121  call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1122endfunc
1123
1124
1125" When using CheckScriptFailure() for the below test, E1010 is generated instead
1126" of E1056.
1127func Test_E1056_1059()
1128  let caught_1056 = 0
1129  try
1130    def F():
1131      return 1
1132    enddef
1133  catch /E1056:/
1134    let caught_1056 = 1
1135  endtry
1136  eval caught_1056->assert_equal(1)
1137
1138  let caught_1059 = 0
1139  try
1140    def F5(items : list)
1141      echo 'a'
1142    enddef
1143  catch /E1059:/
1144    let caught_1059 = 1
1145  endtry
1146  eval caught_1059->assert_equal(1)
1147endfunc
1148
1149func DelMe()
1150  echo 'DelMe'
1151endfunc
1152
1153def Test_error_reporting()
1154  # comment lines at the start of the function
1155  let lines =<< trim END
1156    " comment
1157    def Func()
1158      # comment
1159      # comment
1160      invalid
1161    enddef
1162    defcompile
1163  END
1164  writefile(lines, 'Xdef')
1165  try
1166    source Xdef
1167    assert_report('should have failed')
1168  catch /E476:/
1169    v:exception->assert_match('Invalid command: invalid')
1170    v:throwpoint->assert_match(', line 3$')
1171  endtry
1172
1173  # comment lines after the start of the function
1174  lines =<< trim END
1175    " comment
1176    def Func()
1177      let x = 1234
1178      # comment
1179      # comment
1180      invalid
1181    enddef
1182    defcompile
1183  END
1184  writefile(lines, 'Xdef')
1185  try
1186    source Xdef
1187    assert_report('should have failed')
1188  catch /E476:/
1189    v:exception->assert_match('Invalid command: invalid')
1190    v:throwpoint->assert_match(', line 4$')
1191  endtry
1192
1193  lines =<< trim END
1194    vim9script
1195    def Func()
1196      let db = #{foo: 1, bar: 2}
1197      # comment
1198      let x = db.asdf
1199    enddef
1200    defcompile
1201    Func()
1202  END
1203  writefile(lines, 'Xdef')
1204  try
1205    source Xdef
1206    assert_report('should have failed')
1207  catch /E716:/
1208    v:throwpoint->assert_match('_Func, line 3$')
1209  endtry
1210
1211  delete('Xdef')
1212enddef
1213
1214def Test_deleted_function()
1215  CheckDefExecFailure([
1216      'let RefMe: func = function("g:DelMe")',
1217      'delfunc g:DelMe',
1218      'echo RefMe()'], 'E117:')
1219enddef
1220
1221def Test_unknown_function()
1222  CheckDefExecFailure([
1223      'let Ref: func = function("NotExist")',
1224      'delfunc g:NotExist'], 'E700:')
1225enddef
1226
1227def RefFunc(Ref: func(string): string): string
1228  return Ref('more')
1229enddef
1230
1231def Test_closure_simple()
1232  let local = 'some '
1233  RefFunc({s -> local .. s})->assert_equal('some more')
1234enddef
1235
1236def MakeRef()
1237  let local = 'some '
1238  g:Ref = {s -> local .. s}
1239enddef
1240
1241def Test_closure_ref_after_return()
1242  MakeRef()
1243  g:Ref('thing')->assert_equal('some thing')
1244  unlet g:Ref
1245enddef
1246
1247def MakeTwoRefs()
1248  let local = ['some']
1249  g:Extend = {s -> local->add(s)}
1250  g:Read = {-> local}
1251enddef
1252
1253def Test_closure_two_refs()
1254  MakeTwoRefs()
1255  join(g:Read(), ' ')->assert_equal('some')
1256  g:Extend('more')
1257  join(g:Read(), ' ')->assert_equal('some more')
1258  g:Extend('even')
1259  join(g:Read(), ' ')->assert_equal('some more even')
1260
1261  unlet g:Extend
1262  unlet g:Read
1263enddef
1264
1265def ReadRef(Ref: func(): list<string>): string
1266  return join(Ref(), ' ')
1267enddef
1268
1269def ExtendRef(Ref: func(string): list<string>, add: string)
1270  Ref(add)
1271enddef
1272
1273def Test_closure_two_indirect_refs()
1274  MakeTwoRefs()
1275  ReadRef(g:Read)->assert_equal('some')
1276  ExtendRef(g:Extend, 'more')
1277  ReadRef(g:Read)->assert_equal('some more')
1278  ExtendRef(g:Extend, 'even')
1279  ReadRef(g:Read)->assert_equal('some more even')
1280
1281  unlet g:Extend
1282  unlet g:Read
1283enddef
1284
1285def MakeArgRefs(theArg: string)
1286  let local = 'loc_val'
1287  g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
1288enddef
1289
1290def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
1291  let local = 'the_loc'
1292  g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
1293enddef
1294
1295def Test_closure_using_argument()
1296  MakeArgRefs('arg_val')
1297  g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
1298
1299  MakeArgRefsVarargs('arg_val', 'one', 'two')
1300  g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
1301
1302  unlet g:UseArg
1303  unlet g:UseVararg
1304enddef
1305
1306def MakeGetAndAppendRefs()
1307  let local = 'a'
1308
1309  def Append(arg: string)
1310    local ..= arg
1311  enddef
1312  g:Append = Append
1313
1314  def Get(): string
1315    return local
1316  enddef
1317  g:Get = Get
1318enddef
1319
1320def Test_closure_append_get()
1321  MakeGetAndAppendRefs()
1322  g:Get()->assert_equal('a')
1323  g:Append('-b')
1324  g:Get()->assert_equal('a-b')
1325  g:Append('-c')
1326  g:Get()->assert_equal('a-b-c')
1327
1328  unlet g:Append
1329  unlet g:Get
1330enddef
1331
1332def Test_nested_closure()
1333  let local = 'text'
1334  def Closure(arg: string): string
1335    return local .. arg
1336  enddef
1337  Closure('!!!')->assert_equal('text!!!')
1338enddef
1339
1340func GetResult(Ref)
1341  return a:Ref('some')
1342endfunc
1343
1344def Test_call_closure_not_compiled()
1345  let text = 'text'
1346  g:Ref = {s ->  s .. text}
1347  GetResult(g:Ref)->assert_equal('sometext')
1348enddef
1349
1350def Test_double_closure_fails()
1351  let lines =<< trim END
1352    vim9script
1353    def Func()
1354    let var = 0
1355    for i in range(2)
1356	timer_start(0, {-> var})
1357    endfor
1358    enddef
1359    Func()
1360  END
1361  CheckScriptFailure(lines, 'Multiple closures not supported yet')
1362enddef
1363
1364def Test_sort_return_type()
1365  let res: list<number>
1366  res = [1, 2, 3]->sort()
1367enddef
1368
1369def Test_sort_argument()
1370  let res = ['b', 'a', 'c']->sort('i')
1371  res->assert_equal(['a', 'b', 'c'])
1372enddef
1373
1374def Test_getqflist_return_type()
1375  let l = getqflist()
1376  l->assert_equal([])
1377
1378  let d = getqflist(#{items: 0})
1379  d->assert_equal(#{items: []})
1380enddef
1381
1382def Test_getloclist_return_type()
1383  let l = getloclist(1)
1384  l->assert_equal([])
1385
1386  let d = getloclist(1, #{items: 0})
1387  d->assert_equal(#{items: []})
1388enddef
1389
1390def Test_copy_return_type()
1391  let l = copy([1, 2, 3])
1392  let res = 0
1393  for n in l
1394    res += n
1395  endfor
1396  res->assert_equal(6)
1397
1398  let dl = deepcopy([1, 2, 3])
1399  res = 0
1400  for n in dl
1401    res += n
1402  endfor
1403  res->assert_equal(6)
1404
1405  dl = deepcopy([1, 2, 3], true)
1406enddef
1407
1408def Test_extend_return_type()
1409  let l = extend([1, 2], [3])
1410  let res = 0
1411  for n in l
1412    res += n
1413  endfor
1414  res->assert_equal(6)
1415enddef
1416
1417def Test_garbagecollect()
1418  garbagecollect(true)
1419enddef
1420
1421def Test_insert_return_type()
1422  let l = insert([2, 1], 3)
1423  let res = 0
1424  for n in l
1425    res += n
1426  endfor
1427  res->assert_equal(6)
1428enddef
1429
1430def Test_keys_return_type()
1431  const var: list<string> = #{a: 1, b: 2}->keys()
1432  var->assert_equal(['a', 'b'])
1433enddef
1434
1435def Test_reverse_return_type()
1436  let l = reverse([1, 2, 3])
1437  let res = 0
1438  for n in l
1439    res += n
1440  endfor
1441  res->assert_equal(6)
1442enddef
1443
1444def Test_remove_return_type()
1445  let l = remove(#{one: [1, 2], two: [3, 4]}, 'one')
1446  let res = 0
1447  for n in l
1448    res += n
1449  endfor
1450  res->assert_equal(3)
1451enddef
1452
1453def Test_filter_return_type()
1454  let l = filter([1, 2, 3], {-> 1})
1455  let res = 0
1456  for n in l
1457    res += n
1458  endfor
1459  res->assert_equal(6)
1460enddef
1461
1462def Test_bufnr()
1463  let buf = bufnr()
1464  bufnr('%')->assert_equal(buf)
1465
1466  buf = bufnr('Xdummy', true)
1467  buf->assert_notequal(-1)
1468  exe 'bwipe! ' .. buf
1469enddef
1470
1471def Test_col()
1472  new
1473  setline(1, 'asdf')
1474  col([1, '$'])->assert_equal(5)
1475enddef
1476
1477def Test_char2nr()
1478  char2nr('あ', true)->assert_equal(12354)
1479enddef
1480
1481def Test_getreg_return_type()
1482  let s1: string = getreg('"')
1483  let s2: string = getreg('"', 1)
1484  let s3: list<string> = getreg('"', 1, 1)
1485enddef
1486
1487def Wrong_dict_key_type(items: list<number>): list<number>
1488  return filter(items, {_, val -> get({val: 1}, 'x')})
1489enddef
1490
1491def Test_wrong_dict_key_type()
1492  assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1012:')
1493enddef
1494
1495def Line_continuation_in_def(dir: string = ''): string
1496    let path: string = empty(dir)
1497            \ ? 'empty'
1498            \ : 'full'
1499    return path
1500enddef
1501
1502def Test_line_continuation_in_def()
1503  Line_continuation_in_def('.')->assert_equal('full')
1504enddef
1505
1506def Line_continuation_in_lambda(): list<string>
1507  let x = range(97, 100)
1508      ->map({_, v -> nr2char(v)
1509          ->toupper()})
1510      ->reverse()
1511  return x
1512enddef
1513
1514def Test_line_continuation_in_lambda()
1515  Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
1516enddef
1517
1518func Test_silent_echo()
1519  CheckScreendump
1520
1521  let lines =<< trim END
1522    vim9script
1523    def EchoNothing()
1524      silent echo ''
1525    enddef
1526    defcompile
1527  END
1528  call writefile(lines, 'XTest_silent_echo')
1529
1530  " Check that the balloon shows up after a mouse move
1531  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
1532  call term_sendkeys(buf, ":abc")
1533  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
1534
1535  " clean up
1536  call StopVimInTerminal(buf)
1537  call delete('XTest_silent_echo')
1538endfunc
1539
1540""""""" builtin functions that behave differently in Vim9
1541
1542def Test_bufname()
1543  split SomeFile
1544  bufname('%')->assert_equal('SomeFile')
1545  edit OtherFile
1546  bufname('#')->assert_equal('SomeFile')
1547  close
1548enddef
1549
1550def Test_bufwinid()
1551  let origwin = win_getid()
1552  below split SomeFile
1553  let SomeFileID = win_getid()
1554  below split OtherFile
1555  below split SomeFile
1556  bufwinid('SomeFile')->assert_equal(SomeFileID)
1557
1558  win_gotoid(origwin)
1559  only
1560  bwipe SomeFile
1561  bwipe OtherFile
1562enddef
1563
1564def Test_count()
1565  count('ABC ABC ABC', 'b', true)->assert_equal(3)
1566  count('ABC ABC ABC', 'b', false)->assert_equal(0)
1567enddef
1568
1569def Test_expand()
1570  split SomeFile
1571  expand('%', true, true)->assert_equal(['SomeFile'])
1572  close
1573enddef
1574
1575def Test_getbufinfo()
1576  let bufinfo = getbufinfo(bufnr())
1577  getbufinfo('%')->assert_equal(bufinfo)
1578
1579  edit Xtestfile1
1580  hide edit Xtestfile2
1581  hide enew
1582  getbufinfo(#{bufloaded: true, buflisted: true, bufmodified: false})
1583      ->len()->assert_equal(3)
1584  bwipe Xtestfile1 Xtestfile2
1585enddef
1586
1587def Test_getbufline()
1588  e SomeFile
1589  let buf = bufnr()
1590  e #
1591  let lines = ['aaa', 'bbb', 'ccc']
1592  setbufline(buf, 1, lines)
1593  getbufline('#', 1, '$')->assert_equal(lines)
1594
1595  bwipe!
1596enddef
1597
1598def Test_getchangelist()
1599  new
1600  setline(1, 'some text')
1601  let changelist = bufnr()->getchangelist()
1602  getchangelist('%')->assert_equal(changelist)
1603  bwipe!
1604enddef
1605
1606def Test_getchar()
1607  while getchar(0)
1608  endwhile
1609  getchar(true)->assert_equal(0)
1610enddef
1611
1612def Test_getcompletion()
1613  set wildignore=*.vim,*~
1614  let l = getcompletion('run', 'file', true)
1615  l->assert_equal([])
1616  set wildignore&
1617enddef
1618
1619def Test_getreg()
1620  let lines = ['aaa', 'bbb', 'ccc']
1621  setreg('a', lines)
1622  getreg('a', true, true)->assert_equal(lines)
1623enddef
1624
1625def Test_glob()
1626  glob('runtest.vim', true, true, true)->assert_equal(['runtest.vim'])
1627enddef
1628
1629def Test_globpath()
1630  globpath('.', 'runtest.vim', true, true, true)->assert_equal(['./runtest.vim'])
1631enddef
1632
1633def Test_has()
1634  has('eval', true)->assert_equal(1)
1635enddef
1636
1637def Test_hasmapto()
1638  hasmapto('foobar', 'i', true)->assert_equal(0)
1639  iabbrev foo foobar
1640  hasmapto('foobar', 'i', true)->assert_equal(1)
1641  iunabbrev foo
1642enddef
1643
1644def Test_index()
1645  index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
1646enddef
1647
1648def Test_list2str_str2list_utf8()
1649  let s = "\u3042\u3044"
1650  let l = [0x3042, 0x3044]
1651  str2list(s, true)->assert_equal(l)
1652  list2str(l, true)->assert_equal(s)
1653enddef
1654
1655def SID(): number
1656  return expand('<SID>')
1657          ->matchstr('<SNR>\zs\d\+\ze_$')
1658          ->str2nr()
1659enddef
1660
1661def Test_maparg()
1662  let lnum = str2nr(expand('<sflnum>'))
1663  map foo bar
1664  maparg('foo', '', false, true)->assert_equal(#{
1665        lnum: lnum + 1,
1666        script: 0,
1667        mode: ' ',
1668        silent: 0,
1669        noremap: 0,
1670        lhs: 'foo',
1671        lhsraw: 'foo',
1672        nowait: 0,
1673        expr: 0,
1674        sid: SID(),
1675        rhs: 'bar',
1676        buffer: 0})
1677  unmap foo
1678enddef
1679
1680def Test_mapcheck()
1681  iabbrev foo foobar
1682  mapcheck('foo', 'i', true)->assert_equal('foobar')
1683  iunabbrev foo
1684enddef
1685
1686def Test_nr2char()
1687  nr2char(97, true)->assert_equal('a')
1688enddef
1689
1690def Test_readdir()
1691   eval expand('sautest')->readdir({e -> e[0] !=# '.'})
1692   eval expand('sautest')->readdirex({e -> e.name[0] !=# '.'})
1693enddef
1694
1695def Test_search()
1696  new
1697  setline(1, ['foo', 'bar'])
1698  let val = 0
1699  # skip expr returns boolean
1700  search('bar', 'W', 0, 0, {-> val == 1})->assert_equal(2)
1701  :1
1702  search('bar', 'W', 0, 0, {-> val == 0})->assert_equal(0)
1703  # skip expr returns number, only 0 and 1 are accepted
1704  :1
1705  search('bar', 'W', 0, 0, {-> 0})->assert_equal(2)
1706  :1
1707  search('bar', 'W', 0, 0, {-> 1})->assert_equal(0)
1708  assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:')
1709  assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:')
1710enddef
1711
1712def Test_searchcount()
1713  new
1714  setline(1, "foo bar")
1715  :/foo
1716  searchcount(#{recompute: true})
1717      ->assert_equal(#{
1718          exact_match: 1,
1719          current: 1,
1720          total: 1,
1721          maxcount: 99,
1722          incomplete: 0})
1723  bwipe!
1724enddef
1725
1726def Test_searchdecl()
1727  searchdecl('blah', true, true)->assert_equal(1)
1728enddef
1729
1730def Test_setbufvar()
1731  setbufvar(bufnr('%'), '&syntax', 'vim')
1732  &syntax->assert_equal('vim')
1733  setbufvar(bufnr('%'), '&ts', 16)
1734  &ts->assert_equal(16)
1735  settabwinvar(1, 1, '&syntax', 'vam')
1736  &syntax->assert_equal('vam')
1737  settabwinvar(1, 1, '&ts', 15)
1738  &ts->assert_equal(15)
1739  setlocal ts=8
1740
1741  setbufvar('%', 'myvar', 123)
1742  getbufvar('%', 'myvar')->assert_equal(123)
1743enddef
1744
1745def Test_setloclist()
1746  let items = [#{filename: '/tmp/file', lnum: 1, valid: true}]
1747  let what = #{items: items}
1748  setqflist([], ' ', what)
1749  setloclist(0, [], ' ', what)
1750enddef
1751
1752def Test_setreg()
1753  setreg('a', ['aaa', 'bbb', 'ccc'])
1754  let reginfo = getreginfo('a')
1755  setreg('a', reginfo)
1756  getreginfo('a')->assert_equal(reginfo)
1757enddef
1758
1759def Test_spellsuggest()
1760  if !has('spell')
1761    MissingFeature 'spell'
1762  else
1763    spellsuggest('marrch', 1, true)->assert_equal(['March'])
1764  endif
1765enddef
1766
1767def Test_split()
1768  split('  aa  bb  ', '\W\+', true)->assert_equal(['', 'aa', 'bb', ''])
1769enddef
1770
1771def Test_str2nr()
1772  str2nr("1'000'000", 10, true)->assert_equal(1000000)
1773enddef
1774
1775def Test_strchars()
1776  strchars("A\u20dd", true)->assert_equal(1)
1777enddef
1778
1779def Test_submatch()
1780  let pat = 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)'
1781  let Rep = {-> range(10)->map({_, v -> submatch(v, true)})->string()}
1782  let actual = substitute('A123456789', pat, Rep, '')
1783  let expected = "[['A123456789'], ['1'], ['2'], ['3'], ['4'], ['5'], ['6'], ['7'], ['8'], ['9']]"
1784  actual->assert_equal(expected)
1785enddef
1786
1787def Test_synID()
1788  new
1789  setline(1, "text")
1790  synID(1, 1, true)->assert_equal(0)
1791  bwipe!
1792enddef
1793
1794def Test_term_gettty()
1795  if !has('terminal')
1796    MissingFeature 'terminal'
1797  else
1798    let buf = Run_shell_in_terminal({})
1799    term_gettty(buf, true)->assert_notequal('')
1800    StopShellInTerminal(buf)
1801  endif
1802enddef
1803
1804def Test_term_start()
1805  if !has('terminal')
1806    MissingFeature 'terminal'
1807  else
1808    botright new
1809    let winnr = winnr()
1810    term_start(&shell, #{curwin: true})
1811    winnr()->assert_equal(winnr)
1812    bwipe!
1813  endif
1814enddef
1815
1816def Test_timer_paused()
1817  let id = timer_start(50, {-> 0})
1818  timer_pause(id, true)
1819  let info = timer_info(id)
1820  info[0]['paused']->assert_equal(1)
1821  timer_stop(id)
1822enddef
1823
1824def Test_win_splitmove()
1825  split
1826  win_splitmove(1, 2, #{vertical: true, rightbelow: true})
1827  close
1828enddef
1829
1830""""""" end of builtin functions
1831
1832def Fibonacci(n: number): number
1833  if n < 2
1834    return n
1835  else
1836    return Fibonacci(n - 1) + Fibonacci(n - 2)
1837  endif
1838enddef
1839
1840def Test_recursive_call()
1841  Fibonacci(20)->assert_equal(6765)
1842enddef
1843
1844def TreeWalk(dir: string): list<any>
1845  return readdir(dir)->map({_, val ->
1846            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
1847               ? {val: TreeWalk(dir .. '/' .. val)}
1848               : val
1849             })
1850enddef
1851
1852def Test_closure_in_map()
1853  mkdir('XclosureDir/tdir', 'p')
1854  writefile(['111'], 'XclosureDir/file1')
1855  writefile(['222'], 'XclosureDir/file2')
1856  writefile(['333'], 'XclosureDir/tdir/file3')
1857
1858  TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {'tdir': ['file3']}])
1859
1860  delete('XclosureDir', 'rf')
1861enddef
1862
1863def Test_partial_call()
1864  let Xsetlist = function('setloclist', [0])
1865  Xsetlist([], ' ', {'title': 'test'})
1866  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1867
1868  Xsetlist = function('setloclist', [0, [], ' '])
1869  Xsetlist({'title': 'test'})
1870  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1871
1872  Xsetlist = function('setqflist')
1873  Xsetlist([], ' ', {'title': 'test'})
1874  getqflist({'title': 1})->assert_equal({'title': 'test'})
1875
1876  Xsetlist = function('setqflist', [[], ' '])
1877  Xsetlist({'title': 'test'})
1878  getqflist({'title': 1})->assert_equal({'title': 'test'})
1879enddef
1880
1881def Test_cmd_modifier()
1882  tab echo '0'
1883  CheckDefFailure(['5tab echo 3'], 'E16:')
1884enddef
1885
1886def Test_restore_modifiers()
1887  # check that when compiling a :def function command modifiers are not messed
1888  # up.
1889  let lines =<< trim END
1890      vim9script
1891      set eventignore=
1892      autocmd QuickFixCmdPost * copen
1893      def AutocmdsDisabled()
1894          eval 0
1895      enddef
1896      func Func()
1897        noautocmd call s:AutocmdsDisabled()
1898        let g:ei_after = &eventignore
1899      endfunc
1900      Func()
1901  END
1902  CheckScriptSuccess(lines)
1903  g:ei_after->assert_equal('')
1904enddef
1905
1906def StackTop()
1907  eval 1
1908  eval 2
1909  # call not on fourth line
1910  StackBot()
1911enddef
1912
1913def StackBot()
1914  # throw an error
1915  eval [][0]
1916enddef
1917
1918def Test_callstack_def()
1919  try
1920    StackTop()
1921  catch
1922    v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
1923  endtry
1924enddef
1925
1926
1927" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1928