1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source view_util.vim
5source vim9.vim
6source screendump.vim
7
8func Test_def_basic()
9  def SomeFunc(): string
10    return 'yes'
11  enddef
12  call assert_equal('yes', SomeFunc())
13endfunc
14
15def ReturnString(): string
16  return 'string'
17enddef
18
19def ReturnNumber(): number
20  return 123
21enddef
22
23let g:notNumber = 'string'
24
25def ReturnGlobal(): number
26  return g:notNumber
27enddef
28
29def Test_return_something()
30  assert_equal('string', ReturnString())
31  assert_equal(123, ReturnNumber())
32  assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string')
33enddef
34
35def Test_missing_return()
36  CheckDefFailure(['def Missing(): number',
37                   '  if g:cond',
38                   '    echo "no return"',
39                   '  else',
40                   '    return 0',
41                   '  endif'
42                   'enddef'], 'E1027:')
43  CheckDefFailure(['def Missing(): number',
44                   '  if g:cond',
45                   '    return 1',
46                   '  else',
47                   '    echo "no return"',
48                   '  endif'
49                   'enddef'], 'E1027:')
50  CheckDefFailure(['def Missing(): number',
51                   '  if g:cond',
52                   '    return 1',
53                   '  else',
54                   '    return 2',
55                   '  endif'
56                   '  return 3'
57                   'enddef'], 'E1095:')
58enddef
59
60let s:nothing = 0
61def ReturnNothing()
62  s:nothing = 1
63  if true
64    return
65  endif
66  s:nothing = 2
67enddef
68
69def Test_return_nothing()
70  ReturnNothing()
71  assert_equal(1, s:nothing)
72enddef
73
74func Increment()
75  let g:counter += 1
76endfunc
77
78def Test_call_ufunc_count()
79  g:counter = 1
80  Increment()
81  Increment()
82  Increment()
83  # works with and without :call
84  assert_equal(4, g:counter)
85  call assert_equal(4, g:counter)
86  unlet g:counter
87enddef
88
89def MyVarargs(arg: string, ...rest: list<string>): string
90  let res = arg
91  for s in rest
92    res ..= ',' .. s
93  endfor
94  return res
95enddef
96
97def Test_call_varargs()
98  assert_equal('one', MyVarargs('one'))
99  assert_equal('one,two', MyVarargs('one', 'two'))
100  assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
101enddef
102
103def MyDefaultArgs(name = 'string'): string
104  return name
105enddef
106
107def MyDefaultSecond(name: string, second: bool  = true): string
108  return second ? name : 'none'
109enddef
110
111def Test_call_default_args()
112  assert_equal('string', MyDefaultArgs())
113  assert_equal('one', MyDefaultArgs('one'))
114  assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
115
116  assert_equal('test', MyDefaultSecond('test'))
117  assert_equal('test', MyDefaultSecond('test', true))
118  assert_equal('none', MyDefaultSecond('test', false))
119
120  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
121  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: argument 1: type mismatch, expected number but got string')
122enddef
123
124def Test_nested_function()
125  def Nested(arg: string): string
126    return 'nested ' .. arg
127  enddef
128  assert_equal('nested function', Nested('function'))
129
130  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
131  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
132
133  CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
134  CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
135  CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
136enddef
137
138func Test_call_default_args_from_func()
139  call assert_equal('string', MyDefaultArgs())
140  call assert_equal('one', MyDefaultArgs('one'))
141  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
142endfunc
143
144def Test_nested_global_function()
145  let lines =<< trim END
146      vim9script
147      def Outer()
148          def g:Inner(): string
149              return 'inner'
150          enddef
151      enddef
152      defcompile
153      Outer()
154      assert_equal('inner', g:Inner())
155      delfunc g:Inner
156      Outer()
157      assert_equal('inner', g:Inner())
158      delfunc g:Inner
159      Outer()
160      assert_equal('inner', g:Inner())
161      delfunc g:Inner
162  END
163  CheckScriptSuccess(lines)
164
165  lines =<< trim END
166      vim9script
167      def Outer()
168          def g:Inner(): string
169              return 'inner'
170          enddef
171      enddef
172      defcompile
173      Outer()
174      Outer()
175  END
176  CheckScriptFailure(lines, "E122:")
177
178  lines =<< trim END
179      vim9script
180      def Func()
181        echo 'script'
182      enddef
183      def Outer()
184        def Func()
185          echo 'inner'
186        enddef
187      enddef
188      defcompile
189  END
190  CheckScriptFailure(lines, "E1073:")
191enddef
192
193def Test_global_local_function()
194  let lines =<< trim END
195      vim9script
196      def g:Func(): string
197          return 'global'
198      enddef
199      def Func(): string
200          return 'local'
201      enddef
202      assert_equal('global', g:Func())
203      assert_equal('local', Func())
204  END
205  CheckScriptSuccess(lines)
206enddef
207
208func TakesOneArg(arg)
209  echo a:arg
210endfunc
211
212def Test_call_wrong_args()
213  call CheckDefFailure(['TakesOneArg()'], 'E119:')
214  call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
215  call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
216  call CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
217enddef
218
219" Default arg and varargs
220def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
221  let res = one .. ',' .. two
222  for s in rest
223    res ..= ',' .. s
224  endfor
225  return res
226enddef
227
228def Test_call_def_varargs()
229  call assert_fails('call MyDefVarargs()', 'E119:')
230  assert_equal('one,foo', MyDefVarargs('one'))
231  assert_equal('one,two', MyDefVarargs('one', 'two'))
232  assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
233  CheckDefFailure(['MyDefVarargs("one", 22)'],
234      'E1013: argument 2: type mismatch, expected string but got number')
235  CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
236      'E1013: argument 3: type mismatch, expected string but got number')
237
238  let lines =<< trim END
239      vim9script
240      def Func(...l: list<string>)
241        echo l
242      enddef
243      Func('a', 'b', 'c')
244  END
245  CheckScriptSuccess(lines)
246
247  lines =<< trim END
248      vim9script
249      def Func(...l: list<string>)
250        echo l
251      enddef
252      Func()
253  END
254  CheckScriptSuccess(lines)
255
256  lines =<< trim END
257      vim9script
258      def Func(...l: list<string>)
259        echo l
260      enddef
261      Func(1, 2, 3)
262  END
263  CheckScriptFailure(lines, 'E1013:')
264
265  lines =<< trim END
266      vim9script
267      def Func(...l: list<string>)
268        echo l
269      enddef
270      Func('a', 9)
271  END
272  CheckScriptFailure(lines, 'E1013:')
273
274  lines =<< trim END
275      vim9script
276      def Func(...l: list<string>)
277        echo l
278      enddef
279      Func(1, 'a')
280  END
281  CheckScriptFailure(lines, 'E1013:')
282enddef
283
284let s:value = ''
285
286def FuncOneDefArg(opt = 'text')
287  s:value = opt
288enddef
289
290def FuncTwoDefArg(nr = 123, opt = 'text'): string
291  return nr .. opt
292enddef
293
294def FuncVarargs(...arg: list<string>): string
295  return join(arg, ',')
296enddef
297
298def Test_func_type_varargs()
299  let RefDefArg: func(?string)
300  RefDefArg = FuncOneDefArg
301  RefDefArg()
302  assert_equal('text', s:value)
303  RefDefArg('some')
304  assert_equal('some', s:value)
305
306  let RefDef2Arg: func(?number, ?string): string
307  RefDef2Arg = FuncTwoDefArg
308  assert_equal('123text', RefDef2Arg())
309  assert_equal('99text', RefDef2Arg(99))
310  assert_equal('77some', RefDef2Arg(77, 'some'))
311
312  call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:')
313  call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:')
314
315  let RefVarargs: func(...list<string>): string
316  RefVarargs = FuncVarargs
317  assert_equal('', RefVarargs())
318  assert_equal('one', RefVarargs('one'))
319  assert_equal('one,two', RefVarargs('one', 'two'))
320
321  call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:')
322  call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:')
323enddef
324
325" Only varargs
326def MyVarargsOnly(...args: list<string>): string
327  return join(args, ',')
328enddef
329
330def Test_call_varargs_only()
331  assert_equal('', MyVarargsOnly())
332  assert_equal('one', MyVarargsOnly('one'))
333  assert_equal('one,two', MyVarargsOnly('one', 'two'))
334  call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
335  call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
336enddef
337
338def Test_using_var_as_arg()
339  call writefile(['def Func(x: number)',  'let x = 234', 'enddef', 'defcompile'], 'Xdef')
340  call assert_fails('so Xdef', 'E1006:')
341  call delete('Xdef')
342enddef
343
344def DictArg(arg: dict<string>)
345  arg['key'] = 'value'
346enddef
347
348def ListArg(arg: list<string>)
349  arg[0] = 'value'
350enddef
351
352def Test_assign_to_argument()
353  # works for dict and list
354  let d: dict<string> = {}
355  DictArg(d)
356  assert_equal('value', d['key'])
357  let l: list<string> = []
358  ListArg(l)
359  assert_equal('value', l[0])
360
361  call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
362enddef
363
364def Test_call_func_defined_later()
365  call assert_equal('one', g:DefinedLater('one'))
366  call assert_fails('call NotDefined("one")', 'E117:')
367enddef
368
369func DefinedLater(arg)
370  return a:arg
371endfunc
372
373def Test_call_funcref()
374  assert_equal(3, g:SomeFunc('abc'))
375  assert_fails('NotAFunc()', 'E117:') # comment after call
376  assert_fails('g:NotAFunc()', 'E117:')
377
378  let lines =<< trim END
379    vim9script
380    def RetNumber(): number
381      return 123
382    enddef
383    let Funcref: func: number = function('RetNumber')
384    assert_equal(123, Funcref())
385  END
386  CheckScriptSuccess(lines)
387
388  lines =<< trim END
389    vim9script
390    def RetNumber(): number
391      return 123
392    enddef
393    def Bar(F: func: number): number
394      return F()
395    enddef
396    let Funcref = function('RetNumber')
397    assert_equal(123, Bar(Funcref))
398  END
399  CheckScriptSuccess(lines)
400
401  lines =<< trim END
402    vim9script
403    def UseNumber(nr: number)
404      echo nr
405    enddef
406    let Funcref: func(number) = function('UseNumber')
407    Funcref(123)
408  END
409  CheckScriptSuccess(lines)
410
411  lines =<< trim END
412    vim9script
413    def UseNumber(nr: number)
414      echo nr
415    enddef
416    let Funcref: func(string) = function('UseNumber')
417  END
418  CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)')
419
420  lines =<< trim END
421    vim9script
422    def EchoNr(nr = 34)
423      g:echo = nr
424    enddef
425    let Funcref: func(?number) = function('EchoNr')
426    Funcref()
427    assert_equal(34, g:echo)
428    Funcref(123)
429    assert_equal(123, g:echo)
430  END
431  CheckScriptSuccess(lines)
432
433  lines =<< trim END
434    vim9script
435    def EchoList(...l: list<number>)
436      g:echo = l
437    enddef
438    let Funcref: func(...list<number>) = function('EchoList')
439    Funcref()
440    assert_equal([], g:echo)
441    Funcref(1, 2, 3)
442    assert_equal([1, 2, 3], g:echo)
443  END
444  CheckScriptSuccess(lines)
445
446  lines =<< trim END
447    vim9script
448    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
449      g:optarg = opt
450      g:listarg = l
451      return nr
452    enddef
453    let Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
454    assert_equal(10, Funcref(10))
455    assert_equal(12, g:optarg)
456    assert_equal([], g:listarg)
457
458    assert_equal(11, Funcref(11, 22))
459    assert_equal(22, g:optarg)
460    assert_equal([], g:listarg)
461
462    assert_equal(17, Funcref(17, 18, 1, 2, 3))
463    assert_equal(18, g:optarg)
464    assert_equal([1, 2, 3], g:listarg)
465  END
466  CheckScriptSuccess(lines)
467enddef
468
469let SomeFunc = function('len')
470let NotAFunc = 'text'
471
472def CombineFuncrefTypes()
473  # same arguments, different return type
474  let Ref1: func(bool): string
475  let Ref2: func(bool): number
476  let Ref3: func(bool): any
477  Ref3 = g:cond ? Ref1 : Ref2
478
479  # different number of arguments
480  let Refa1: func(bool): number
481  let Refa2: func(bool, number): number
482  let Refa3: func: number
483  Refa3 = g:cond ? Refa1 : Refa2
484
485  # different argument types
486  let Refb1: func(bool, string): number
487  let Refb2: func(string, number): number
488  let Refb3: func(any, any): number
489  Refb3 = g:cond ? Refb1 : Refb2
490enddef
491
492def FuncWithForwardCall()
493  return g:DefinedEvenLater("yes")
494enddef
495
496def DefinedEvenLater(arg: string): string
497  return arg
498enddef
499
500def Test_error_in_nested_function()
501  # Error in called function requires unwinding the call stack.
502  assert_fails('call FuncWithForwardCall()', 'E1096')
503enddef
504
505def Test_return_type_wrong()
506  CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef', 'defcompile'], 'expected number but got string')
507  CheckScriptFailure(['def Func(): string', 'return 1', 'enddef', 'defcompile'], 'expected string but got number')
508  CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type')
509  CheckScriptFailure(['def Func()', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type')
510
511  CheckScriptFailure(['def Func(): number', 'return', 'enddef', 'defcompile'], 'E1003:')
512
513  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
514  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
515  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
516enddef
517
518def Test_arg_type_wrong()
519  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
520  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
521  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
522  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
523enddef
524
525def Test_vim9script_call()
526  let lines =<< trim END
527    vim9script
528    let var = ''
529    def MyFunc(arg: string)
530       var = arg
531    enddef
532    MyFunc('foobar')
533    assert_equal('foobar', var)
534
535    let str = 'barfoo'
536    str->MyFunc()
537    assert_equal('barfoo', var)
538
539    g:value = 'value'
540    g:value->MyFunc()
541    assert_equal('value', var)
542
543    let listvar = []
544    def ListFunc(arg: list<number>)
545       listvar = arg
546    enddef
547    [1, 2, 3]->ListFunc()
548    assert_equal([1, 2, 3], listvar)
549
550    let dictvar = {}
551    def DictFunc(arg: dict<number>)
552       dictvar = arg
553    enddef
554    {'a': 1, 'b': 2}->DictFunc()
555    assert_equal(#{a: 1, b: 2}, dictvar)
556    def CompiledDict()
557      {'a': 3, 'b': 4}->DictFunc()
558    enddef
559    CompiledDict()
560    assert_equal(#{a: 3, b: 4}, dictvar)
561
562    #{a: 3, b: 4}->DictFunc()
563    assert_equal(#{a: 3, b: 4}, dictvar)
564
565    ('text')->MyFunc()
566    assert_equal('text', var)
567    ("some")->MyFunc()
568    assert_equal('some', var)
569
570    # line starting with single quote is not a mark
571    # line starting with double quote can be a method call
572    'asdfasdf'->MyFunc()
573    assert_equal('asdfasdf', var)
574    "xyz"->MyFunc()
575    assert_equal('xyz', var)
576
577    def UseString()
578      'xyork'->MyFunc()
579    enddef
580    UseString()
581    assert_equal('xyork', var)
582
583    def UseString2()
584      "knife"->MyFunc()
585    enddef
586    UseString2()
587    assert_equal('knife', var)
588
589    # prepending a colon makes it a mark
590    new
591    setline(1, ['aaa', 'bbb', 'ccc'])
592    normal! 3Gmt1G
593    :'t
594    assert_equal(3, getcurpos()[1])
595    bwipe!
596
597    MyFunc(
598        'continued'
599        )
600    assert_equal('continued',
601            var
602            )
603
604    call MyFunc(
605        'more'
606          ..
607          'lines'
608        )
609    assert_equal(
610        'morelines',
611        var)
612  END
613  writefile(lines, 'Xcall.vim')
614  source Xcall.vim
615  delete('Xcall.vim')
616enddef
617
618def Test_vim9script_call_fail_decl()
619  let lines =<< trim END
620    vim9script
621    let var = ''
622    def MyFunc(arg: string)
623       let var = 123
624    enddef
625    defcompile
626  END
627  CheckScriptFailure(lines, 'E1054:')
628enddef
629
630def Test_vim9script_call_fail_type()
631  let lines =<< trim END
632    vim9script
633    def MyFunc(arg: string)
634      echo arg
635    enddef
636    MyFunc(1234)
637  END
638  CheckScriptFailure(lines, 'E1013: type mismatch, expected string but got number')
639enddef
640
641def Test_vim9script_call_fail_const()
642  let lines =<< trim END
643    vim9script
644    const var = ''
645    def MyFunc(arg: string)
646       var = 'asdf'
647    enddef
648    defcompile
649  END
650  writefile(lines, 'Xcall_const.vim')
651  assert_fails('source Xcall_const.vim', 'E46:')
652  delete('Xcall_const.vim')
653enddef
654
655" Test that inside :function a Python function can be defined, :def is not
656" recognized.
657func Test_function_python()
658  CheckFeature python3
659  let py = 'python3'
660  execute py "<< EOF"
661def do_something():
662  return 1
663EOF
664endfunc
665
666def Test_delfunc()
667  let lines =<< trim END
668    vim9script
669    def g:GoneSoon()
670      echo 'hello'
671    enddef
672
673    def CallGoneSoon()
674      GoneSoon()
675    enddef
676    defcompile
677
678    delfunc g:GoneSoon
679    CallGoneSoon()
680  END
681  writefile(lines, 'XToDelFunc')
682  assert_fails('so XToDelFunc', 'E933')
683  assert_fails('so XToDelFunc', 'E933')
684
685  delete('XToDelFunc')
686enddef
687
688def Test_redef_failure()
689  call writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
690  so Xdef
691  call writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
692  so Xdef
693  call writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
694  call assert_fails('so Xdef', 'E1027:')
695  call writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
696  so Xdef
697  call delete('Xdef')
698
699  call assert_equal(0, g:Func0())
700  call assert_equal('Func1', g:Func1())
701  call assert_equal('Func2', g:Func2())
702
703  delfunc! Func0
704  delfunc! Func1
705  delfunc! Func2
706enddef
707
708def Test_vim9script_func()
709  let lines =<< trim END
710    vim9script
711    func Func(arg)
712      echo a:arg
713    endfunc
714    Func('text')
715  END
716  writefile(lines, 'XVim9Func')
717  so XVim9Func
718
719  delete('XVim9Func')
720enddef
721
722" Test for internal functions returning different types
723func Test_InternalFuncRetType()
724  let lines =<< trim END
725    def RetFloat(): float
726      return ceil(1.456)
727    enddef
728
729    def RetListAny(): list<any>
730      return items({'k' : 'v'})
731    enddef
732
733    def RetListString(): list<string>
734      return split('a:b:c', ':')
735    enddef
736
737    def RetListDictAny(): list<dict<any>>
738      return getbufinfo()
739    enddef
740
741    def RetDictNumber(): dict<number>
742      return wordcount()
743    enddef
744
745    def RetDictString(): dict<string>
746      return environ()
747    enddef
748  END
749  call writefile(lines, 'Xscript')
750  source Xscript
751
752  call assert_equal(2.0, RetFloat())
753  call assert_equal([['k', 'v']], RetListAny())
754  call assert_equal(['a', 'b', 'c'], RetListString())
755  call assert_notequal([], RetListDictAny())
756  call assert_notequal({}, RetDictNumber())
757  call assert_notequal({}, RetDictString())
758  call delete('Xscript')
759endfunc
760
761" Test for passing too many or too few arguments to internal functions
762func Test_internalfunc_arg_error()
763  let l =<< trim END
764    def! FArgErr(): float
765      return ceil(1.1, 2)
766    enddef
767    defcompile
768  END
769  call writefile(l, 'Xinvalidarg')
770  call assert_fails('so Xinvalidarg', 'E118:')
771  let l =<< trim END
772    def! FArgErr(): float
773      return ceil()
774    enddef
775    defcompile
776  END
777  call writefile(l, 'Xinvalidarg')
778  call assert_fails('so Xinvalidarg', 'E119:')
779  call delete('Xinvalidarg')
780endfunc
781
782let s:funcResult = 0
783
784def FuncNoArgNoRet()
785  funcResult = 11
786enddef
787
788def FuncNoArgRetNumber(): number
789  funcResult = 22
790  return 1234
791enddef
792
793def FuncNoArgRetString(): string
794  funcResult = 45
795  return 'text'
796enddef
797
798def FuncOneArgNoRet(arg: number)
799  funcResult = arg
800enddef
801
802def FuncOneArgRetNumber(arg: number): number
803  funcResult = arg
804  return arg
805enddef
806
807def FuncTwoArgNoRet(one: bool, two: number)
808  funcResult = two
809enddef
810
811def FuncOneArgRetString(arg: string): string
812  return arg
813enddef
814
815def FuncOneArgRetAny(arg: any): any
816  return arg
817enddef
818
819def Test_func_type()
820  let Ref1: func()
821  funcResult = 0
822  Ref1 = FuncNoArgNoRet
823  Ref1()
824  assert_equal(11, funcResult)
825
826  let Ref2: func
827  funcResult = 0
828  Ref2 = FuncNoArgNoRet
829  Ref2()
830  assert_equal(11, funcResult)
831
832  funcResult = 0
833  Ref2 = FuncOneArgNoRet
834  Ref2(12)
835  assert_equal(12, funcResult)
836
837  funcResult = 0
838  Ref2 = FuncNoArgRetNumber
839  assert_equal(1234, Ref2())
840  assert_equal(22, funcResult)
841
842  funcResult = 0
843  Ref2 = FuncOneArgRetNumber
844  assert_equal(13, Ref2(13))
845  assert_equal(13, funcResult)
846enddef
847
848def Test_repeat_return_type()
849  let res = 0
850  for n in repeat([1], 3)
851    res += n
852  endfor
853  assert_equal(3, res)
854
855  res = 0
856  for n in add([1, 2], 3)
857    res += n
858  endfor
859  assert_equal(6, res)
860enddef
861
862def Test_argv_return_type()
863  next fileone filetwo
864  let res = ''
865  for name in argv()
866    res ..= name
867  endfor
868  assert_equal('fileonefiletwo', res)
869enddef
870
871def Test_func_type_part()
872  let RefVoid: func: void
873  RefVoid = FuncNoArgNoRet
874  RefVoid = FuncOneArgNoRet
875  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
876  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
877
878  let RefAny: func(): any
879  RefAny = FuncNoArgRetNumber
880  RefAny = FuncNoArgRetString
881  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
882  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
883
884  let RefNr: func: number
885  RefNr = FuncNoArgRetNumber
886  RefNr = FuncOneArgRetNumber
887  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
888  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
889
890  let RefStr: func: string
891  RefStr = FuncNoArgRetString
892  RefStr = FuncOneArgRetString
893  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
894  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
895enddef
896
897def Test_func_type_fails()
898  CheckDefFailure(['let ref1: func()'], 'E704:')
899
900  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
901  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
902  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
903  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
904  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
905  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
906
907  call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
908  call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
909  call CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E740:')
910  call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
911enddef
912
913def Test_func_return_type()
914  let nr: number
915  nr = FuncNoArgRetNumber()
916  assert_equal(1234, nr)
917
918  nr = FuncOneArgRetAny(122)
919  assert_equal(122, nr)
920
921  let str: string
922  str = FuncOneArgRetAny('yes')
923  assert_equal('yes', str)
924
925  CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
926enddef
927
928def MultiLine(
929    arg1: string,
930    arg2 = 1234,
931    ...rest: list<string>
932      ): string
933  return arg1 .. arg2 .. join(rest, '-')
934enddef
935
936def MultiLineComment(
937    arg1: string, # comment
938    arg2 = 1234, # comment
939    ...rest: list<string> # comment
940      ): string # comment
941  return arg1 .. arg2 .. join(rest, '-')
942enddef
943
944def Test_multiline()
945  assert_equal('text1234', MultiLine('text'))
946  assert_equal('text777', MultiLine('text', 777))
947  assert_equal('text777one', MultiLine('text', 777, 'one'))
948  assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
949enddef
950
951func Test_multiline_not_vim9()
952  call assert_equal('text1234', MultiLine('text'))
953  call assert_equal('text777', MultiLine('text', 777))
954  call assert_equal('text777one', MultiLine('text', 777, 'one'))
955  call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
956endfunc
957
958
959" When using CheckScriptFailure() for the below test, E1010 is generated instead
960" of E1056.
961func Test_E1056_1059()
962  let caught_1056 = 0
963  try
964    def F():
965      return 1
966    enddef
967  catch /E1056:/
968    let caught_1056 = 1
969  endtry
970  call assert_equal(1, caught_1056)
971
972  let caught_1059 = 0
973  try
974    def F5(items : list)
975      echo 'a'
976    enddef
977  catch /E1059:/
978    let caught_1059 = 1
979  endtry
980  call assert_equal(1, caught_1059)
981endfunc
982
983func DelMe()
984  echo 'DelMe'
985endfunc
986
987def Test_deleted_function()
988  CheckDefExecFailure([
989      'let RefMe: func = function("g:DelMe")',
990      'delfunc g:DelMe',
991      'echo RefMe()'], 'E117:')
992enddef
993
994def Test_unknown_function()
995  CheckDefExecFailure([
996      'let Ref: func = function("NotExist")',
997      'delfunc g:NotExist'], 'E700:')
998enddef
999
1000def RefFunc(Ref: func(string): string): string
1001  return Ref('more')
1002enddef
1003
1004def Test_closure_simple()
1005  let local = 'some '
1006  assert_equal('some more', RefFunc({s -> local .. s}))
1007enddef
1008
1009def MakeRef()
1010  let local = 'some '
1011  g:Ref = {s -> local .. s}
1012enddef
1013
1014def Test_closure_ref_after_return()
1015  MakeRef()
1016  assert_equal('some thing', g:Ref('thing'))
1017  unlet g:Ref
1018enddef
1019
1020def MakeTwoRefs()
1021  let local = ['some']
1022  g:Extend = {s -> local->add(s)}
1023  g:Read = {-> local}
1024enddef
1025
1026def Test_closure_two_refs()
1027  MakeTwoRefs()
1028  assert_equal('some', join(g:Read(), ' '))
1029  g:Extend('more')
1030  assert_equal('some more', join(g:Read(), ' '))
1031  g:Extend('even')
1032  assert_equal('some more even', join(g:Read(), ' '))
1033
1034  unlet g:Extend
1035  unlet g:Read
1036enddef
1037
1038def ReadRef(Ref: func(): list<string>): string
1039  return join(Ref(), ' ')
1040enddef
1041
1042def ExtendRef(Ref: func(string), add: string)
1043  Ref(add)
1044enddef
1045
1046def Test_closure_two_indirect_refs()
1047  MakeTwoRefs()
1048  assert_equal('some', ReadRef(g:Read))
1049  ExtendRef(g:Extend, 'more')
1050  assert_equal('some more', ReadRef(g:Read))
1051  ExtendRef(g:Extend, 'even')
1052  assert_equal('some more even', ReadRef(g:Read))
1053
1054  unlet g:Extend
1055  unlet g:Read
1056enddef
1057
1058def MakeArgRefs(theArg: string)
1059  let local = 'loc_val'
1060  g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
1061enddef
1062
1063def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
1064  let local = 'the_loc'
1065  g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
1066enddef
1067
1068def Test_closure_using_argument()
1069  MakeArgRefs('arg_val')
1070  assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val'))
1071
1072  MakeArgRefsVarargs('arg_val', 'one', 'two')
1073  assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val'))
1074
1075  unlet g:UseArg
1076  unlet g:UseVararg
1077enddef
1078
1079def MakeGetAndAppendRefs()
1080  let local = 'a'
1081
1082  def Append(arg: string)
1083    local ..= arg
1084  enddef
1085  g:Append = Append
1086
1087  def Get(): string
1088    return local
1089  enddef
1090  g:Get = Get
1091enddef
1092
1093def Test_closure_append_get()
1094  MakeGetAndAppendRefs()
1095  assert_equal('a', g:Get())
1096  g:Append('-b')
1097  assert_equal('a-b', g:Get())
1098  g:Append('-c')
1099  assert_equal('a-b-c', g:Get())
1100
1101  unlet g:Append
1102  unlet g:Get
1103enddef
1104
1105def Test_nested_closure()
1106  let local = 'text'
1107  def Closure(arg: string): string
1108    return local .. arg
1109  enddef
1110  assert_equal('text!!!', Closure('!!!'))
1111enddef
1112
1113func GetResult(Ref)
1114  return a:Ref('some')
1115endfunc
1116
1117def Test_call_closure_not_compiled()
1118  let text = 'text'
1119  g:Ref = {s ->  s .. text}
1120  assert_equal('sometext', GetResult(g:Ref))
1121enddef
1122
1123def Test_sort_return_type()
1124  let res: list<number>
1125  res = [1, 2, 3]->sort()
1126enddef
1127
1128def Test_getqflist_return_type()
1129  let l = getqflist()
1130  assert_equal([], l)
1131
1132  let d = getqflist(#{items: 0})
1133  assert_equal(#{items: []}, d)
1134enddef
1135
1136def Test_getloclist_return_type()
1137  let l = getloclist(1)
1138  assert_equal([], l)
1139
1140  let d = getloclist(1, #{items: 0})
1141  assert_equal(#{items: []}, d)
1142enddef
1143
1144def Test_copy_return_type()
1145  let l = copy([1, 2, 3])
1146  let res = 0
1147  for n in l
1148    res += n
1149  endfor
1150  assert_equal(6, res)
1151
1152  let dl = deepcopy([1, 2, 3])
1153  res = 0
1154  for n in dl
1155    res += n
1156  endfor
1157  assert_equal(6, res)
1158enddef
1159
1160def Test_extend_return_type()
1161  let l = extend([1, 2], [3])
1162  let res = 0
1163  for n in l
1164    res += n
1165  endfor
1166  assert_equal(6, res)
1167enddef
1168
1169def Test_insert_return_type()
1170  let l = insert([2, 1], 3)
1171  let res = 0
1172  for n in l
1173    res += n
1174  endfor
1175  assert_equal(6, res)
1176enddef
1177
1178def Test_reverse_return_type()
1179  let l = reverse([1, 2, 3])
1180  let res = 0
1181  for n in l
1182    res += n
1183  endfor
1184  assert_equal(6, res)
1185enddef
1186
1187def Test_remove_return_type()
1188  let l = remove(#{one: [1, 2], two: [3, 4]}, 'one')
1189  let res = 0
1190  for n in l
1191    res += n
1192  endfor
1193  assert_equal(3, res)
1194enddef
1195
1196def Test_filter_return_type()
1197  let l = filter([1, 2, 3], {-> 1})
1198  let res = 0
1199  for n in l
1200    res += n
1201  endfor
1202  assert_equal(6, res)
1203enddef
1204
1205def Test_getreg_return_type()
1206  let s1: string = getreg('"')
1207  let s2: string = getreg('"', 1)
1208  let s3: list<string> = getreg('"', 1, 1)
1209enddef
1210
1211def Wrong_dict_key_type(items: list<number>): list<number>
1212  return filter(items, {_, val -> get({val: 1}, 'x')})
1213enddef
1214
1215def Test_wrong_dict_key_type()
1216  assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1029:')
1217enddef
1218
1219def Line_continuation_in_def(dir: string = ''): string
1220    let path: string = empty(dir)
1221            \ ? 'empty'
1222            \ : 'full'
1223    return path
1224enddef
1225
1226def Test_line_continuation_in_def()
1227  assert_equal('full', Line_continuation_in_def('.'))
1228enddef
1229
1230def Line_continuation_in_lambda(): list<number>
1231  let x = range(97, 100)
1232      ->map({_, v -> nr2char(v)
1233          ->toupper()})
1234      ->reverse()
1235  return x
1236enddef
1237
1238def Test_line_continuation_in_lambda()
1239  assert_equal(['D', 'C', 'B', 'A'], Line_continuation_in_lambda())
1240enddef
1241
1242func Test_silent_echo()
1243  CheckScreendump
1244
1245  let lines =<< trim END
1246    vim9script
1247    def EchoNothing()
1248      silent echo ''
1249    enddef
1250    defcompile
1251  END
1252  call writefile(lines, 'XTest_silent_echo')
1253
1254  " Check that the balloon shows up after a mouse move
1255  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
1256  call term_sendkeys(buf, ":abc")
1257  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
1258
1259  " clean up
1260  call StopVimInTerminal(buf)
1261  call delete('XTest_silent_echo')
1262endfunc
1263
1264def Fibonacci(n: number): number
1265  if n < 2
1266    return n
1267  else
1268    return Fibonacci(n - 1) + Fibonacci(n - 2)
1269  endif
1270enddef
1271
1272def Test_recursive_call()
1273  assert_equal(6765, Fibonacci(20))
1274enddef
1275
1276def TreeWalk(dir: string): list<any>
1277  return readdir(dir)->map({_, val ->
1278            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
1279               ? {val: TreeWalk(dir .. '/' .. val)}
1280               : val
1281             })
1282enddef
1283
1284def Test_closure_in_map()
1285  mkdir('XclosureDir/tdir', 'p')
1286  writefile(['111'], 'XclosureDir/file1')
1287  writefile(['222'], 'XclosureDir/file2')
1288  writefile(['333'], 'XclosureDir/tdir/file3')
1289
1290  assert_equal(['file1', 'file2', {'tdir': ['file3']}], TreeWalk('XclosureDir'))
1291
1292  delete('XclosureDir', 'rf')
1293enddef
1294
1295def Test_partial_call()
1296  let Xsetlist = function('setloclist', [0])
1297  Xsetlist([], ' ', {'title': 'test'})
1298  assert_equal({'title': 'test'}, getloclist(0, {'title': 1}))
1299
1300  Xsetlist = function('setloclist', [0, [], ' '])
1301  Xsetlist({'title': 'test'})
1302  assert_equal({'title': 'test'}, getloclist(0, {'title': 1}))
1303
1304  Xsetlist = function('setqflist')
1305  Xsetlist([], ' ', {'title': 'test'})
1306  assert_equal({'title': 'test'}, getqflist({'title': 1}))
1307
1308  Xsetlist = function('setqflist', [[], ' '])
1309  Xsetlist({'title': 'test'})
1310  assert_equal({'title': 'test'}, getqflist({'title': 1}))
1311enddef
1312
1313
1314" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1315