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