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