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
16func Test_compiling_error()
17  " use a terminal to see the whole error message
18  CheckRunVimInTerminal
19
20  call TestCompilingError()
21  call TestCompilingErrorInTry()
22endfunc
23
24def TestCompilingError()
25  var lines =<< trim END
26    vim9script
27    def Fails()
28      echo nothing
29    enddef
30    defcompile
31  END
32  writefile(lines, 'XTest_compile_error')
33  var buf = RunVimInTerminal('-S XTest_compile_error',
34              {rows: 10, wait_for_ruler: 0})
35  WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing',
36                     Term_getlines(buf, range(1, 9))))
37
38  # clean up
39  StopVimInTerminal(buf)
40  delete('XTest_compile_error')
41enddef
42
43def TestCompilingErrorInTry()
44  var dir = 'Xdir/autoload'
45  mkdir(dir, 'p')
46
47  var lines =<< trim END
48      vim9script
49      def script#OnlyCompiled()
50        g:runtime = 'yes'
51        invalid
52      enddef
53  END
54  writefile(lines, dir .. '/script.vim')
55
56  lines =<< trim END
57      vim9script
58      todo
59      try
60        script#OnlyCompiled()
61      catch /nothing/
62      endtry
63  END
64  lines[1] = 'set rtp=' .. getcwd() .. '/Xdir'
65  writefile(lines, 'XTest_compile_error')
66
67  var buf = RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0})
68  WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid',
69                     Term_getlines(buf, range(1, 9))))
70
71  # clean up
72  StopVimInTerminal(buf)
73  delete('XTest_compile_error')
74  delete('Xdir', 'rf')
75enddef
76
77def Test_autoload_name_mismatch()
78  var dir = 'Xdir/autoload'
79  mkdir(dir, 'p')
80
81  var lines =<< trim END
82      vim9script
83      def scriptX#Function()
84        # comment
85        g:runtime = 'yes'
86      enddef
87  END
88  writefile(lines, dir .. '/script.vim')
89
90  var save_rtp = &rtp
91  exe 'set rtp=' .. getcwd() .. '/Xdir'
92  lines =<< trim END
93      call script#Function()
94  END
95  CheckScriptFailure(lines, 'E746:', 2)
96
97  &rtp = save_rtp
98  delete(dir, 'rf')
99enddef
100
101def CallRecursive(n: number): number
102  return CallRecursive(n + 1)
103enddef
104
105def CallMapRecursive(l: list<number>): number
106  return map(l, (_, v) => CallMapRecursive([v]))[0]
107enddef
108
109def Test_funcdepth_error()
110  set maxfuncdepth=10
111
112  var caught = false
113  try
114    CallRecursive(1)
115  catch /E132:/
116    caught = true
117  endtry
118  assert_true(caught)
119
120  caught = false
121  try
122    CallMapRecursive([1])
123  catch /E132:/
124    caught = true
125  endtry
126  assert_true(caught)
127
128  set maxfuncdepth&
129enddef
130
131def Test_endfunc_enddef()
132  var lines =<< trim END
133    def Test()
134      echo 'test'
135      endfunc
136    enddef
137  END
138  CheckScriptFailure(lines, 'E1151:', 3)
139
140  lines =<< trim END
141    def Test()
142      func Nested()
143        echo 'test'
144      enddef
145    enddef
146  END
147  CheckScriptFailure(lines, 'E1152:', 4)
148
149  lines =<< trim END
150    def Ok()
151      echo 'hello'
152    enddef | echo 'there'
153    def Bad()
154      echo 'hello'
155    enddef there
156  END
157  CheckScriptFailure(lines, 'E1173: Text found after enddef: there', 6)
158enddef
159
160def Test_missing_endfunc_enddef()
161  var lines =<< trim END
162    vim9script
163    def Test()
164      echo 'test'
165    endef
166  END
167  CheckScriptFailure(lines, 'E1057:', 2)
168
169  lines =<< trim END
170    vim9script
171    func Some()
172      echo 'test'
173    enfffunc
174  END
175  CheckScriptFailure(lines, 'E126:', 2)
176enddef
177
178def Test_white_space_before_paren()
179  var lines =<< trim END
180    vim9script
181    def Test ()
182      echo 'test'
183    enddef
184  END
185  CheckScriptFailure(lines, 'E1068:', 2)
186
187  lines =<< trim END
188    vim9script
189    func Test ()
190      echo 'test'
191    endfunc
192  END
193  CheckScriptFailure(lines, 'E1068:', 2)
194
195  lines =<< trim END
196    def Test ()
197      echo 'test'
198    enddef
199  END
200  CheckScriptFailure(lines, 'E1068:', 1)
201
202  lines =<< trim END
203    func Test ()
204      echo 'test'
205    endfunc
206  END
207  CheckScriptSuccess(lines)
208enddef
209
210def Test_enddef_dict_key()
211  var d = {
212    enddef: 'x',
213    endfunc: 'y',
214  }
215  assert_equal({enddef: 'x', endfunc: 'y'}, d)
216enddef
217
218def ReturnString(): string
219  return 'string'
220enddef
221
222def ReturnNumber(): number
223  return 123
224enddef
225
226let g:notNumber = 'string'
227
228def ReturnGlobal(): number
229  return g:notNumber
230enddef
231
232def Test_return_something()
233  ReturnString()->assert_equal('string')
234  ReturnNumber()->assert_equal(123)
235  assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
236enddef
237
238def Test_check_argument_type()
239  var lines =<< trim END
240      vim9script
241      def Val(a: number, b: number): number
242        return 0
243      enddef
244      def Func()
245        var x: any = true
246        Val(0, x)
247      enddef
248      disass Func
249      Func()
250  END
251  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2)
252enddef
253
254def Test_missing_return()
255  CheckDefFailure(['def Missing(): number',
256                   '  if g:cond',
257                   '    echo "no return"',
258                   '  else',
259                   '    return 0',
260                   '  endif'
261                   'enddef'], 'E1027:')
262  CheckDefFailure(['def Missing(): number',
263                   '  if g:cond',
264                   '    return 1',
265                   '  else',
266                   '    echo "no return"',
267                   '  endif'
268                   'enddef'], 'E1027:')
269  CheckDefFailure(['def Missing(): number',
270                   '  if g:cond',
271                   '    return 1',
272                   '  else',
273                   '    return 2',
274                   '  endif'
275                   '  return 3'
276                   'enddef'], 'E1095:')
277enddef
278
279def Test_return_bool()
280  var lines =<< trim END
281      vim9script
282      def MenuFilter(id: number, key: string): bool
283        return popup_filter_menu(id, key)
284      enddef
285      def YesnoFilter(id: number, key: string): bool
286        return popup_filter_yesno(id, key)
287      enddef
288      defcompile
289  END
290  CheckScriptSuccess(lines)
291enddef
292
293let s:nothing = 0
294def ReturnNothing()
295  s:nothing = 1
296  if true
297    return
298  endif
299  s:nothing = 2
300enddef
301
302def Test_return_nothing()
303  ReturnNothing()
304  s:nothing->assert_equal(1)
305enddef
306
307def Test_return_invalid()
308  var lines =<< trim END
309    vim9script
310    def Func(): invalid
311      return xxx
312    enddef
313    defcompile
314  END
315  CheckScriptFailure(lines, 'E1010:', 2)
316
317  lines =<< trim END
318      vim9script
319      def Test(Fun: func(number): number): list<number>
320          return map([1, 2, 3], (_, i) => Fun(i))
321      enddef
322      defcompile
323      def Inc(nr: number): nr
324        return nr + 2
325      enddef
326      echo Test(Inc)
327  END
328  # doing this twice was leaking memory
329  CheckScriptFailure(lines, 'E1010:')
330  CheckScriptFailure(lines, 'E1010:')
331enddef
332
333func Increment()
334  let g:counter += 1
335endfunc
336
337def Test_call_ufunc_count()
338  g:counter = 1
339  Increment()
340  Increment()
341  Increment()
342  # works with and without :call
343  g:counter->assert_equal(4)
344  eval g:counter->assert_equal(4)
345  unlet g:counter
346enddef
347
348def MyVarargs(arg: string, ...rest: list<string>): string
349  var res = arg
350  for s in rest
351    res ..= ',' .. s
352  endfor
353  return res
354enddef
355
356def Test_call_varargs()
357  MyVarargs('one')->assert_equal('one')
358  MyVarargs('one', 'two')->assert_equal('one,two')
359  MyVarargs('one', 'two', 'three')->assert_equal('one,two,three')
360enddef
361
362def MyDefaultArgs(name = 'string'): string
363  return name
364enddef
365
366def MyDefaultSecond(name: string, second: bool  = true): string
367  return second ? name : 'none'
368enddef
369
370
371def Test_call_default_args()
372  MyDefaultArgs()->assert_equal('string')
373  MyDefaultArgs(v:none)->assert_equal('string')
374  MyDefaultArgs('one')->assert_equal('one')
375  assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 4, 'Test_call_default_args')
376
377  MyDefaultSecond('test')->assert_equal('test')
378  MyDefaultSecond('test', true)->assert_equal('test')
379  MyDefaultSecond('test', false)->assert_equal('none')
380
381  var lines =<< trim END
382      def MyDefaultThird(name: string, aa = 'aa', bb = 'bb'): string
383        return name .. aa .. bb
384      enddef
385
386      MyDefaultThird('->')->assert_equal('->aabb')
387      MyDefaultThird('->', v:none)->assert_equal('->aabb')
388      MyDefaultThird('->', 'xx')->assert_equal('->xxbb')
389      MyDefaultThird('->', v:none, v:none)->assert_equal('->aabb')
390      MyDefaultThird('->', 'xx', v:none)->assert_equal('->xxbb')
391      MyDefaultThird('->', v:none, 'yy')->assert_equal('->aayy')
392      MyDefaultThird('->', 'xx', 'yy')->assert_equal('->xxyy')
393  END
394  CheckDefAndScriptSuccess(lines)
395
396  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
397  delfunc g:Func
398  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
399  delfunc g:Func
400
401  lines =<< trim END
402      vim9script
403      def Func(a = b == 0 ? 1 : 2, b = 0)
404      enddef
405      defcompile
406  END
407  CheckScriptFailure(lines, 'E1001: Variable not found: b')
408enddef
409
410def FuncWithComment(  # comment
411  a: number, #comment
412  b: bool, # comment
413  c: string) #comment
414  assert_equal(4, a)
415  assert_equal(true, b)
416  assert_equal('yes', c)
417enddef
418
419def Test_func_with_comments()
420  FuncWithComment(4, true, 'yes')
421
422  var lines =<< trim END
423      def Func(# comment
424        arg: string)
425      enddef
426  END
427  CheckScriptFailure(lines, 'E125:', 1)
428
429  lines =<< trim END
430      def Func(
431        arg: string# comment
432        )
433      enddef
434  END
435  CheckScriptFailure(lines, 'E475:', 2)
436
437  lines =<< trim END
438      def Func(
439        arg: string
440        )# comment
441      enddef
442  END
443  CheckScriptFailure(lines, 'E488:', 3)
444enddef
445
446def Test_nested_function()
447  def Nested(arg: string): string
448    return 'nested ' .. arg
449  enddef
450  Nested('function')->assert_equal('nested function')
451
452  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
453  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
454
455  CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
456  CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
457  CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
458
459  var lines =<< trim END
460      def Outer()
461        def Inner()
462          # comment
463        enddef
464        def Inner()
465        enddef
466      enddef
467  END
468  CheckDefFailure(lines, 'E1073:')
469
470  lines =<< trim END
471      def Outer()
472        def Inner()
473          # comment
474        enddef
475        def! Inner()
476        enddef
477      enddef
478  END
479  CheckDefFailure(lines, 'E1117:')
480
481  # nested function inside conditional
482  lines =<< trim END
483      vim9script
484      var thecount = 0
485      if true
486        def Test(): number
487          def TheFunc(): number
488            thecount += 1
489            return thecount
490          enddef
491          return TheFunc()
492        enddef
493      endif
494      defcompile
495      assert_equal(1, Test())
496      assert_equal(2, Test())
497  END
498  CheckScriptSuccess(lines)
499
500  # also works when "thecount" is inside the "if" block
501  lines =<< trim END
502      vim9script
503      if true
504        var thecount = 0
505        def Test(): number
506          def TheFunc(): number
507            thecount += 1
508            return thecount
509          enddef
510          return TheFunc()
511        enddef
512      endif
513      defcompile
514      assert_equal(1, Test())
515      assert_equal(2, Test())
516  END
517  CheckScriptSuccess(lines)
518enddef
519
520def Test_not_nested_function()
521  echo printf('%d',
522      function('len')('xxx'))
523enddef
524
525func Test_call_default_args_from_func()
526  call MyDefaultArgs()->assert_equal('string')
527  call MyDefaultArgs('one')->assert_equal('one')
528  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func')
529endfunc
530
531def Test_nested_global_function()
532  var lines =<< trim END
533      vim9script
534      def Outer()
535          def g:Inner(): string
536              return 'inner'
537          enddef
538      enddef
539      defcompile
540      Outer()
541      g:Inner()->assert_equal('inner')
542      delfunc g:Inner
543      Outer()
544      g:Inner()->assert_equal('inner')
545      delfunc g:Inner
546      Outer()
547      g:Inner()->assert_equal('inner')
548      delfunc g:Inner
549  END
550  CheckScriptSuccess(lines)
551
552  lines =<< trim END
553      vim9script
554      def Outer()
555          def g:Inner(): string
556              return 'inner'
557          enddef
558      enddef
559      defcompile
560      Outer()
561      Outer()
562  END
563  CheckScriptFailure(lines, "E122:")
564  delfunc g:Inner
565
566  lines =<< trim END
567      vim9script
568      def Outer()
569        def g:Inner()
570          echo map([1, 2, 3], (_, v) => v + 1)
571        enddef
572        g:Inner()
573      enddef
574      Outer()
575  END
576  CheckScriptSuccess(lines)
577  delfunc g:Inner
578
579  lines =<< trim END
580      vim9script
581      def Func()
582        echo 'script'
583      enddef
584      def Outer()
585        def Func()
586          echo 'inner'
587        enddef
588      enddef
589      defcompile
590  END
591  CheckScriptFailure(lines, "E1073:")
592enddef
593
594def DefListAll()
595  def
596enddef
597
598def DefListOne()
599  def DefListOne
600enddef
601
602def DefListMatches()
603  def /DefList
604enddef
605
606def Test_nested_def_list()
607  var funcs = split(execute('call DefListAll()'), "\n")
608  assert_true(len(funcs) > 10)
609  assert_true(funcs->index('def DefListAll()') >= 0)
610
611  funcs = split(execute('call DefListOne()'), "\n")
612  assert_equal(['   def DefListOne()', '1    def DefListOne', '   enddef'], funcs)
613
614  funcs = split(execute('call DefListMatches()'), "\n")
615  assert_true(len(funcs) >= 3)
616  assert_true(funcs->index('def DefListAll()') >= 0)
617  assert_true(funcs->index('def DefListOne()') >= 0)
618  assert_true(funcs->index('def DefListMatches()') >= 0)
619
620  var lines =<< trim END
621    vim9script
622    def Func()
623      def +Func+
624    enddef
625    defcompile
626  END
627  CheckScriptFailure(lines, 'E476:', 1)
628enddef
629
630def Test_global_local_function()
631  var lines =<< trim END
632      vim9script
633      def g:Func(): string
634          return 'global'
635      enddef
636      def Func(): string
637          return 'local'
638      enddef
639      g:Func()->assert_equal('global')
640      Func()->assert_equal('local')
641      delfunc g:Func
642  END
643  CheckScriptSuccess(lines)
644
645  lines =<< trim END
646      vim9script
647      def g:Funcy()
648        echo 'funcy'
649      enddef
650      s:Funcy()
651  END
652  CheckScriptFailure(lines, 'E117:')
653enddef
654
655def Test_local_function_shadows_global()
656  var lines =<< trim END
657      vim9script
658      def g:Gfunc(): string
659        return 'global'
660      enddef
661      def AnotherFunc(): number
662        var Gfunc = function('len')
663        return Gfunc('testing')
664      enddef
665      g:Gfunc()->assert_equal('global')
666      AnotherFunc()->assert_equal(7)
667      delfunc g:Gfunc
668  END
669  CheckScriptSuccess(lines)
670
671  lines =<< trim END
672      vim9script
673      def g:Func(): string
674        return 'global'
675      enddef
676      def AnotherFunc()
677        g:Func = function('len')
678      enddef
679      AnotherFunc()
680  END
681  CheckScriptFailure(lines, 'E705:')
682  delfunc g:Func
683
684  # global function is found without g: prefix
685  lines =<< trim END
686      vim9script
687      def g:Func(): string
688        return 'global'
689      enddef
690      def AnotherFunc(): string
691        return Func()
692      enddef
693      assert_equal('global', AnotherFunc())
694    delfunc g:Func
695  END
696  CheckScriptSuccess(lines)
697
698  lines =<< trim END
699      vim9script
700      def g:Func(): string
701        return 'global'
702      enddef
703      assert_equal('global', Func())
704      delfunc g:Func
705  END
706  CheckScriptSuccess(lines)
707enddef
708
709func TakesOneArg(arg)
710  echo a:arg
711endfunc
712
713def Test_call_wrong_args()
714  CheckDefFailure(['TakesOneArg()'], 'E119:')
715  CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
716  CheckDefFailure(['bufnr(xxx)'], 'E1001:')
717  CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
718
719  var lines =<< trim END
720    vim9script
721    def Func(s: string)
722      echo s
723    enddef
724    Func([])
725  END
726  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
727
728  lines =<< trim END
729    vim9script
730    var name = 'piet'
731    def FuncOne(name: string)
732      echo nr
733    enddef
734  END
735  CheckScriptFailure(lines, 'E1168:')
736
737  lines =<< trim END
738    vim9script
739    def FuncOne(nr: number)
740      echo nr
741    enddef
742    def FuncTwo()
743      FuncOne()
744    enddef
745    defcompile
746  END
747  writefile(lines, 'Xscript')
748  var didCatch = false
749  try
750    source Xscript
751  catch
752    assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception)
753    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
754    didCatch = true
755  endtry
756  assert_true(didCatch)
757
758  lines =<< trim END
759    vim9script
760    def FuncOne(nr: number)
761      echo nr
762    enddef
763    def FuncTwo()
764      FuncOne(1, 2)
765    enddef
766    defcompile
767  END
768  writefile(lines, 'Xscript')
769  didCatch = false
770  try
771    source Xscript
772  catch
773    assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception)
774    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
775    didCatch = true
776  endtry
777  assert_true(didCatch)
778
779  delete('Xscript')
780enddef
781
782def Test_call_funcref_wrong_args()
783  var head =<< trim END
784      vim9script
785      def Func3(a1: string, a2: number, a3: list<number>)
786        echo a1 .. a2 .. a3[0]
787      enddef
788      def Testme()
789        var funcMap: dict<func> = {func: Func3}
790  END
791  var tail =<< trim END
792      enddef
793      Testme()
794  END
795  CheckScriptSuccess(head + ["funcMap['func']('str', 123, [1, 2, 3])"] + tail)
796
797  CheckScriptFailure(head + ["funcMap['func']('str', 123)"] + tail, 'E119:')
798  CheckScriptFailure(head + ["funcMap['func']('str', 123, [1], 4)"] + tail, 'E118:')
799
800  var lines =<< trim END
801      vim9script
802      var Ref: func(number): any
803      Ref = (j) => !j
804      echo Ref(false)
805  END
806  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
807
808  lines =<< trim END
809      vim9script
810      var Ref: func(number): any
811      Ref = (j) => !j
812      call Ref(false)
813  END
814  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
815enddef
816
817def Test_call_lambda_args()
818  var lines =<< trim END
819    var Callback = (..._) => 'anything'
820    assert_equal('anything', Callback())
821    assert_equal('anything', Callback(1))
822    assert_equal('anything', Callback('a', 2))
823
824    assert_equal('xyz', ((a: string): string => a)('xyz'))
825  END
826  CheckDefAndScriptSuccess(lines)
827
828  CheckDefFailure(['echo ((i) => 0)()'],
829                  'E119: Not enough arguments for function: ((i) => 0)()')
830
831  lines =<< trim END
832      var Ref = (x: number, y: number) => x + y
833      echo Ref(1, 'x')
834  END
835  CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string')
836
837  lines =<< trim END
838    var Ref: func(job, string, number)
839    Ref = (x, y) => 0
840  END
841  CheckDefAndScriptFailure(lines, 'E1012:')
842
843  lines =<< trim END
844    var Ref: func(job, string)
845    Ref = (x, y, z) => 0
846  END
847  CheckDefAndScriptFailure(lines, 'E1012:')
848
849  lines =<< trim END
850      var one = 1
851      var l = [1, 2, 3]
852      echo map(l, (one) => one)
853  END
854  CheckDefFailure(lines, 'E1167:')
855  CheckScriptFailure(['vim9script'] + lines, 'E1168:')
856
857  lines =<< trim END
858      def ShadowLocal()
859        var one = 1
860        var l = [1, 2, 3]
861        echo map(l, (one) => one)
862      enddef
863  END
864  CheckDefFailure(lines, 'E1167:')
865
866  lines =<< trim END
867      def Shadowarg(one: number)
868        var l = [1, 2, 3]
869        echo map(l, (one) => one)
870      enddef
871  END
872  CheckDefFailure(lines, 'E1167:')
873
874  lines =<< trim END
875    echo ((a) => a)('aa', 'bb')
876  END
877  CheckDefAndScriptFailure(lines, 'E118:', 1)
878enddef
879
880def FilterWithCond(x: string, Cond: func(string): bool): bool
881  return Cond(x)
882enddef
883
884def Test_lambda_return_type()
885  var lines =<< trim END
886    var Ref = (): => 123
887  END
888  CheckDefAndScriptFailure(lines, 'E1157:', 1)
889
890  # this works
891  for x in ['foo', 'boo']
892    echo FilterWithCond(x, (v) => v =~ '^b')
893  endfor
894
895  # this fails
896  lines =<< trim END
897      echo FilterWithCond('foo', (v) => v .. '^b')
898  END
899  CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1)
900enddef
901
902def Test_lambda_uses_assigned_var()
903  CheckDefSuccess([
904        'var x: any = "aaa"'
905        'x = filter(["bbb"], (_, v) => v =~ x)'])
906enddef
907
908def Test_pass_legacy_lambda_to_def_func()
909  var lines =<< trim END
910      vim9script
911      func Foo()
912        eval s:Bar({x -> 0})
913      endfunc
914      def Bar(y: any)
915      enddef
916      Foo()
917  END
918  CheckScriptSuccess(lines)
919enddef
920
921" Default arg and varargs
922def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
923  var res = one .. ',' .. two
924  for s in rest
925    res ..= ',' .. s
926  endfor
927  return res
928enddef
929
930def Test_call_def_varargs()
931  assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs')
932  MyDefVarargs('one')->assert_equal('one,foo')
933  MyDefVarargs('one', 'two')->assert_equal('one,two')
934  MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three')
935  CheckDefFailure(['MyDefVarargs("one", 22)'],
936      'E1013: Argument 2: type mismatch, expected string but got number')
937  CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
938      'E1013: Argument 3: type mismatch, expected string but got number')
939
940  var lines =<< trim END
941      vim9script
942      def Func(...l: list<string>)
943        echo l
944      enddef
945      Func('a', 'b', 'c')
946  END
947  CheckScriptSuccess(lines)
948
949  lines =<< trim END
950      vim9script
951      def Func(...l: list<string>)
952        echo l
953      enddef
954      Func()
955  END
956  CheckScriptSuccess(lines)
957
958  lines =<< trim END
959      vim9script
960      def Func(...l: list<any>)
961        echo l
962      enddef
963      Func(0)
964  END
965  CheckScriptSuccess(lines)
966
967  lines =<< trim END
968      vim9script
969      def Func(...l: any)
970        echo l
971      enddef
972      Func(0)
973  END
974  CheckScriptFailure(lines, 'E1180:', 2)
975
976  lines =<< trim END
977      vim9script
978      def Func(..._l: list<string>)
979        echo _l
980      enddef
981      Func('a', 'b', 'c')
982  END
983  CheckScriptSuccess(lines)
984
985  lines =<< trim END
986      vim9script
987      def Func(...l: list<string>)
988        echo l
989      enddef
990      Func(1, 2, 3)
991  END
992  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
993
994  lines =<< trim END
995      vim9script
996      def Func(...l: list<string>)
997        echo l
998      enddef
999      Func('a', 9)
1000  END
1001  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch')
1002
1003  lines =<< trim END
1004      vim9script
1005      def Func(...l: list<string>)
1006        echo l
1007      enddef
1008      Func(1, 'a')
1009  END
1010  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
1011
1012  lines =<< trim END
1013      vim9script
1014      def Func(  # some comment
1015                ...l = []
1016                )
1017        echo l
1018      enddef
1019  END
1020  CheckScriptFailure(lines, 'E1160:')
1021enddef
1022
1023let s:value = ''
1024
1025def FuncOneDefArg(opt = 'text')
1026  s:value = opt
1027enddef
1028
1029def FuncTwoDefArg(nr = 123, opt = 'text'): string
1030  return nr .. opt
1031enddef
1032
1033def FuncVarargs(...arg: list<string>): string
1034  return join(arg, ',')
1035enddef
1036
1037def Test_func_type_varargs()
1038  var RefDefArg: func(?string)
1039  RefDefArg = FuncOneDefArg
1040  RefDefArg()
1041  s:value->assert_equal('text')
1042  RefDefArg('some')
1043  s:value->assert_equal('some')
1044
1045  var RefDef2Arg: func(?number, ?string): string
1046  RefDef2Arg = FuncTwoDefArg
1047  RefDef2Arg()->assert_equal('123text')
1048  RefDef2Arg(99)->assert_equal('99text')
1049  RefDef2Arg(77, 'some')->assert_equal('77some')
1050
1051  CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:')
1052  CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
1053
1054  var RefVarargs: func(...list<string>): string
1055  RefVarargs = FuncVarargs
1056  RefVarargs()->assert_equal('')
1057  RefVarargs('one')->assert_equal('one')
1058  RefVarargs('one', 'two')->assert_equal('one,two')
1059
1060  CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:')
1061  CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:')
1062enddef
1063
1064" Only varargs
1065def MyVarargsOnly(...args: list<string>): string
1066  return join(args, ',')
1067enddef
1068
1069def Test_call_varargs_only()
1070  MyVarargsOnly()->assert_equal('')
1071  MyVarargsOnly('one')->assert_equal('one')
1072  MyVarargsOnly('one', 'two')->assert_equal('one,two')
1073  CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
1074  CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number')
1075enddef
1076
1077def Test_using_var_as_arg()
1078  writefile(['def Func(x: number)',  'var x = 234', 'enddef', 'defcompile'], 'Xdef')
1079  assert_fails('so Xdef', 'E1006:', '', 1, 'Func')
1080  delete('Xdef')
1081enddef
1082
1083def DictArg(arg: dict<string>)
1084  arg['key'] = 'value'
1085enddef
1086
1087def ListArg(arg: list<string>)
1088  arg[0] = 'value'
1089enddef
1090
1091def Test_assign_to_argument()
1092  # works for dict and list
1093  var d: dict<string> = {}
1094  DictArg(d)
1095  d['key']->assert_equal('value')
1096  var l: list<string> = []
1097  ListArg(l)
1098  l[0]->assert_equal('value')
1099
1100  CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
1101  delfunc! g:Func
1102enddef
1103
1104" These argument names are reserved in legacy functions.
1105def WithReservedNames(firstline: string, lastline: string): string
1106  return firstline .. lastline
1107enddef
1108
1109def Test_argument_names()
1110  assert_equal('OK', WithReservedNames('O', 'K'))
1111enddef
1112
1113def Test_call_func_defined_later()
1114  g:DefinedLater('one')->assert_equal('one')
1115  assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
1116enddef
1117
1118func DefinedLater(arg)
1119  return a:arg
1120endfunc
1121
1122def Test_call_funcref()
1123  g:SomeFunc('abc')->assert_equal(3)
1124  assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
1125  assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
1126
1127  var lines =<< trim END
1128    vim9script
1129    def RetNumber(): number
1130      return 123
1131    enddef
1132    var Funcref: func: number = function('RetNumber')
1133    Funcref()->assert_equal(123)
1134  END
1135  CheckScriptSuccess(lines)
1136
1137  lines =<< trim END
1138    vim9script
1139    def RetNumber(): number
1140      return 123
1141    enddef
1142    def Bar(F: func: number): number
1143      return F()
1144    enddef
1145    var Funcref = function('RetNumber')
1146    Bar(Funcref)->assert_equal(123)
1147  END
1148  CheckScriptSuccess(lines)
1149
1150  lines =<< trim END
1151    vim9script
1152    def UseNumber(nr: number)
1153      echo nr
1154    enddef
1155    var Funcref: func(number) = function('UseNumber')
1156    Funcref(123)
1157  END
1158  CheckScriptSuccess(lines)
1159
1160  lines =<< trim END
1161    vim9script
1162    def UseNumber(nr: number)
1163      echo nr
1164    enddef
1165    var Funcref: func(string) = function('UseNumber')
1166  END
1167  CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
1168
1169  lines =<< trim END
1170    vim9script
1171    def EchoNr(nr = 34)
1172      g:echo = nr
1173    enddef
1174    var Funcref: func(?number) = function('EchoNr')
1175    Funcref()
1176    g:echo->assert_equal(34)
1177    Funcref(123)
1178    g:echo->assert_equal(123)
1179  END
1180  CheckScriptSuccess(lines)
1181
1182  lines =<< trim END
1183    vim9script
1184    def EchoList(...l: list<number>)
1185      g:echo = l
1186    enddef
1187    var Funcref: func(...list<number>) = function('EchoList')
1188    Funcref()
1189    g:echo->assert_equal([])
1190    Funcref(1, 2, 3)
1191    g:echo->assert_equal([1, 2, 3])
1192  END
1193  CheckScriptSuccess(lines)
1194
1195  lines =<< trim END
1196    vim9script
1197    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
1198      g:optarg = opt
1199      g:listarg = l
1200      return nr
1201    enddef
1202    var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
1203    Funcref(10)->assert_equal(10)
1204    g:optarg->assert_equal(12)
1205    g:listarg->assert_equal([])
1206
1207    Funcref(11, 22)->assert_equal(11)
1208    g:optarg->assert_equal(22)
1209    g:listarg->assert_equal([])
1210
1211    Funcref(17, 18, 1, 2, 3)->assert_equal(17)
1212    g:optarg->assert_equal(18)
1213    g:listarg->assert_equal([1, 2, 3])
1214  END
1215  CheckScriptSuccess(lines)
1216enddef
1217
1218let SomeFunc = function('len')
1219let NotAFunc = 'text'
1220
1221def CombineFuncrefTypes()
1222  # same arguments, different return type
1223  var Ref1: func(bool): string
1224  var Ref2: func(bool): number
1225  var Ref3: func(bool): any
1226  Ref3 = g:cond ? Ref1 : Ref2
1227
1228  # different number of arguments
1229  var Refa1: func(bool): number
1230  var Refa2: func(bool, number): number
1231  var Refa3: func: number
1232  Refa3 = g:cond ? Refa1 : Refa2
1233
1234  # different argument types
1235  var Refb1: func(bool, string): number
1236  var Refb2: func(string, number): number
1237  var Refb3: func(any, any): number
1238  Refb3 = g:cond ? Refb1 : Refb2
1239enddef
1240
1241def FuncWithForwardCall()
1242  return g:DefinedEvenLater("yes")
1243enddef
1244
1245def DefinedEvenLater(arg: string): string
1246  return arg
1247enddef
1248
1249def Test_error_in_nested_function()
1250  # Error in called function requires unwinding the call stack.
1251  assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
1252enddef
1253
1254def Test_return_type_wrong()
1255  CheckScriptFailure([
1256        'def Func(): number',
1257        'return "a"',
1258        'enddef',
1259        'defcompile'], 'expected number but got string')
1260  delfunc! g:Func
1261  CheckScriptFailure([
1262        'def Func(): string',
1263        'return 1',
1264        'enddef',
1265        'defcompile'], 'expected string but got number')
1266  delfunc! g:Func
1267  CheckScriptFailure([
1268        'def Func(): void',
1269        'return "a"',
1270        'enddef',
1271        'defcompile'],
1272        'E1096: Returning a value in a function without a return type')
1273  delfunc! g:Func
1274  CheckScriptFailure([
1275        'def Func()',
1276        'return "a"',
1277        'enddef',
1278        'defcompile'],
1279        'E1096: Returning a value in a function without a return type')
1280  delfunc! g:Func
1281
1282  CheckScriptFailure([
1283        'def Func(): number',
1284        'return',
1285        'enddef',
1286        'defcompile'], 'E1003:')
1287  delfunc! g:Func
1288
1289  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
1290  delfunc! g:Func
1291  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
1292  delfunc! g:Func
1293  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
1294  delfunc! g:Func
1295
1296  CheckScriptFailure([
1297        'vim9script',
1298        'def FuncB()',
1299        '  return 123',
1300        'enddef',
1301        'def FuncA()',
1302        '   FuncB()',
1303        'enddef',
1304        'defcompile'], 'E1096:')
1305enddef
1306
1307def Test_arg_type_wrong()
1308  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
1309  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
1310  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
1311  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
1312enddef
1313
1314def Test_white_space_before_comma()
1315  var lines =<< trim END
1316    vim9script
1317    def Func(a: number , b: number)
1318    enddef
1319  END
1320  CheckScriptFailure(lines, 'E1068:')
1321enddef
1322
1323def Test_white_space_after_comma()
1324  var lines =<< trim END
1325    vim9script
1326    def Func(a: number,b: number)
1327    enddef
1328  END
1329  CheckScriptFailure(lines, 'E1069:')
1330
1331  # OK in legacy function
1332  lines =<< trim END
1333    vim9script
1334    func Func(a,b)
1335    endfunc
1336  END
1337  CheckScriptSuccess(lines)
1338enddef
1339
1340def Test_vim9script_call()
1341  var lines =<< trim END
1342    vim9script
1343    var name = ''
1344    def MyFunc(arg: string)
1345       name = arg
1346    enddef
1347    MyFunc('foobar')
1348    name->assert_equal('foobar')
1349
1350    var str = 'barfoo'
1351    str->MyFunc()
1352    name->assert_equal('barfoo')
1353
1354    g:value = 'value'
1355    g:value->MyFunc()
1356    name->assert_equal('value')
1357
1358    var listvar = []
1359    def ListFunc(arg: list<number>)
1360       listvar = arg
1361    enddef
1362    [1, 2, 3]->ListFunc()
1363    listvar->assert_equal([1, 2, 3])
1364
1365    var dictvar = {}
1366    def DictFunc(arg: dict<number>)
1367       dictvar = arg
1368    enddef
1369    {a: 1, b: 2}->DictFunc()
1370    dictvar->assert_equal({a: 1, b: 2})
1371    def CompiledDict()
1372      {a: 3, b: 4}->DictFunc()
1373    enddef
1374    CompiledDict()
1375    dictvar->assert_equal({a: 3, b: 4})
1376
1377    {a: 3, b: 4}->DictFunc()
1378    dictvar->assert_equal({a: 3, b: 4})
1379
1380    ('text')->MyFunc()
1381    name->assert_equal('text')
1382    ("some")->MyFunc()
1383    name->assert_equal('some')
1384
1385    # line starting with single quote is not a mark
1386    # line starting with double quote can be a method call
1387    'asdfasdf'->MyFunc()
1388    name->assert_equal('asdfasdf')
1389    "xyz"->MyFunc()
1390    name->assert_equal('xyz')
1391
1392    def UseString()
1393      'xyork'->MyFunc()
1394    enddef
1395    UseString()
1396    name->assert_equal('xyork')
1397
1398    def UseString2()
1399      "knife"->MyFunc()
1400    enddef
1401    UseString2()
1402    name->assert_equal('knife')
1403
1404    # prepending a colon makes it a mark
1405    new
1406    setline(1, ['aaa', 'bbb', 'ccc'])
1407    normal! 3Gmt1G
1408    :'t
1409    getcurpos()[1]->assert_equal(3)
1410    bwipe!
1411
1412    MyFunc(
1413        'continued'
1414        )
1415    assert_equal('continued',
1416            name
1417            )
1418
1419    call MyFunc(
1420        'more'
1421          ..
1422          'lines'
1423        )
1424    assert_equal(
1425        'morelines',
1426        name)
1427  END
1428  writefile(lines, 'Xcall.vim')
1429  source Xcall.vim
1430  delete('Xcall.vim')
1431enddef
1432
1433def Test_vim9script_call_fail_decl()
1434  var lines =<< trim END
1435    vim9script
1436    var name = ''
1437    def MyFunc(arg: string)
1438       var name = 123
1439    enddef
1440    defcompile
1441  END
1442  CheckScriptFailure(lines, 'E1054:')
1443enddef
1444
1445def Test_vim9script_call_fail_type()
1446  var lines =<< trim END
1447    vim9script
1448    def MyFunc(arg: string)
1449      echo arg
1450    enddef
1451    MyFunc(1234)
1452  END
1453  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
1454enddef
1455
1456def Test_vim9script_call_fail_const()
1457  var lines =<< trim END
1458    vim9script
1459    const var = ''
1460    def MyFunc(arg: string)
1461       var = 'asdf'
1462    enddef
1463    defcompile
1464  END
1465  writefile(lines, 'Xcall_const.vim')
1466  assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
1467  delete('Xcall_const.vim')
1468
1469  lines =<< trim END
1470      const g:Aconst = 77
1471      def Change()
1472        # comment
1473        g:Aconst = 99
1474      enddef
1475      call Change()
1476      unlet g:Aconst
1477  END
1478  CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2)
1479enddef
1480
1481" Test that inside :function a Python function can be defined, :def is not
1482" recognized.
1483func Test_function_python()
1484  CheckFeature python3
1485  let py = 'python3'
1486  execute py "<< EOF"
1487def do_something():
1488  return 1
1489EOF
1490endfunc
1491
1492def Test_delfunc()
1493  var lines =<< trim END
1494    vim9script
1495    def g:GoneSoon()
1496      echo 'hello'
1497    enddef
1498
1499    def CallGoneSoon()
1500      GoneSoon()
1501    enddef
1502    defcompile
1503
1504    delfunc g:GoneSoon
1505    CallGoneSoon()
1506  END
1507  writefile(lines, 'XToDelFunc')
1508  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
1509  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
1510
1511  delete('XToDelFunc')
1512enddef
1513
1514def Test_redef_failure()
1515  writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
1516  so Xdef
1517  writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
1518  so Xdef
1519  writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
1520  assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
1521  writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
1522  so Xdef
1523  delete('Xdef')
1524
1525  assert_fails('g:Func0()', 'E1091:')
1526  g:Func1()->assert_equal('Func1')
1527  g:Func2()->assert_equal('Func2')
1528
1529  delfunc! Func0
1530  delfunc! Func1
1531  delfunc! Func2
1532enddef
1533
1534def Test_vim9script_func()
1535  var lines =<< trim END
1536    vim9script
1537    func Func(arg)
1538      echo a:arg
1539    endfunc
1540    Func('text')
1541  END
1542  writefile(lines, 'XVim9Func')
1543  so XVim9Func
1544
1545  delete('XVim9Func')
1546enddef
1547
1548let s:funcResult = 0
1549
1550def FuncNoArgNoRet()
1551  s:funcResult = 11
1552enddef
1553
1554def FuncNoArgRetNumber(): number
1555  s:funcResult = 22
1556  return 1234
1557enddef
1558
1559def FuncNoArgRetString(): string
1560  s:funcResult = 45
1561  return 'text'
1562enddef
1563
1564def FuncOneArgNoRet(arg: number)
1565  s:funcResult = arg
1566enddef
1567
1568def FuncOneArgRetNumber(arg: number): number
1569  s:funcResult = arg
1570  return arg
1571enddef
1572
1573def FuncTwoArgNoRet(one: bool, two: number)
1574  s:funcResult = two
1575enddef
1576
1577def FuncOneArgRetString(arg: string): string
1578  return arg
1579enddef
1580
1581def FuncOneArgRetAny(arg: any): any
1582  return arg
1583enddef
1584
1585def Test_func_type()
1586  var Ref1: func()
1587  s:funcResult = 0
1588  Ref1 = FuncNoArgNoRet
1589  Ref1()
1590  s:funcResult->assert_equal(11)
1591
1592  var Ref2: func
1593  s:funcResult = 0
1594  Ref2 = FuncNoArgNoRet
1595  Ref2()
1596  s:funcResult->assert_equal(11)
1597
1598  s:funcResult = 0
1599  Ref2 = FuncOneArgNoRet
1600  Ref2(12)
1601  s:funcResult->assert_equal(12)
1602
1603  s:funcResult = 0
1604  Ref2 = FuncNoArgRetNumber
1605  Ref2()->assert_equal(1234)
1606  s:funcResult->assert_equal(22)
1607
1608  s:funcResult = 0
1609  Ref2 = FuncOneArgRetNumber
1610  Ref2(13)->assert_equal(13)
1611  s:funcResult->assert_equal(13)
1612enddef
1613
1614def Test_repeat_return_type()
1615  var res = 0
1616  for n in repeat([1], 3)
1617    res += n
1618  endfor
1619  res->assert_equal(3)
1620
1621  res = 0
1622  for n in add([1, 2], 3)
1623    res += n
1624  endfor
1625  res->assert_equal(6)
1626enddef
1627
1628def Test_argv_return_type()
1629  next fileone filetwo
1630  var res = ''
1631  for name in argv()
1632    res ..= name
1633  endfor
1634  res->assert_equal('fileonefiletwo')
1635enddef
1636
1637def Test_func_type_part()
1638  var RefVoid: func: void
1639  RefVoid = FuncNoArgNoRet
1640  RefVoid = FuncOneArgNoRet
1641  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1642  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
1643
1644  var RefAny: func(): any
1645  RefAny = FuncNoArgRetNumber
1646  RefAny = FuncNoArgRetString
1647  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1648  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
1649
1650  var RefAnyNoArgs: func: any = RefAny
1651
1652  var RefNr: func: number
1653  RefNr = FuncNoArgRetNumber
1654  RefNr = FuncOneArgRetNumber
1655  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1656  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
1657
1658  var RefStr: func: string
1659  RefStr = FuncNoArgRetString
1660  RefStr = FuncOneArgRetString
1661  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1662  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
1663enddef
1664
1665def Test_func_type_fails()
1666  CheckDefFailure(['var ref1: func()'], 'E704:')
1667
1668  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1669  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1670  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1671  CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1672  CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1673  CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
1674
1675  CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:')
1676  CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:')
1677  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:')
1678  CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:')
1679enddef
1680
1681def Test_func_return_type()
1682  var nr: number
1683  nr = FuncNoArgRetNumber()
1684  nr->assert_equal(1234)
1685
1686  nr = FuncOneArgRetAny(122)
1687  nr->assert_equal(122)
1688
1689  var str: string
1690  str = FuncOneArgRetAny('yes')
1691  str->assert_equal('yes')
1692
1693  CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
1694enddef
1695
1696def Test_func_common_type()
1697  def FuncOne(n: number): number
1698    return n
1699  enddef
1700  def FuncTwo(s: string): number
1701    return len(s)
1702  enddef
1703  def FuncThree(n: number, s: string): number
1704    return n + len(s)
1705  enddef
1706  var list = [FuncOne, FuncTwo, FuncThree]
1707  assert_equal(8, list[0](8))
1708  assert_equal(4, list[1]('word'))
1709  assert_equal(7, list[2](3, 'word'))
1710enddef
1711
1712def MultiLine(
1713    arg1: string,
1714    arg2 = 1234,
1715    ...rest: list<string>
1716      ): string
1717  return arg1 .. arg2 .. join(rest, '-')
1718enddef
1719
1720def MultiLineComment(
1721    arg1: string, # comment
1722    arg2 = 1234, # comment
1723    ...rest: list<string> # comment
1724      ): string # comment
1725  return arg1 .. arg2 .. join(rest, '-')
1726enddef
1727
1728def Test_multiline()
1729  MultiLine('text')->assert_equal('text1234')
1730  MultiLine('text', 777)->assert_equal('text777')
1731  MultiLine('text', 777, 'one')->assert_equal('text777one')
1732  MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1733enddef
1734
1735func Test_multiline_not_vim9()
1736  call MultiLine('text')->assert_equal('text1234')
1737  call MultiLine('text', 777)->assert_equal('text777')
1738  call MultiLine('text', 777, 'one')->assert_equal('text777one')
1739  call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1740endfunc
1741
1742
1743" When using CheckScriptFailure() for the below test, E1010 is generated instead
1744" of E1056.
1745func Test_E1056_1059()
1746  let caught_1056 = 0
1747  try
1748    def F():
1749      return 1
1750    enddef
1751  catch /E1056:/
1752    let caught_1056 = 1
1753  endtry
1754  eval caught_1056->assert_equal(1)
1755
1756  let caught_1059 = 0
1757  try
1758    def F5(items : list)
1759      echo 'a'
1760    enddef
1761  catch /E1059:/
1762    let caught_1059 = 1
1763  endtry
1764  eval caught_1059->assert_equal(1)
1765endfunc
1766
1767func DelMe()
1768  echo 'DelMe'
1769endfunc
1770
1771def Test_error_reporting()
1772  # comment lines at the start of the function
1773  var lines =<< trim END
1774    " comment
1775    def Func()
1776      # comment
1777      # comment
1778      invalid
1779    enddef
1780    defcompile
1781  END
1782  writefile(lines, 'Xdef')
1783  try
1784    source Xdef
1785    assert_report('should have failed')
1786  catch /E476:/
1787    v:exception->assert_match('Invalid command: invalid')
1788    v:throwpoint->assert_match(', line 3$')
1789  endtry
1790  delfunc! g:Func
1791
1792  # comment lines after the start of the function
1793  lines =<< trim END
1794    " comment
1795    def Func()
1796      var x = 1234
1797      # comment
1798      # comment
1799      invalid
1800    enddef
1801    defcompile
1802  END
1803  writefile(lines, 'Xdef')
1804  try
1805    source Xdef
1806    assert_report('should have failed')
1807  catch /E476:/
1808    v:exception->assert_match('Invalid command: invalid')
1809    v:throwpoint->assert_match(', line 4$')
1810  endtry
1811  delfunc! g:Func
1812
1813  lines =<< trim END
1814    vim9script
1815    def Func()
1816      var db = {foo: 1, bar: 2}
1817      # comment
1818      var x = db.asdf
1819    enddef
1820    defcompile
1821    Func()
1822  END
1823  writefile(lines, 'Xdef')
1824  try
1825    source Xdef
1826    assert_report('should have failed')
1827  catch /E716:/
1828    v:throwpoint->assert_match('_Func, line 3$')
1829  endtry
1830  delfunc! g:Func
1831
1832  delete('Xdef')
1833enddef
1834
1835def Test_deleted_function()
1836  CheckDefExecFailure([
1837      'var RefMe: func = function("g:DelMe")',
1838      'delfunc g:DelMe',
1839      'echo RefMe()'], 'E117:')
1840enddef
1841
1842def Test_unknown_function()
1843  CheckDefExecFailure([
1844      'var Ref: func = function("NotExist")',
1845      'delfunc g:NotExist'], 'E700:')
1846enddef
1847
1848def RefFunc(Ref: func(any): any): string
1849  return Ref('more')
1850enddef
1851
1852def Test_closure_simple()
1853  var local = 'some '
1854  RefFunc((s) => local .. s)->assert_equal('some more')
1855enddef
1856
1857def MakeRef()
1858  var local = 'some '
1859  g:Ref = (s) => local .. s
1860enddef
1861
1862def Test_closure_ref_after_return()
1863  MakeRef()
1864  g:Ref('thing')->assert_equal('some thing')
1865  unlet g:Ref
1866enddef
1867
1868def MakeTwoRefs()
1869  var local = ['some']
1870  g:Extend = (s) => local->add(s)
1871  g:Read = () => local
1872enddef
1873
1874def Test_closure_two_refs()
1875  MakeTwoRefs()
1876  join(g:Read(), ' ')->assert_equal('some')
1877  g:Extend('more')
1878  join(g:Read(), ' ')->assert_equal('some more')
1879  g:Extend('even')
1880  join(g:Read(), ' ')->assert_equal('some more even')
1881
1882  unlet g:Extend
1883  unlet g:Read
1884enddef
1885
1886def ReadRef(Ref: func(): list<string>): string
1887  return join(Ref(), ' ')
1888enddef
1889
1890def ExtendRef(Ref: func(string): list<string>, add: string)
1891  Ref(add)
1892enddef
1893
1894def Test_closure_two_indirect_refs()
1895  MakeTwoRefs()
1896  ReadRef(g:Read)->assert_equal('some')
1897  ExtendRef(g:Extend, 'more')
1898  ReadRef(g:Read)->assert_equal('some more')
1899  ExtendRef(g:Extend, 'even')
1900  ReadRef(g:Read)->assert_equal('some more even')
1901
1902  unlet g:Extend
1903  unlet g:Read
1904enddef
1905
1906def MakeArgRefs(theArg: string)
1907  var local = 'loc_val'
1908  g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s
1909enddef
1910
1911def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
1912  var local = 'the_loc'
1913  g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)
1914enddef
1915
1916def Test_closure_using_argument()
1917  MakeArgRefs('arg_val')
1918  g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
1919
1920  MakeArgRefsVarargs('arg_val', 'one', 'two')
1921  g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
1922
1923  unlet g:UseArg
1924  unlet g:UseVararg
1925
1926  var lines =<< trim END
1927      vim9script
1928      def Test(Fun: func(number): number): list<number>
1929        return map([1, 2, 3], (_, i) => Fun(i))
1930      enddef
1931      def Inc(nr: number): number
1932        return nr + 2
1933      enddef
1934      assert_equal([3, 4, 5], Test(Inc))
1935  END
1936  CheckScriptSuccess(lines)
1937enddef
1938
1939def MakeGetAndAppendRefs()
1940  var local = 'a'
1941
1942  def Append(arg: string)
1943    local ..= arg
1944  enddef
1945  g:Append = Append
1946
1947  def Get(): string
1948    return local
1949  enddef
1950  g:Get = Get
1951enddef
1952
1953def Test_closure_append_get()
1954  MakeGetAndAppendRefs()
1955  g:Get()->assert_equal('a')
1956  g:Append('-b')
1957  g:Get()->assert_equal('a-b')
1958  g:Append('-c')
1959  g:Get()->assert_equal('a-b-c')
1960
1961  unlet g:Append
1962  unlet g:Get
1963enddef
1964
1965def Test_nested_closure()
1966  var local = 'text'
1967  def Closure(arg: string): string
1968    return local .. arg
1969  enddef
1970  Closure('!!!')->assert_equal('text!!!')
1971enddef
1972
1973func GetResult(Ref)
1974  return a:Ref('some')
1975endfunc
1976
1977def Test_call_closure_not_compiled()
1978  var text = 'text'
1979  g:Ref = (s) =>  s .. text
1980  GetResult(g:Ref)->assert_equal('sometext')
1981enddef
1982
1983def Test_double_closure_fails()
1984  var lines =<< trim END
1985    vim9script
1986    def Func()
1987      var name = 0
1988      for i in range(2)
1989          timer_start(0, () => name)
1990      endfor
1991    enddef
1992    Func()
1993  END
1994  CheckScriptSuccess(lines)
1995enddef
1996
1997def Test_nested_closure_used()
1998  var lines =<< trim END
1999      vim9script
2000      def Func()
2001        var x = 'hello'
2002        var Closure = () => x
2003        g:Myclosure = () => Closure()
2004      enddef
2005      Func()
2006      assert_equal('hello', g:Myclosure())
2007  END
2008  CheckScriptSuccess(lines)
2009enddef
2010
2011def Test_nested_closure_fails()
2012  var lines =<< trim END
2013    vim9script
2014    def FuncA()
2015      FuncB(0)
2016    enddef
2017    def FuncB(n: number): list<string>
2018      return map([0], (_, v) => n)
2019    enddef
2020    FuncA()
2021  END
2022  CheckScriptFailure(lines, 'E1012:')
2023enddef
2024
2025def Test_global_closure()
2026  var lines =<< trim END
2027      vim9script
2028      def ReverseEveryNLines(n: number, line1: number, line2: number)
2029        var mods = 'sil keepj keepp lockm '
2030        var range = ':' .. line1 .. ',' .. line2
2031        def g:Offset(): number
2032            var offset = (line('.') - line1 + 1) % n
2033            return offset != 0 ? offset : n
2034        enddef
2035        exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()'
2036      enddef
2037
2038      new
2039      repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1)
2040      ReverseEveryNLines(3, 1, 9)
2041  END
2042  CheckScriptSuccess(lines)
2043  var expected = repeat(['ccc', 'bbb', 'aaa'], 3)
2044  assert_equal(expected, getline(1, 9))
2045  bwipe!
2046enddef
2047
2048def Test_global_closure_called_directly()
2049  var lines =<< trim END
2050      vim9script
2051      def Outer()
2052        var x = 1
2053        def g:Inner()
2054          var y = x
2055          x += 1
2056          assert_equal(1, y)
2057        enddef
2058        g:Inner()
2059        assert_equal(2, x)
2060      enddef
2061      Outer()
2062  END
2063  CheckScriptSuccess(lines)
2064  delfunc g:Inner
2065enddef
2066
2067def Test_failure_in_called_function()
2068  # this was using the frame index as the return value
2069  var lines =<< trim END
2070      vim9script
2071      au TerminalWinOpen * eval [][0]
2072      def PopupTerm(a: any)
2073        # make sure typvals on stack are string
2074        ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join()
2075        FireEvent()
2076      enddef
2077      def FireEvent()
2078          do TerminalWinOpen
2079      enddef
2080      # use try/catch to make eval fail
2081      try
2082          call PopupTerm(0)
2083      catch
2084      endtry
2085      au! TerminalWinOpen
2086  END
2087  CheckScriptSuccess(lines)
2088enddef
2089
2090def Test_nested_lambda()
2091  var lines =<< trim END
2092    vim9script
2093    def Func()
2094      var x = 4
2095      var Lambda1 = () => 7
2096      var Lambda2 = () => [Lambda1(), x]
2097      var res = Lambda2()
2098      assert_equal([7, 4], res)
2099    enddef
2100    Func()
2101  END
2102  CheckScriptSuccess(lines)
2103enddef
2104
2105def Shadowed(): list<number>
2106  var FuncList: list<func: number> = [() => 42]
2107  return FuncList->mapnew((_, Shadowed) => Shadowed())
2108enddef
2109
2110def Test_lambda_arg_shadows_func()
2111  assert_equal([42], Shadowed())
2112enddef
2113
2114def Line_continuation_in_def(dir: string = ''): string
2115  var path: string = empty(dir)
2116          \ ? 'empty'
2117          \ : 'full'
2118  return path
2119enddef
2120
2121def Test_line_continuation_in_def()
2122  Line_continuation_in_def('.')->assert_equal('full')
2123enddef
2124
2125def Test_script_var_in_lambda()
2126  var lines =<< trim END
2127      vim9script
2128      var script = 'test'
2129      assert_equal(['test'], map(['one'], (_, _) => script))
2130  END
2131  CheckScriptSuccess(lines)
2132enddef
2133
2134def Line_continuation_in_lambda(): list<string>
2135  var x = range(97, 100)
2136      ->mapnew((_, v) => nr2char(v)
2137          ->toupper())
2138      ->reverse()
2139  return x
2140enddef
2141
2142def Test_line_continuation_in_lambda()
2143  Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
2144
2145  var lines =<< trim END
2146      vim9script
2147      var res = [{n: 1, m: 2, s: 'xxx'}]
2148                ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s',
2149                    v.n,
2150                    v.m,
2151                    substitute(v.s, '.*', 'yyy', '')
2152                    ))
2153      assert_equal(['1:2:yyy'], res)
2154  END
2155  CheckScriptSuccess(lines)
2156enddef
2157
2158def Test_list_lambda()
2159  timer_start(1000, (_) => 0)
2160  var body = execute(timer_info()[0].callback
2161         ->string()
2162         ->substitute("('", ' ', '')
2163         ->substitute("')", '', '')
2164         ->substitute('function\zs', ' ', ''))
2165  assert_match('def <lambda>\d\+(_: any): number\n1  return 0\n   enddef', body)
2166enddef
2167
2168def Test_legacy_lambda()
2169  legacy echo {x -> 'hello ' .. x}('foo')
2170
2171  var lines =<< trim END
2172      echo {x -> 'hello ' .. x}('foo')
2173  END
2174  CheckDefAndScriptFailure(lines, 'E720:')
2175
2176  lines =<< trim END
2177      vim9script
2178      def Func()
2179        echo (() => 'no error')()
2180      enddef
2181      legacy call s:Func()
2182  END
2183  CheckScriptSuccess(lines)
2184enddef
2185
2186def DoFilterThis(a: string): list<string>
2187  # closure nested inside another closure using argument
2188  var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0)
2189  return ['x', 'y', 'a', 'x2', 'c']->Filter()
2190enddef
2191
2192def Test_nested_closure_using_argument()
2193  assert_equal(['x', 'x2'], DoFilterThis('x'))
2194enddef
2195
2196def Test_triple_nested_closure()
2197  var what = 'x'
2198  var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0
2199  var Filter = (l) => filter(l, (_, v) => Match(v, what))
2200  assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter())
2201enddef
2202
2203func Test_silent_echo()
2204  CheckScreendump
2205
2206  let lines =<< trim END
2207    vim9script
2208    def EchoNothing()
2209      silent echo ''
2210    enddef
2211    defcompile
2212  END
2213  call writefile(lines, 'XTest_silent_echo')
2214
2215  " Check that the balloon shows up after a mouse move
2216  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
2217  call term_sendkeys(buf, ":abc")
2218  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
2219
2220  " clean up
2221  call StopVimInTerminal(buf)
2222  call delete('XTest_silent_echo')
2223endfunc
2224
2225def SilentlyError()
2226  execute('silent! invalid')
2227  g:did_it = 'yes'
2228enddef
2229
2230func UserError()
2231  silent! invalid
2232endfunc
2233
2234def SilentlyUserError()
2235  UserError()
2236  g:did_it = 'yes'
2237enddef
2238
2239" This can't be a :def function, because the assert would not be reached.
2240func Test_ignore_silent_error()
2241  let g:did_it = 'no'
2242  call SilentlyError()
2243  call assert_equal('yes', g:did_it)
2244
2245  let g:did_it = 'no'
2246  call SilentlyUserError()
2247  call assert_equal('yes', g:did_it)
2248
2249  unlet g:did_it
2250endfunc
2251
2252def Test_ignore_silent_error_in_filter()
2253  var lines =<< trim END
2254      vim9script
2255      def Filter(winid: number, key: string): bool
2256          if key == 'o'
2257              silent! eval [][0]
2258              return true
2259          endif
2260          return popup_filter_menu(winid, key)
2261      enddef
2262
2263      popup_create('popup', {filter: Filter})
2264      feedkeys("o\r", 'xnt')
2265  END
2266  CheckScriptSuccess(lines)
2267enddef
2268
2269def Fibonacci(n: number): number
2270  if n < 2
2271    return n
2272  else
2273    return Fibonacci(n - 1) + Fibonacci(n - 2)
2274  endif
2275enddef
2276
2277def Test_recursive_call()
2278  Fibonacci(20)->assert_equal(6765)
2279enddef
2280
2281def TreeWalk(dir: string): list<any>
2282  return readdir(dir)->mapnew((_, val) =>
2283            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
2284               ? {[val]: TreeWalk(dir .. '/' .. val)}
2285               : val
2286             )
2287enddef
2288
2289def Test_closure_in_map()
2290  mkdir('XclosureDir/tdir', 'p')
2291  writefile(['111'], 'XclosureDir/file1')
2292  writefile(['222'], 'XclosureDir/file2')
2293  writefile(['333'], 'XclosureDir/tdir/file3')
2294
2295  TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}])
2296
2297  delete('XclosureDir', 'rf')
2298enddef
2299
2300def Test_invalid_function_name()
2301  var lines =<< trim END
2302      vim9script
2303      def s: list<string>
2304  END
2305  CheckScriptFailure(lines, 'E129:')
2306
2307  lines =<< trim END
2308      vim9script
2309      def g: list<string>
2310  END
2311  CheckScriptFailure(lines, 'E129:')
2312
2313  lines =<< trim END
2314      vim9script
2315      def <SID>: list<string>
2316  END
2317  CheckScriptFailure(lines, 'E884:')
2318
2319  lines =<< trim END
2320      vim9script
2321      def F list<string>
2322  END
2323  CheckScriptFailure(lines, 'E488:')
2324enddef
2325
2326def Test_partial_call()
2327  var Xsetlist = function('setloclist', [0])
2328  Xsetlist([], ' ', {title: 'test'})
2329  getloclist(0, {title: 1})->assert_equal({title: 'test'})
2330
2331  Xsetlist = function('setloclist', [0, [], ' '])
2332  Xsetlist({title: 'test'})
2333  getloclist(0, {title: 1})->assert_equal({title: 'test'})
2334
2335  Xsetlist = function('setqflist')
2336  Xsetlist([], ' ', {title: 'test'})
2337  getqflist({title: 1})->assert_equal({title: 'test'})
2338
2339  Xsetlist = function('setqflist', [[], ' '])
2340  Xsetlist({title: 'test'})
2341  getqflist({title: 1})->assert_equal({title: 'test'})
2342
2343  var Len: func: number = function('len', ['word'])
2344  assert_equal(4, Len())
2345enddef
2346
2347def Test_cmd_modifier()
2348  tab echo '0'
2349  CheckDefFailure(['5tab echo 3'], 'E16:')
2350enddef
2351
2352def Test_restore_modifiers()
2353  # check that when compiling a :def function command modifiers are not messed
2354  # up.
2355  var lines =<< trim END
2356      vim9script
2357      set eventignore=
2358      autocmd QuickFixCmdPost * copen
2359      def AutocmdsDisabled()
2360        eval 0
2361      enddef
2362      func Func()
2363        noautocmd call s:AutocmdsDisabled()
2364        let g:ei_after = &eventignore
2365      endfunc
2366      Func()
2367  END
2368  CheckScriptSuccess(lines)
2369  g:ei_after->assert_equal('')
2370enddef
2371
2372def StackTop()
2373  eval 1
2374  eval 2
2375  # call not on fourth line
2376  StackBot()
2377enddef
2378
2379def StackBot()
2380  # throw an error
2381  eval [][0]
2382enddef
2383
2384def Test_callstack_def()
2385  try
2386    StackTop()
2387  catch
2388    v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
2389  endtry
2390enddef
2391
2392" Re-using spot for variable used in block
2393def Test_block_scoped_var()
2394  var lines =<< trim END
2395      vim9script
2396      def Func()
2397        var x = ['a', 'b', 'c']
2398        if 1
2399          var y = 'x'
2400          map(x, (_, _) => y)
2401        endif
2402        var z = x
2403        assert_equal(['x', 'x', 'x'], z)
2404      enddef
2405      Func()
2406  END
2407  CheckScriptSuccess(lines)
2408enddef
2409
2410def Test_reset_did_emsg()
2411  var lines =<< trim END
2412      @s = 'blah'
2413      au BufWinLeave * #
2414      def Func()
2415        var winid = popup_create('popup', {})
2416        exe '*s'
2417        popup_close(winid)
2418      enddef
2419      Func()
2420  END
2421  CheckScriptFailure(lines, 'E492:', 8)
2422  delfunc! g:Func
2423enddef
2424
2425def Test_did_emsg_reset()
2426  # executing an autocommand resets did_emsg, this should not result in a
2427  # builtin function considered failing
2428  var lines =<< trim END
2429      vim9script
2430      au BufWinLeave * #
2431      def Func()
2432          popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()})
2433          eval [][0]
2434      enddef
2435      nno <F3> <cmd>call <sid>Func()<cr>
2436      feedkeys("\<F3>\e", 'xt')
2437  END
2438  writefile(lines, 'XemsgReset')
2439  assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2)
2440  delete('XemsgReset')
2441  nunmap <F3>
2442  au! BufWinLeave
2443enddef
2444
2445def Test_abort_with_silent_call()
2446  var lines =<< trim END
2447      vim9script
2448      g:result = 'none'
2449      def Func()
2450        g:result += 3
2451        g:result = 'yes'
2452      enddef
2453      # error is silenced, but function aborts on error
2454      silent! Func()
2455      assert_equal('none', g:result)
2456      unlet g:result
2457  END
2458  CheckScriptSuccess(lines)
2459enddef
2460
2461def Test_continues_with_silent_error()
2462  var lines =<< trim END
2463      vim9script
2464      g:result = 'none'
2465      def Func()
2466        silent!  g:result += 3
2467        g:result = 'yes'
2468      enddef
2469      # error is silenced, function does not abort
2470      Func()
2471      assert_equal('yes', g:result)
2472      unlet g:result
2473  END
2474  CheckScriptSuccess(lines)
2475enddef
2476
2477def Test_abort_even_with_silent()
2478  var lines =<< trim END
2479      vim9script
2480      g:result = 'none'
2481      def Func()
2482        eval {-> ''}() .. '' .. {}['X']
2483        g:result = 'yes'
2484      enddef
2485      silent! Func()
2486      assert_equal('none', g:result)
2487      unlet g:result
2488  END
2489  CheckScriptSuccess(lines)
2490enddef
2491
2492def Test_cmdmod_silent_restored()
2493  var lines =<< trim END
2494      vim9script
2495      def Func()
2496        g:result = 'none'
2497        silent! g:result += 3
2498        g:result = 'none'
2499        g:result += 3
2500      enddef
2501      Func()
2502  END
2503  # can't use CheckScriptFailure, it ignores the :silent!
2504  var fname = 'Xdefsilent'
2505  writefile(lines, fname)
2506  var caught = 'no'
2507  try
2508    exe 'source ' .. fname
2509  catch /E1030:/
2510    caught = 'yes'
2511    assert_match('Func, line 4', v:throwpoint)
2512  endtry
2513  assert_equal('yes', caught)
2514  delete(fname)
2515enddef
2516
2517def Test_cmdmod_silent_nested()
2518  var lines =<< trim END
2519      vim9script
2520      var result = ''
2521
2522      def Error()
2523          result ..= 'Eb'
2524          eval [][0]
2525          result ..= 'Ea'
2526      enddef
2527
2528      def Crash()
2529          result ..= 'Cb'
2530          sil! Error()
2531          result ..= 'Ca'
2532      enddef
2533
2534      Crash()
2535      assert_equal('CbEbEaCa', result)
2536  END
2537  CheckScriptSuccess(lines)
2538enddef
2539
2540def Test_dict_member_with_silent()
2541  var lines =<< trim END
2542      vim9script
2543      g:result = 'none'
2544      var d: dict<any>
2545      def Func()
2546        try
2547          g:result = map([], (_, v) => ({}[v]))->join() .. d['']
2548        catch
2549        endtry
2550      enddef
2551      silent! Func()
2552      assert_equal('0', g:result)
2553      unlet g:result
2554  END
2555  CheckScriptSuccess(lines)
2556enddef
2557
2558def Test_skip_cmds_with_silent()
2559  var lines =<< trim END
2560      vim9script
2561
2562      def Func(b: bool)
2563        Crash()
2564      enddef
2565
2566      def Crash()
2567        sil! :/not found/d _
2568        sil! :/not found/put _
2569      enddef
2570
2571      Func(true)
2572  END
2573  CheckScriptSuccess(lines)
2574enddef
2575
2576def Test_opfunc()
2577  nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@
2578  def g:Opfunc(_: any): string
2579    setline(1, 'ASDF')
2580    return ''
2581  enddef
2582  new
2583  setline(1, 'asdf')
2584  feedkeys("\<F3>$", 'x')
2585  assert_equal('ASDF', getline(1))
2586
2587  bwipe!
2588  nunmap <F3>
2589enddef
2590
2591" this was crashing on exit
2592def Test_nested_lambda_in_closure()
2593  var lines =<< trim END
2594      vim9script
2595      command WriteDone writefile(['Done'], 'XnestedDone')
2596      def Outer()
2597          def g:Inner()
2598              echo map([1, 2, 3], {_, v -> v + 1})
2599          enddef
2600          g:Inner()
2601      enddef
2602      defcompile
2603      # not reached
2604  END
2605  if !RunVim([], lines, '--clean -c WriteDone -c quit')
2606    return
2607  endif
2608  assert_equal(['Done'], readfile('XnestedDone'))
2609  delete('XnestedDone')
2610enddef
2611
2612def Test_check_func_arg_types()
2613  var lines =<< trim END
2614      vim9script
2615      def F1(x: string): string
2616        return x
2617      enddef
2618
2619      def F2(x: number): number
2620        return x + 1
2621      enddef
2622
2623      def G(g: func): dict<func>
2624        return {f: g}
2625      enddef
2626
2627      def H(d: dict<func>): string
2628        return d.f('a')
2629      enddef
2630  END
2631
2632  CheckScriptSuccess(lines + ['echo H(G(F1))'])
2633  CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:')
2634enddef
2635
2636def Test_compile_error()
2637  var lines =<< trim END
2638    def g:Broken()
2639      echo 'a' + {}
2640    enddef
2641    call g:Broken()
2642  END
2643  # First call: compilation error
2644  CheckScriptFailure(lines, 'E1051: Wrong argument type for +')
2645
2646  # Second call won't try compiling again
2647  assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
2648  delfunc g:Broken
2649
2650  # No error when compiling with :silent!
2651  lines =<< trim END
2652    def g:Broken()
2653      echo 'a' + []
2654    enddef
2655    silent! defcompile
2656  END
2657  CheckScriptSuccess(lines)
2658
2659  # Calling the function won't try compiling again
2660  assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
2661  delfunc g:Broken
2662enddef
2663
2664def Test_ignored_argument()
2665  var lines =<< trim END
2666      vim9script
2667      def Ignore(_, _): string
2668        return 'yes'
2669      enddef
2670      assert_equal('yes', Ignore(1, 2))
2671
2672      func Ok(_)
2673        return a:_
2674      endfunc
2675      assert_equal('ok', Ok('ok'))
2676
2677      func Oktoo()
2678        let _ = 'too'
2679        return _
2680      endfunc
2681      assert_equal('too', Oktoo())
2682
2683      assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1)))
2684  END
2685  CheckScriptSuccess(lines)
2686
2687  lines =<< trim END
2688      def Ignore(_: string): string
2689        return _
2690      enddef
2691      defcompile
2692  END
2693  CheckScriptFailure(lines, 'E1181:', 1)
2694
2695  lines =<< trim END
2696      var _ = 1
2697  END
2698  CheckDefAndScriptFailure(lines, 'E1181:', 1)
2699enddef
2700
2701def Test_too_many_arguments()
2702  var lines =<< trim END
2703    echo [0, 1, 2]->map(() => 123)
2704  END
2705  CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1)
2706
2707  lines =<< trim END
2708    echo [0, 1, 2]->map((_) => 123)
2709  END
2710  CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1)
2711enddef
2712
2713def Test_closing_brace_at_start_of_line()
2714  var lines =<< trim END
2715      def Func()
2716      enddef
2717      Func(
2718      )
2719  END
2720  call CheckDefAndScriptSuccess(lines)
2721enddef
2722
2723
2724" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
2725