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