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()
21endfunc
22
23def TestCompilingError()
24  var lines =<< trim END
25    vim9script
26    def Fails()
27      echo nothing
28    enddef
29    defcompile
30  END
31  call writefile(lines, 'XTest_compile_error')
32  var buf = RunVimInTerminal('-S XTest_compile_error',
33              #{rows: 10, wait_for_ruler: 0})
34  var text = ''
35  for loop in range(100)
36    text = ''
37    for i in range(1, 9)
38      text ..= term_getline(buf, i)
39    endfor
40    if text =~ 'Error detected'
41      break
42    endif
43    sleep 20m
44  endfor
45  assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing', text)
46
47  # clean up
48  call StopVimInTerminal(buf)
49  call delete('XTest_compile_error')
50enddef
51
52def CallRecursive(n: number): number
53  return CallRecursive(n + 1)
54enddef
55
56def CallMapRecursive(l: list<number>): number
57  return map(l, {_, v -> CallMapRecursive([v])})[0]
58enddef
59
60def Test_funcdepth_error()
61  set maxfuncdepth=10
62
63  var caught = false
64  try
65    CallRecursive(1)
66  catch /E132:/
67    caught = true
68  endtry
69  assert_true(caught)
70
71  caught = false
72  try
73    CallMapRecursive([1])
74  catch /E132:/
75    caught = true
76  endtry
77  assert_true(caught)
78
79  set maxfuncdepth&
80enddef
81
82def ReturnString(): string
83  return 'string'
84enddef
85
86def ReturnNumber(): number
87  return 123
88enddef
89
90let g:notNumber = 'string'
91
92def ReturnGlobal(): number
93  return g:notNumber
94enddef
95
96def Test_return_something()
97  ReturnString()->assert_equal('string')
98  ReturnNumber()->assert_equal(123)
99  assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
100enddef
101
102def Test_missing_return()
103  CheckDefFailure(['def Missing(): number',
104                   '  if g:cond',
105                   '    echo "no return"',
106                   '  else',
107                   '    return 0',
108                   '  endif'
109                   'enddef'], 'E1027:')
110  CheckDefFailure(['def Missing(): number',
111                   '  if g:cond',
112                   '    return 1',
113                   '  else',
114                   '    echo "no return"',
115                   '  endif'
116                   'enddef'], 'E1027:')
117  CheckDefFailure(['def Missing(): number',
118                   '  if g:cond',
119                   '    return 1',
120                   '  else',
121                   '    return 2',
122                   '  endif'
123                   '  return 3'
124                   'enddef'], 'E1095:')
125enddef
126
127def Test_return_bool()
128  var lines =<< trim END
129      vim9script
130      def MenuFilter(id: number, key: string): bool
131        return popup_filter_menu(id, key)
132      enddef
133      def YesnoFilter(id: number, key: string): bool
134        return popup_filter_yesno(id, key)
135      enddef
136      defcompile
137  END
138  CheckScriptSuccess(lines)
139enddef
140
141let s:nothing = 0
142def ReturnNothing()
143  s:nothing = 1
144  if true
145    return
146  endif
147  s:nothing = 2
148enddef
149
150def Test_return_nothing()
151  ReturnNothing()
152  s:nothing->assert_equal(1)
153enddef
154
155func Increment()
156  let g:counter += 1
157endfunc
158
159def Test_call_ufunc_count()
160  g:counter = 1
161  Increment()
162  Increment()
163  Increment()
164  # works with and without :call
165  g:counter->assert_equal(4)
166  eval g:counter->assert_equal(4)
167  unlet g:counter
168enddef
169
170def MyVarargs(arg: string, ...rest: list<string>): string
171  var res = arg
172  for s in rest
173    res ..= ',' .. s
174  endfor
175  return res
176enddef
177
178def Test_call_varargs()
179  MyVarargs('one')->assert_equal('one')
180  MyVarargs('one', 'two')->assert_equal('one,two')
181  MyVarargs('one', 'two', 'three')->assert_equal('one,two,three')
182enddef
183
184def MyDefaultArgs(name = 'string'): string
185  return name
186enddef
187
188def MyDefaultSecond(name: string, second: bool  = true): string
189  return second ? name : 'none'
190enddef
191
192def Test_call_default_args()
193  MyDefaultArgs()->assert_equal('string')
194  MyDefaultArgs('one')->assert_equal('one')
195  assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args')
196
197  MyDefaultSecond('test')->assert_equal('test')
198  MyDefaultSecond('test', true)->assert_equal('test')
199  MyDefaultSecond('test', false)->assert_equal('none')
200
201  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
202  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
203enddef
204
205def Test_nested_function()
206  def Nested(arg: string): string
207    return 'nested ' .. arg
208  enddef
209  Nested('function')->assert_equal('nested function')
210
211  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
212  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
213
214  CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
215  CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
216  CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
217
218  CheckDefFailure([
219        'def Outer()',
220        '  def Inner()',
221        '    # comment',
222        '  enddef',
223        '  def Inner()',
224        '  enddef',
225        'enddef'], 'E1073:')
226  CheckDefFailure([
227        'def Outer()',
228        '  def Inner()',
229        '    # comment',
230        '  enddef',
231        '  def! Inner()',
232        '  enddef',
233        'enddef'], 'E1117:')
234enddef
235
236func Test_call_default_args_from_func()
237  call MyDefaultArgs()->assert_equal('string')
238  call MyDefaultArgs('one')->assert_equal('one')
239  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func')
240endfunc
241
242def Test_nested_global_function()
243  var lines =<< trim END
244      vim9script
245      def Outer()
246          def g:Inner(): string
247              return 'inner'
248          enddef
249      enddef
250      defcompile
251      Outer()
252      g:Inner()->assert_equal('inner')
253      delfunc g:Inner
254      Outer()
255      g:Inner()->assert_equal('inner')
256      delfunc g:Inner
257      Outer()
258      g:Inner()->assert_equal('inner')
259      delfunc g:Inner
260  END
261  CheckScriptSuccess(lines)
262
263  lines =<< trim END
264      vim9script
265      def Outer()
266          def g:Inner(): string
267              return 'inner'
268          enddef
269      enddef
270      defcompile
271      Outer()
272      Outer()
273  END
274  CheckScriptFailure(lines, "E122:")
275
276  lines =<< trim END
277      vim9script
278      def Func()
279        echo 'script'
280      enddef
281      def Outer()
282        def Func()
283          echo 'inner'
284        enddef
285      enddef
286      defcompile
287  END
288  CheckScriptFailure(lines, "E1073:")
289enddef
290
291def Test_global_local_function()
292  var lines =<< trim END
293      vim9script
294      def g:Func(): string
295          return 'global'
296      enddef
297      def Func(): string
298          return 'local'
299      enddef
300      g:Func()->assert_equal('global')
301      Func()->assert_equal('local')
302  END
303  CheckScriptSuccess(lines)
304
305  lines =<< trim END
306      vim9script
307      def g:Funcy()
308        echo 'funcy'
309      enddef
310      s:Funcy()
311  END
312  CheckScriptFailure(lines, 'E117:')
313enddef
314
315def Test_local_function_shadows_global()
316  var lines =<< trim END
317      vim9script
318      def g:Gfunc(): string
319        return 'global'
320      enddef
321      def AnotherFunc(): number
322        var Gfunc = function('len')
323        return Gfunc('testing')
324      enddef
325      g:Gfunc()->assert_equal('global')
326      AnotherFunc()->assert_equal(7)
327      delfunc g:Gfunc
328  END
329  CheckScriptSuccess(lines)
330
331  lines =<< trim END
332      vim9script
333      def g:Func(): string
334        return 'global'
335      enddef
336      def AnotherFunc()
337        g:Func = function('len')
338      enddef
339      AnotherFunc()
340  END
341  CheckScriptFailure(lines, 'E705:')
342  delfunc g:Func
343enddef
344
345func TakesOneArg(arg)
346  echo a:arg
347endfunc
348
349def Test_call_wrong_args()
350  CheckDefFailure(['TakesOneArg()'], 'E119:')
351  CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
352  CheckDefFailure(['bufnr(xxx)'], 'E1001:')
353  CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
354
355  var lines =<< trim END
356    vim9script
357    def Func(s: string)
358      echo s
359    enddef
360    Func([])
361  END
362  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
363
364  lines =<< trim END
365    vim9script
366    def FuncOne(nr: number)
367      echo nr
368    enddef
369    def FuncTwo()
370      FuncOne()
371    enddef
372    defcompile
373  END
374  writefile(lines, 'Xscript')
375  var didCatch = false
376  try
377    source Xscript
378  catch
379    assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception)
380    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
381    didCatch = true
382  endtry
383  assert_true(didCatch)
384
385  lines =<< trim END
386    vim9script
387    def FuncOne(nr: number)
388      echo nr
389    enddef
390    def FuncTwo()
391      FuncOne(1, 2)
392    enddef
393    defcompile
394  END
395  writefile(lines, 'Xscript')
396  didCatch = false
397  try
398    source Xscript
399  catch
400    assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception)
401    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
402    didCatch = true
403  endtry
404  assert_true(didCatch)
405
406  delete('Xscript')
407enddef
408
409def Test_call_lambda_args()
410  CheckDefFailure(['echo {i -> 0}()'],
411                  'E119: Not enough arguments for function: {i -> 0}()')
412
413  var lines =<< trim END
414      var Ref = {x: number, y: number -> x + y}
415      echo Ref(1, 'x')
416  END
417  CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string')
418enddef
419
420" Default arg and varargs
421def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
422  var res = one .. ',' .. two
423  for s in rest
424    res ..= ',' .. s
425  endfor
426  return res
427enddef
428
429def Test_call_def_varargs()
430  assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs')
431  MyDefVarargs('one')->assert_equal('one,foo')
432  MyDefVarargs('one', 'two')->assert_equal('one,two')
433  MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three')
434  CheckDefFailure(['MyDefVarargs("one", 22)'],
435      'E1013: Argument 2: type mismatch, expected string but got number')
436  CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
437      'E1013: Argument 3: type mismatch, expected string but got number')
438
439  var lines =<< trim END
440      vim9script
441      def Func(...l: list<string>)
442        echo l
443      enddef
444      Func('a', 'b', 'c')
445  END
446  CheckScriptSuccess(lines)
447
448  lines =<< trim END
449      vim9script
450      def Func(...l: list<string>)
451        echo l
452      enddef
453      Func()
454  END
455  CheckScriptSuccess(lines)
456
457  lines =<< trim END
458      vim9script
459      def Func(...l: any)
460        echo l
461      enddef
462      Func(0)
463  END
464  CheckScriptSuccess(lines)
465
466  lines =<< trim END
467      vim9script
468      def Func(..._l: list<string>)
469        echo _l
470      enddef
471      Func('a', 'b', 'c')
472  END
473  CheckScriptSuccess(lines)
474
475  lines =<< trim END
476      vim9script
477      def Func(...l: list<string>)
478        echo l
479      enddef
480      Func(1, 2, 3)
481  END
482  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
483
484  lines =<< trim END
485      vim9script
486      def Func(...l: list<string>)
487        echo l
488      enddef
489      Func('a', 9)
490  END
491  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch')
492
493  lines =<< trim END
494      vim9script
495      def Func(...l: list<string>)
496        echo l
497      enddef
498      Func(1, 'a')
499  END
500  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
501enddef
502
503let s:value = ''
504
505def FuncOneDefArg(opt = 'text')
506  s:value = opt
507enddef
508
509def FuncTwoDefArg(nr = 123, opt = 'text'): string
510  return nr .. opt
511enddef
512
513def FuncVarargs(...arg: list<string>): string
514  return join(arg, ',')
515enddef
516
517def Test_func_type_varargs()
518  var RefDefArg: func(?string)
519  RefDefArg = FuncOneDefArg
520  RefDefArg()
521  s:value->assert_equal('text')
522  RefDefArg('some')
523  s:value->assert_equal('some')
524
525  var RefDef2Arg: func(?number, ?string): string
526  RefDef2Arg = FuncTwoDefArg
527  RefDef2Arg()->assert_equal('123text')
528  RefDef2Arg(99)->assert_equal('99text')
529  RefDef2Arg(77, 'some')->assert_equal('77some')
530
531  CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:')
532  CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
533
534  var RefVarargs: func(...list<string>): string
535  RefVarargs = FuncVarargs
536  RefVarargs()->assert_equal('')
537  RefVarargs('one')->assert_equal('one')
538  RefVarargs('one', 'two')->assert_equal('one,two')
539
540  CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:')
541  CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:')
542enddef
543
544" Only varargs
545def MyVarargsOnly(...args: list<string>): string
546  return join(args, ',')
547enddef
548
549def Test_call_varargs_only()
550  MyVarargsOnly()->assert_equal('')
551  MyVarargsOnly('one')->assert_equal('one')
552  MyVarargsOnly('one', 'two')->assert_equal('one,two')
553  CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
554  CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number')
555enddef
556
557def Test_using_var_as_arg()
558  writefile(['def Func(x: number)',  'var x = 234', 'enddef', 'defcompile'], 'Xdef')
559  assert_fails('so Xdef', 'E1006:', '', 1, 'Func')
560  delete('Xdef')
561enddef
562
563def DictArg(arg: dict<string>)
564  arg['key'] = 'value'
565enddef
566
567def ListArg(arg: list<string>)
568  arg[0] = 'value'
569enddef
570
571def Test_assign_to_argument()
572  # works for dict and list
573  var d: dict<string> = {}
574  DictArg(d)
575  d['key']->assert_equal('value')
576  var l: list<string> = []
577  ListArg(l)
578  l[0]->assert_equal('value')
579
580  CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
581enddef
582
583" These argument names are reserved in legacy functions.
584def WithReservedNames(firstline: string, lastline: string): string
585  return firstline .. lastline
586enddef
587
588def Test_argument_names()
589  assert_equal('OK', WithReservedNames('O', 'K'))
590enddef
591
592def Test_call_func_defined_later()
593  g:DefinedLater('one')->assert_equal('one')
594  assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
595enddef
596
597func DefinedLater(arg)
598  return a:arg
599endfunc
600
601def Test_call_funcref()
602  g:SomeFunc('abc')->assert_equal(3)
603  assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
604  assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
605
606  var lines =<< trim END
607    vim9script
608    def RetNumber(): number
609      return 123
610    enddef
611    var Funcref: func: number = function('RetNumber')
612    Funcref()->assert_equal(123)
613  END
614  CheckScriptSuccess(lines)
615
616  lines =<< trim END
617    vim9script
618    def RetNumber(): number
619      return 123
620    enddef
621    def Bar(F: func: number): number
622      return F()
623    enddef
624    var Funcref = function('RetNumber')
625    Bar(Funcref)->assert_equal(123)
626  END
627  CheckScriptSuccess(lines)
628
629  lines =<< trim END
630    vim9script
631    def UseNumber(nr: number)
632      echo nr
633    enddef
634    var Funcref: func(number) = function('UseNumber')
635    Funcref(123)
636  END
637  CheckScriptSuccess(lines)
638
639  lines =<< trim END
640    vim9script
641    def UseNumber(nr: number)
642      echo nr
643    enddef
644    var Funcref: func(string) = function('UseNumber')
645  END
646  CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
647
648  lines =<< trim END
649    vim9script
650    def EchoNr(nr = 34)
651      g:echo = nr
652    enddef
653    var Funcref: func(?number) = function('EchoNr')
654    Funcref()
655    g:echo->assert_equal(34)
656    Funcref(123)
657    g:echo->assert_equal(123)
658  END
659  CheckScriptSuccess(lines)
660
661  lines =<< trim END
662    vim9script
663    def EchoList(...l: list<number>)
664      g:echo = l
665    enddef
666    var Funcref: func(...list<number>) = function('EchoList')
667    Funcref()
668    g:echo->assert_equal([])
669    Funcref(1, 2, 3)
670    g:echo->assert_equal([1, 2, 3])
671  END
672  CheckScriptSuccess(lines)
673
674  lines =<< trim END
675    vim9script
676    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
677      g:optarg = opt
678      g:listarg = l
679      return nr
680    enddef
681    var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
682    Funcref(10)->assert_equal(10)
683    g:optarg->assert_equal(12)
684    g:listarg->assert_equal([])
685
686    Funcref(11, 22)->assert_equal(11)
687    g:optarg->assert_equal(22)
688    g:listarg->assert_equal([])
689
690    Funcref(17, 18, 1, 2, 3)->assert_equal(17)
691    g:optarg->assert_equal(18)
692    g:listarg->assert_equal([1, 2, 3])
693  END
694  CheckScriptSuccess(lines)
695enddef
696
697let SomeFunc = function('len')
698let NotAFunc = 'text'
699
700def CombineFuncrefTypes()
701  # same arguments, different return type
702  var Ref1: func(bool): string
703  var Ref2: func(bool): number
704  var Ref3: func(bool): any
705  Ref3 = g:cond ? Ref1 : Ref2
706
707  # different number of arguments
708  var Refa1: func(bool): number
709  var Refa2: func(bool, number): number
710  var Refa3: func: number
711  Refa3 = g:cond ? Refa1 : Refa2
712
713  # different argument types
714  var Refb1: func(bool, string): number
715  var Refb2: func(string, number): number
716  var Refb3: func(any, any): number
717  Refb3 = g:cond ? Refb1 : Refb2
718enddef
719
720def FuncWithForwardCall()
721  return g:DefinedEvenLater("yes")
722enddef
723
724def DefinedEvenLater(arg: string): string
725  return arg
726enddef
727
728def Test_error_in_nested_function()
729  # Error in called function requires unwinding the call stack.
730  assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
731enddef
732
733def Test_return_type_wrong()
734  CheckScriptFailure([
735        'def Func(): number',
736        'return "a"',
737        'enddef',
738        'defcompile'], 'expected number but got string')
739  CheckScriptFailure([
740        'def Func(): string',
741        'return 1',
742        'enddef',
743        'defcompile'], 'expected string but got number')
744  CheckScriptFailure([
745        'def Func(): void',
746        'return "a"',
747        'enddef',
748        'defcompile'],
749        'E1096: Returning a value in a function without a return type')
750  CheckScriptFailure([
751        'def Func()',
752        'return "a"',
753        'enddef',
754        'defcompile'],
755        'E1096: Returning a value in a function without a return type')
756
757  CheckScriptFailure([
758        'def Func(): number',
759        'return',
760        'enddef',
761        'defcompile'], 'E1003:')
762
763  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
764  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
765  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
766
767  CheckScriptFailure([
768        'vim9script',
769        'def FuncB()',
770        '  return 123',
771        'enddef',
772        'def FuncA()',
773        '   FuncB()',
774        'enddef',
775        'defcompile'], 'E1096:')
776enddef
777
778def Test_arg_type_wrong()
779  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
780  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
781  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
782  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
783enddef
784
785def Test_vim9script_call()
786  var lines =<< trim END
787    vim9script
788    var name = ''
789    def MyFunc(arg: string)
790       name = arg
791    enddef
792    MyFunc('foobar')
793    name->assert_equal('foobar')
794
795    var str = 'barfoo'
796    str->MyFunc()
797    name->assert_equal('barfoo')
798
799    g:value = 'value'
800    g:value->MyFunc()
801    name->assert_equal('value')
802
803    var listvar = []
804    def ListFunc(arg: list<number>)
805       listvar = arg
806    enddef
807    [1, 2, 3]->ListFunc()
808    listvar->assert_equal([1, 2, 3])
809
810    var dictvar = {}
811    def DictFunc(arg: dict<number>)
812       dictvar = arg
813    enddef
814    {'a': 1, 'b': 2}->DictFunc()
815    dictvar->assert_equal(#{a: 1, b: 2})
816    def CompiledDict()
817      {'a': 3, 'b': 4}->DictFunc()
818    enddef
819    CompiledDict()
820    dictvar->assert_equal(#{a: 3, b: 4})
821
822    #{a: 3, b: 4}->DictFunc()
823    dictvar->assert_equal(#{a: 3, b: 4})
824
825    ('text')->MyFunc()
826    name->assert_equal('text')
827    ("some")->MyFunc()
828    name->assert_equal('some')
829
830    # line starting with single quote is not a mark
831    # line starting with double quote can be a method call
832    'asdfasdf'->MyFunc()
833    name->assert_equal('asdfasdf')
834    "xyz"->MyFunc()
835    name->assert_equal('xyz')
836
837    def UseString()
838      'xyork'->MyFunc()
839    enddef
840    UseString()
841    name->assert_equal('xyork')
842
843    def UseString2()
844      "knife"->MyFunc()
845    enddef
846    UseString2()
847    name->assert_equal('knife')
848
849    # prepending a colon makes it a mark
850    new
851    setline(1, ['aaa', 'bbb', 'ccc'])
852    normal! 3Gmt1G
853    :'t
854    getcurpos()[1]->assert_equal(3)
855    bwipe!
856
857    MyFunc(
858        'continued'
859        )
860    assert_equal('continued',
861            name
862            )
863
864    call MyFunc(
865        'more'
866          ..
867          'lines'
868        )
869    assert_equal(
870        'morelines',
871        name)
872  END
873  writefile(lines, 'Xcall.vim')
874  source Xcall.vim
875  delete('Xcall.vim')
876enddef
877
878def Test_vim9script_call_fail_decl()
879  var lines =<< trim END
880    vim9script
881    var name = ''
882    def MyFunc(arg: string)
883       var name = 123
884    enddef
885    defcompile
886  END
887  CheckScriptFailure(lines, 'E1054:')
888enddef
889
890def Test_vim9script_call_fail_type()
891  var lines =<< trim END
892    vim9script
893    def MyFunc(arg: string)
894      echo arg
895    enddef
896    MyFunc(1234)
897  END
898  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
899enddef
900
901def Test_vim9script_call_fail_const()
902  var lines =<< trim END
903    vim9script
904    const var = ''
905    def MyFunc(arg: string)
906       var = 'asdf'
907    enddef
908    defcompile
909  END
910  writefile(lines, 'Xcall_const.vim')
911  assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
912  delete('Xcall_const.vim')
913enddef
914
915" Test that inside :function a Python function can be defined, :def is not
916" recognized.
917func Test_function_python()
918  CheckFeature python3
919  let py = 'python3'
920  execute py "<< EOF"
921def do_something():
922  return 1
923EOF
924endfunc
925
926def Test_delfunc()
927  var lines =<< trim END
928    vim9script
929    def g:GoneSoon()
930      echo 'hello'
931    enddef
932
933    def CallGoneSoon()
934      GoneSoon()
935    enddef
936    defcompile
937
938    delfunc g:GoneSoon
939    CallGoneSoon()
940  END
941  writefile(lines, 'XToDelFunc')
942  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
943  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
944
945  delete('XToDelFunc')
946enddef
947
948def Test_redef_failure()
949  writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
950  so Xdef
951  writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
952  so Xdef
953  writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
954  assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
955  writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
956  so Xdef
957  delete('Xdef')
958
959  g:Func0()->assert_equal(0)
960  g:Func1()->assert_equal('Func1')
961  g:Func2()->assert_equal('Func2')
962
963  delfunc! Func0
964  delfunc! Func1
965  delfunc! Func2
966enddef
967
968def Test_vim9script_func()
969  var lines =<< trim END
970    vim9script
971    func Func(arg)
972      echo a:arg
973    endfunc
974    Func('text')
975  END
976  writefile(lines, 'XVim9Func')
977  so XVim9Func
978
979  delete('XVim9Func')
980enddef
981
982let s:funcResult = 0
983
984def FuncNoArgNoRet()
985  s:funcResult = 11
986enddef
987
988def FuncNoArgRetNumber(): number
989  s:funcResult = 22
990  return 1234
991enddef
992
993def FuncNoArgRetString(): string
994  s:funcResult = 45
995  return 'text'
996enddef
997
998def FuncOneArgNoRet(arg: number)
999  s:funcResult = arg
1000enddef
1001
1002def FuncOneArgRetNumber(arg: number): number
1003  s:funcResult = arg
1004  return arg
1005enddef
1006
1007def FuncTwoArgNoRet(one: bool, two: number)
1008  s:funcResult = two
1009enddef
1010
1011def FuncOneArgRetString(arg: string): string
1012  return arg
1013enddef
1014
1015def FuncOneArgRetAny(arg: any): any
1016  return arg
1017enddef
1018
1019def Test_func_type()
1020  var Ref1: func()
1021  s:funcResult = 0
1022  Ref1 = FuncNoArgNoRet
1023  Ref1()
1024  s:funcResult->assert_equal(11)
1025
1026  var Ref2: func
1027  s:funcResult = 0
1028  Ref2 = FuncNoArgNoRet
1029  Ref2()
1030  s:funcResult->assert_equal(11)
1031
1032  s:funcResult = 0
1033  Ref2 = FuncOneArgNoRet
1034  Ref2(12)
1035  s:funcResult->assert_equal(12)
1036
1037  s:funcResult = 0
1038  Ref2 = FuncNoArgRetNumber
1039  Ref2()->assert_equal(1234)
1040  s:funcResult->assert_equal(22)
1041
1042  s:funcResult = 0
1043  Ref2 = FuncOneArgRetNumber
1044  Ref2(13)->assert_equal(13)
1045  s:funcResult->assert_equal(13)
1046enddef
1047
1048def Test_repeat_return_type()
1049  var res = 0
1050  for n in repeat([1], 3)
1051    res += n
1052  endfor
1053  res->assert_equal(3)
1054
1055  res = 0
1056  for n in add([1, 2], 3)
1057    res += n
1058  endfor
1059  res->assert_equal(6)
1060enddef
1061
1062def Test_argv_return_type()
1063  next fileone filetwo
1064  var res = ''
1065  for name in argv()
1066    res ..= name
1067  endfor
1068  res->assert_equal('fileonefiletwo')
1069enddef
1070
1071def Test_func_type_part()
1072  var RefVoid: func: void
1073  RefVoid = FuncNoArgNoRet
1074  RefVoid = FuncOneArgNoRet
1075  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1076  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
1077
1078  var RefAny: func(): any
1079  RefAny = FuncNoArgRetNumber
1080  RefAny = FuncNoArgRetString
1081  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1082  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
1083
1084  var RefAnyNoArgs: func: any = RefAny
1085
1086  var RefNr: func: number
1087  RefNr = FuncNoArgRetNumber
1088  RefNr = FuncOneArgRetNumber
1089  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1090  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
1091
1092  var RefStr: func: string
1093  RefStr = FuncNoArgRetString
1094  RefStr = FuncOneArgRetString
1095  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1096  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
1097enddef
1098
1099def Test_func_type_fails()
1100  CheckDefFailure(['var ref1: func()'], 'E704:')
1101
1102  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1103  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1104  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1105  CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1106  CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1107  CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
1108
1109  CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:')
1110  CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:')
1111  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:')
1112  CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:')
1113enddef
1114
1115def Test_func_return_type()
1116  var nr: number
1117  nr = FuncNoArgRetNumber()
1118  nr->assert_equal(1234)
1119
1120  nr = FuncOneArgRetAny(122)
1121  nr->assert_equal(122)
1122
1123  var str: string
1124  str = FuncOneArgRetAny('yes')
1125  str->assert_equal('yes')
1126
1127  CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
1128enddef
1129
1130def Test_func_common_type()
1131  def FuncOne(n: number): number
1132    return n
1133  enddef
1134  def FuncTwo(s: string): number
1135    return len(s)
1136  enddef
1137  def FuncThree(n: number, s: string): number
1138    return n + len(s)
1139  enddef
1140  var list = [FuncOne, FuncTwo, FuncThree]
1141  assert_equal(8, list[0](8))
1142  assert_equal(4, list[1]('word'))
1143  assert_equal(7, list[2](3, 'word'))
1144enddef
1145
1146def MultiLine(
1147    arg1: string,
1148    arg2 = 1234,
1149    ...rest: list<string>
1150      ): string
1151  return arg1 .. arg2 .. join(rest, '-')
1152enddef
1153
1154def MultiLineComment(
1155    arg1: string, # comment
1156    arg2 = 1234, # comment
1157    ...rest: list<string> # comment
1158      ): string # comment
1159  return arg1 .. arg2 .. join(rest, '-')
1160enddef
1161
1162def Test_multiline()
1163  MultiLine('text')->assert_equal('text1234')
1164  MultiLine('text', 777)->assert_equal('text777')
1165  MultiLine('text', 777, 'one')->assert_equal('text777one')
1166  MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1167enddef
1168
1169func Test_multiline_not_vim9()
1170  call MultiLine('text')->assert_equal('text1234')
1171  call MultiLine('text', 777)->assert_equal('text777')
1172  call MultiLine('text', 777, 'one')->assert_equal('text777one')
1173  call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
1174endfunc
1175
1176
1177" When using CheckScriptFailure() for the below test, E1010 is generated instead
1178" of E1056.
1179func Test_E1056_1059()
1180  let caught_1056 = 0
1181  try
1182    def F():
1183      return 1
1184    enddef
1185  catch /E1056:/
1186    let caught_1056 = 1
1187  endtry
1188  eval caught_1056->assert_equal(1)
1189
1190  let caught_1059 = 0
1191  try
1192    def F5(items : list)
1193      echo 'a'
1194    enddef
1195  catch /E1059:/
1196    let caught_1059 = 1
1197  endtry
1198  eval caught_1059->assert_equal(1)
1199endfunc
1200
1201func DelMe()
1202  echo 'DelMe'
1203endfunc
1204
1205def Test_error_reporting()
1206  # comment lines at the start of the function
1207  var lines =<< trim END
1208    " comment
1209    def Func()
1210      # comment
1211      # comment
1212      invalid
1213    enddef
1214    defcompile
1215  END
1216  writefile(lines, 'Xdef')
1217  try
1218    source Xdef
1219    assert_report('should have failed')
1220  catch /E476:/
1221    v:exception->assert_match('Invalid command: invalid')
1222    v:throwpoint->assert_match(', line 3$')
1223  endtry
1224
1225  # comment lines after the start of the function
1226  lines =<< trim END
1227    " comment
1228    def Func()
1229      var x = 1234
1230      # comment
1231      # comment
1232      invalid
1233    enddef
1234    defcompile
1235  END
1236  writefile(lines, 'Xdef')
1237  try
1238    source Xdef
1239    assert_report('should have failed')
1240  catch /E476:/
1241    v:exception->assert_match('Invalid command: invalid')
1242    v:throwpoint->assert_match(', line 4$')
1243  endtry
1244
1245  lines =<< trim END
1246    vim9script
1247    def Func()
1248      var db = #{foo: 1, bar: 2}
1249      # comment
1250      var x = db.asdf
1251    enddef
1252    defcompile
1253    Func()
1254  END
1255  writefile(lines, 'Xdef')
1256  try
1257    source Xdef
1258    assert_report('should have failed')
1259  catch /E716:/
1260    v:throwpoint->assert_match('_Func, line 3$')
1261  endtry
1262
1263  delete('Xdef')
1264enddef
1265
1266def Test_deleted_function()
1267  CheckDefExecFailure([
1268      'var RefMe: func = function("g:DelMe")',
1269      'delfunc g:DelMe',
1270      'echo RefMe()'], 'E117:')
1271enddef
1272
1273def Test_unknown_function()
1274  CheckDefExecFailure([
1275      'var Ref: func = function("NotExist")',
1276      'delfunc g:NotExist'], 'E700:')
1277enddef
1278
1279def RefFunc(Ref: func(string): string): string
1280  return Ref('more')
1281enddef
1282
1283def Test_closure_simple()
1284  var local = 'some '
1285  RefFunc({s -> local .. s})->assert_equal('some more')
1286enddef
1287
1288def MakeRef()
1289  var local = 'some '
1290  g:Ref = {s -> local .. s}
1291enddef
1292
1293def Test_closure_ref_after_return()
1294  MakeRef()
1295  g:Ref('thing')->assert_equal('some thing')
1296  unlet g:Ref
1297enddef
1298
1299def MakeTwoRefs()
1300  var local = ['some']
1301  g:Extend = {s -> local->add(s)}
1302  g:Read = {-> local}
1303enddef
1304
1305def Test_closure_two_refs()
1306  MakeTwoRefs()
1307  join(g:Read(), ' ')->assert_equal('some')
1308  g:Extend('more')
1309  join(g:Read(), ' ')->assert_equal('some more')
1310  g:Extend('even')
1311  join(g:Read(), ' ')->assert_equal('some more even')
1312
1313  unlet g:Extend
1314  unlet g:Read
1315enddef
1316
1317def ReadRef(Ref: func(): list<string>): string
1318  return join(Ref(), ' ')
1319enddef
1320
1321def ExtendRef(Ref: func(string): list<string>, add: string)
1322  Ref(add)
1323enddef
1324
1325def Test_closure_two_indirect_refs()
1326  MakeTwoRefs()
1327  ReadRef(g:Read)->assert_equal('some')
1328  ExtendRef(g:Extend, 'more')
1329  ReadRef(g:Read)->assert_equal('some more')
1330  ExtendRef(g:Extend, 'even')
1331  ReadRef(g:Read)->assert_equal('some more even')
1332
1333  unlet g:Extend
1334  unlet g:Read
1335enddef
1336
1337def MakeArgRefs(theArg: string)
1338  var local = 'loc_val'
1339  g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
1340enddef
1341
1342def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
1343  var local = 'the_loc'
1344  g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
1345enddef
1346
1347def Test_closure_using_argument()
1348  MakeArgRefs('arg_val')
1349  g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
1350
1351  MakeArgRefsVarargs('arg_val', 'one', 'two')
1352  g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
1353
1354  unlet g:UseArg
1355  unlet g:UseVararg
1356enddef
1357
1358def MakeGetAndAppendRefs()
1359  var local = 'a'
1360
1361  def Append(arg: string)
1362    local ..= arg
1363  enddef
1364  g:Append = Append
1365
1366  def Get(): string
1367    return local
1368  enddef
1369  g:Get = Get
1370enddef
1371
1372def Test_closure_append_get()
1373  MakeGetAndAppendRefs()
1374  g:Get()->assert_equal('a')
1375  g:Append('-b')
1376  g:Get()->assert_equal('a-b')
1377  g:Append('-c')
1378  g:Get()->assert_equal('a-b-c')
1379
1380  unlet g:Append
1381  unlet g:Get
1382enddef
1383
1384def Test_nested_closure()
1385  var local = 'text'
1386  def Closure(arg: string): string
1387    return local .. arg
1388  enddef
1389  Closure('!!!')->assert_equal('text!!!')
1390enddef
1391
1392func GetResult(Ref)
1393  return a:Ref('some')
1394endfunc
1395
1396def Test_call_closure_not_compiled()
1397  var text = 'text'
1398  g:Ref = {s ->  s .. text}
1399  GetResult(g:Ref)->assert_equal('sometext')
1400enddef
1401
1402def Test_double_closure_fails()
1403  var lines =<< trim END
1404    vim9script
1405    def Func()
1406      var name = 0
1407      for i in range(2)
1408          timer_start(0, {-> name})
1409      endfor
1410    enddef
1411    Func()
1412  END
1413  CheckScriptSuccess(lines)
1414enddef
1415
1416def Test_nested_closure_used()
1417  var lines =<< trim END
1418      vim9script
1419      def Func()
1420        var x = 'hello'
1421        var Closure = {-> x}
1422        g:Myclosure = {-> Closure()}
1423      enddef
1424      Func()
1425      assert_equal('hello', g:Myclosure())
1426  END
1427  CheckScriptSuccess(lines)
1428enddef
1429
1430def Test_nested_closure_fails()
1431  var lines =<< trim END
1432    vim9script
1433    def FuncA()
1434      FuncB(0)
1435    enddef
1436    def FuncB(n: number): list<string>
1437      return map([0], {_, v -> n})
1438    enddef
1439    FuncA()
1440  END
1441  CheckScriptFailure(lines, 'E1012:')
1442enddef
1443
1444def Test_nested_lambda()
1445  var lines =<< trim END
1446    vim9script
1447    def Func()
1448      var x = 4
1449      var Lambda1 = {-> 7}
1450      var Lambda2 = {-> [Lambda1(), x]}
1451      var res = Lambda2()
1452      assert_equal([7, 4], res)
1453    enddef
1454    Func()
1455  END
1456  CheckScriptSuccess(lines)
1457enddef
1458
1459def Shadowed(): list<number>
1460  var FuncList: list<func: number> = [{ -> 42}]
1461  return FuncList->map({_, Shadowed -> Shadowed()})
1462enddef
1463
1464def Test_lambda_arg_shadows_func()
1465  assert_equal([42], Shadowed())
1466enddef
1467
1468def Line_continuation_in_def(dir: string = ''): string
1469  var path: string = empty(dir)
1470          \ ? 'empty'
1471          \ : 'full'
1472  return path
1473enddef
1474
1475def Test_line_continuation_in_def()
1476  Line_continuation_in_def('.')->assert_equal('full')
1477enddef
1478
1479def Test_script_var_in_lambda()
1480  var lines =<< trim END
1481      vim9script
1482      var script = 'test'
1483      assert_equal(['test'], map(['one'], {-> script}))
1484  END
1485  CheckScriptSuccess(lines)
1486enddef
1487
1488def Line_continuation_in_lambda(): list<string>
1489  var x = range(97, 100)
1490      ->map({_, v -> nr2char(v)
1491          ->toupper()})
1492      ->reverse()
1493  return x
1494enddef
1495
1496def Test_line_continuation_in_lambda()
1497  Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
1498enddef
1499
1500func Test_silent_echo()
1501  CheckScreendump
1502
1503  let lines =<< trim END
1504    vim9script
1505    def EchoNothing()
1506      silent echo ''
1507    enddef
1508    defcompile
1509  END
1510  call writefile(lines, 'XTest_silent_echo')
1511
1512  " Check that the balloon shows up after a mouse move
1513  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
1514  call term_sendkeys(buf, ":abc")
1515  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
1516
1517  " clean up
1518  call StopVimInTerminal(buf)
1519  call delete('XTest_silent_echo')
1520endfunc
1521
1522def SilentlyError()
1523  execute('silent! invalid')
1524  g:did_it = 'yes'
1525enddef
1526
1527func UserError()
1528  silent! invalid
1529endfunc
1530
1531def SilentlyUserError()
1532  UserError()
1533  g:did_it = 'yes'
1534enddef
1535
1536" This can't be a :def function, because the assert would not be reached.
1537func Test_ignore_silent_error()
1538  let g:did_it = 'no'
1539  call SilentlyError()
1540  call assert_equal('yes', g:did_it)
1541
1542  let g:did_it = 'no'
1543  call SilentlyUserError()
1544  call assert_equal('yes', g:did_it)
1545
1546  unlet g:did_it
1547endfunc
1548
1549def Test_ignore_silent_error_in_filter()
1550  var lines =<< trim END
1551      vim9script
1552      def Filter(winid: number, key: string): bool
1553          if key == 'o'
1554              silent! eval [][0]
1555              return true
1556          endif
1557          return popup_filter_menu(winid, key)
1558      enddef
1559
1560      popup_create('popup', #{filter: Filter})
1561      feedkeys("o\r", 'xnt')
1562  END
1563  CheckScriptSuccess(lines)
1564enddef
1565
1566def Fibonacci(n: number): number
1567  if n < 2
1568    return n
1569  else
1570    return Fibonacci(n - 1) + Fibonacci(n - 2)
1571  endif
1572enddef
1573
1574def Test_recursive_call()
1575  Fibonacci(20)->assert_equal(6765)
1576enddef
1577
1578def TreeWalk(dir: string): list<any>
1579  return readdir(dir)->map({_, val ->
1580            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
1581               ? {[val]: TreeWalk(dir .. '/' .. val)}
1582               : val
1583             })
1584enddef
1585
1586def Test_closure_in_map()
1587  mkdir('XclosureDir/tdir', 'p')
1588  writefile(['111'], 'XclosureDir/file1')
1589  writefile(['222'], 'XclosureDir/file2')
1590  writefile(['333'], 'XclosureDir/tdir/file3')
1591
1592  TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {'tdir': ['file3']}])
1593
1594  delete('XclosureDir', 'rf')
1595enddef
1596
1597def Test_invalid_function_name()
1598  var lines =<< trim END
1599      vim9script
1600      def s: list<string>
1601  END
1602  CheckScriptFailure(lines, 'E129:')
1603
1604  lines =<< trim END
1605      vim9script
1606      def g: list<string>
1607  END
1608  CheckScriptFailure(lines, 'E129:')
1609
1610  lines =<< trim END
1611      vim9script
1612      def <SID>: list<string>
1613  END
1614  CheckScriptFailure(lines, 'E884:')
1615
1616  lines =<< trim END
1617      vim9script
1618      def F list<string>
1619  END
1620  CheckScriptFailure(lines, 'E488:')
1621enddef
1622
1623def Test_partial_call()
1624  var Xsetlist = function('setloclist', [0])
1625  Xsetlist([], ' ', {'title': 'test'})
1626  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1627
1628  Xsetlist = function('setloclist', [0, [], ' '])
1629  Xsetlist({'title': 'test'})
1630  getloclist(0, {'title': 1})->assert_equal({'title': 'test'})
1631
1632  Xsetlist = function('setqflist')
1633  Xsetlist([], ' ', {'title': 'test'})
1634  getqflist({'title': 1})->assert_equal({'title': 'test'})
1635
1636  Xsetlist = function('setqflist', [[], ' '])
1637  Xsetlist({'title': 'test'})
1638  getqflist({'title': 1})->assert_equal({'title': 'test'})
1639
1640  var Len: func: number = function('len', ['word'])
1641  assert_equal(4, Len())
1642enddef
1643
1644def Test_cmd_modifier()
1645  tab echo '0'
1646  CheckDefFailure(['5tab echo 3'], 'E16:')
1647enddef
1648
1649def Test_restore_modifiers()
1650  # check that when compiling a :def function command modifiers are not messed
1651  # up.
1652  var lines =<< trim END
1653      vim9script
1654      set eventignore=
1655      autocmd QuickFixCmdPost * copen
1656      def AutocmdsDisabled()
1657        eval 0
1658      enddef
1659      func Func()
1660        noautocmd call s:AutocmdsDisabled()
1661        let g:ei_after = &eventignore
1662      endfunc
1663      Func()
1664  END
1665  CheckScriptSuccess(lines)
1666  g:ei_after->assert_equal('')
1667enddef
1668
1669def StackTop()
1670  eval 1
1671  eval 2
1672  # call not on fourth line
1673  StackBot()
1674enddef
1675
1676def StackBot()
1677  # throw an error
1678  eval [][0]
1679enddef
1680
1681def Test_callstack_def()
1682  try
1683    StackTop()
1684  catch
1685    v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
1686  endtry
1687enddef
1688
1689" Re-using spot for variable used in block
1690def Test_block_scoped_var()
1691  var lines =<< trim END
1692      vim9script
1693      def Func()
1694        var x = ['a', 'b', 'c']
1695        if 1
1696          var y = 'x'
1697          map(x, {-> y})
1698        endif
1699        var z = x
1700        assert_equal(['x', 'x', 'x'], z)
1701      enddef
1702      Func()
1703  END
1704  CheckScriptSuccess(lines)
1705enddef
1706
1707def Test_reset_did_emsg()
1708  var lines =<< trim END
1709      @s = 'blah'
1710      au BufWinLeave * #
1711      def Func()
1712        var winid = popup_create('popup', {})
1713        exe '*s'
1714        popup_close(winid)
1715      enddef
1716      Func()
1717  END
1718  CheckScriptFailure(lines, 'E492:', 8)
1719enddef
1720
1721
1722" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1723