1" Test for user functions.
2" Also test an <expr> mapping calling a function.
3" Also test that a builtin function cannot be replaced.
4" Also test for regression when calling arbitrary expression.
5
6func Table(title, ...)
7  let ret = a:title
8  let idx = 1
9  while idx <= a:0
10    exe "let ret = ret . a:" . idx
11    let idx = idx + 1
12  endwhile
13  return ret
14endfunc
15
16func Compute(n1, n2, divname)
17  if a:n2 == 0
18    return "fail"
19  endif
20  exe "let g:" . a:divname . " = ". a:n1 / a:n2
21  return "ok"
22endfunc
23
24func Expr1()
25  silent! normal! v
26  return "111"
27endfunc
28
29func Expr2()
30  call search('XX', 'b')
31  return "222"
32endfunc
33
34func ListItem()
35  let g:counter += 1
36  return g:counter . '. '
37endfunc
38
39func ListReset()
40  let g:counter = 0
41  return ''
42endfunc
43
44func FuncWithRef(a)
45  unlet g:FuncRef
46  return a:a
47endfunc
48
49func Test_user_func()
50  let g:FuncRef = function("FuncWithRef")
51  let g:counter = 0
52  inoremap <expr> ( ListItem()
53  inoremap <expr> [ ListReset()
54  imap <expr> + Expr1()
55  imap <expr> * Expr2()
56  let g:retval = "nop"
57
58  call assert_equal('xxx4asdf', Table("xxx", 4, "asdf"))
59  call assert_equal('fail', Compute(45, 0, "retval"))
60  call assert_equal('nop', g:retval)
61  call assert_equal('ok', Compute(45, 5, "retval"))
62  call assert_equal(9, g:retval)
63  call assert_equal(333, g:FuncRef(333))
64
65  let g:retval = "nop"
66  call assert_equal('xxx4asdf', "xxx"->Table(4, "asdf"))
67  call assert_equal('fail', 45->Compute(0, "retval"))
68  call assert_equal('nop', g:retval)
69  call assert_equal('ok', 45->Compute(5, "retval"))
70  call assert_equal(9, g:retval)
71  " call assert_equal(333, 333->g:FuncRef())
72
73  enew
74
75  normal oXX+-XX
76  call assert_equal('XX111-XX', getline('.'))
77  normal o---*---
78  call assert_equal('---222---', getline('.'))
79  normal o(one
80  call assert_equal('1. one', getline('.'))
81  normal o(two
82  call assert_equal('2. two', getline('.'))
83  normal o[(one again
84  call assert_equal('1. one again', getline('.'))
85
86  call assert_equal(3, max([1, 2, 3]))
87  call assert_fails("call extend(g:, {'max': function('min')})", 'E704')
88  call assert_equal(3, max([1, 2, 3]))
89
90  " Regression: the first line below used to throw ?E110: Missing ')'?
91  " Second is here just to prove that this line is correct when not skipping
92  " rhs of &&.
93  call assert_equal(0, (0 && (function('tr'))(1, 2, 3)))
94  call assert_equal(1, (1 && (function('tr'))(1, 2, 3)))
95
96  delfunc Table
97  delfunc Compute
98  delfunc Expr1
99  delfunc Expr2
100  delfunc ListItem
101  delfunc ListReset
102  unlet g:retval g:counter
103  enew!
104endfunc
105
106func Log(val, base = 10)
107  return log(a:val) / log(a:base)
108endfunc
109
110func Args(mandatory, optional = v:null, ...)
111  return deepcopy(a:)
112endfunc
113
114func Args2(a = 1, b = 2, c = 3)
115  return deepcopy(a:)
116endfunc
117
118func MakeBadFunc()
119  func s:fcn(a, b=1, c)
120  endfunc
121endfunc
122
123func Test_default_arg()
124  if has('float')
125    call assert_equal(1.0, Log(10))
126    call assert_equal(log(10), Log(10, exp(1)))
127    call assert_fails("call Log(1,2,3)", 'E118')
128  endif
129
130  let res = Args(1)
131  call assert_equal(res.mandatory, 1)
132  call assert_equal(res.optional, v:null)
133  call assert_equal(res['0'], 0)
134
135  let res = Args(1,2)
136  call assert_equal(res.mandatory, 1)
137  call assert_equal(res.optional, 2)
138  call assert_equal(res['0'], 0)
139
140  let res = Args(1,2,3)
141  call assert_equal(res.mandatory, 1)
142  call assert_equal(res.optional, 2)
143  call assert_equal(res['0'], 1)
144
145  call assert_fails("call MakeBadFunc()", 'E989')
146  call assert_fails("fu F(a=1 ,) | endf", 'E475')
147
148  let d = Args2(7, v:none, 9)
149  call assert_equal([7, 2, 9], [d.a, d.b, d.c])
150
151  call assert_equal("\n"
152	\ .. "   function Args2(a = 1, b = 2, c = 3)\n"
153	\ .. "1    return deepcopy(a:)\n"
154	\ .. "   endfunction",
155	\ execute('func Args2'))
156endfunc
157
158func s:addFoo(lead)
159  return a:lead .. 'foo'
160endfunc
161
162func Test_user_method()
163  eval 'bar'->s:addFoo()->assert_equal('barfoo')
164endfunc
165