blob: 4721175e770f1e279eb5d46384d6807028c755f7 [file] [log] [blame]
Bram Moolenaar53f0c962017-10-22 14:23:59 +02001" 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
Bram Moolenaar476a6132020-04-08 19:48:56 +02006source check.vim
7source shared.vim
Bram Moolenaar16900322022-09-08 19:51:45 +01008import './vim9.vim' as v9
Bram Moolenaar476a6132020-04-08 19:48:56 +02009
Bram Moolenaar53f0c962017-10-22 14:23:59 +020010func Table(title, ...)
11 let ret = a:title
12 let idx = 1
13 while idx <= a:0
14 exe "let ret = ret . a:" . idx
15 let idx = idx + 1
16 endwhile
17 return ret
18endfunc
19
20func Compute(n1, n2, divname)
21 if a:n2 == 0
22 return "fail"
23 endif
24 exe "let g:" . a:divname . " = ". a:n1 / a:n2
25 return "ok"
26endfunc
27
28func Expr1()
29 silent! normal! v
30 return "111"
31endfunc
32
33func Expr2()
34 call search('XX', 'b')
35 return "222"
36endfunc
37
38func ListItem()
39 let g:counter += 1
40 return g:counter . '. '
41endfunc
42
43func ListReset()
44 let g:counter = 0
45 return ''
46endfunc
47
48func FuncWithRef(a)
49 unlet g:FuncRef
50 return a:a
51endfunc
52
53func Test_user_func()
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +020054 let g:FuncRef = function("FuncWithRef")
Bram Moolenaar53f0c962017-10-22 14:23:59 +020055 let g:counter = 0
56 inoremap <expr> ( ListItem()
57 inoremap <expr> [ ListReset()
58 imap <expr> + Expr1()
59 imap <expr> * Expr2()
60 let g:retval = "nop"
61
62 call assert_equal('xxx4asdf', Table("xxx", 4, "asdf"))
63 call assert_equal('fail', Compute(45, 0, "retval"))
64 call assert_equal('nop', g:retval)
65 call assert_equal('ok', Compute(45, 5, "retval"))
66 call assert_equal(9, g:retval)
67 call assert_equal(333, g:FuncRef(333))
68
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +020069 let g:retval = "nop"
70 call assert_equal('xxx4asdf', "xxx"->Table(4, "asdf"))
71 call assert_equal('fail', 45->Compute(0, "retval"))
72 call assert_equal('nop', g:retval)
73 call assert_equal('ok', 45->Compute(5, "retval"))
74 call assert_equal(9, g:retval)
75 " call assert_equal(333, 333->g:FuncRef())
76
Bram Moolenaar53f0c962017-10-22 14:23:59 +020077 enew
78
79 normal oXX+-XX
80 call assert_equal('XX111-XX', getline('.'))
81 normal o---*---
82 call assert_equal('---222---', getline('.'))
83 normal o(one
84 call assert_equal('1. one', getline('.'))
85 normal o(two
86 call assert_equal('2. two', getline('.'))
87 normal o[(one again
88 call assert_equal('1. one again', getline('.'))
89
Bram Moolenaar476a6132020-04-08 19:48:56 +020090 " Try to overwrite a function in the global (g:) scope
Bram Moolenaar53f0c962017-10-22 14:23:59 +020091 call assert_equal(3, max([1, 2, 3]))
Bram Moolenaare2e40752020-09-04 21:18:46 +020092 call assert_fails("call extend(g:, {'max': function('min')})", 'E704:')
Bram Moolenaar53f0c962017-10-22 14:23:59 +020093 call assert_equal(3, max([1, 2, 3]))
94
Bram Moolenaar8dfcce32020-03-18 19:32:26 +010095 " Try to overwrite an user defined function with a function reference
96 call assert_fails("let Expr1 = function('min')", 'E705:')
97
Bram Moolenaar53f0c962017-10-22 14:23:59 +020098 " Regression: the first line below used to throw ?E110: Missing ')'?
99 " Second is here just to prove that this line is correct when not skipping
100 " rhs of &&.
101 call assert_equal(0, (0 && (function('tr'))(1, 2, 3)))
102 call assert_equal(1, (1 && (function('tr'))(1, 2, 3)))
103
104 delfunc Table
105 delfunc Compute
106 delfunc Expr1
107 delfunc Expr2
108 delfunc ListItem
109 delfunc ListReset
110 unlet g:retval g:counter
111 enew!
112endfunc
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200113
114func Log(val, base = 10)
115 return log(a:val) / log(a:base)
116endfunc
117
118func Args(mandatory, optional = v:null, ...)
119 return deepcopy(a:)
120endfunc
121
122func Args2(a = 1, b = 2, c = 3)
123 return deepcopy(a:)
124endfunc
125
126func MakeBadFunc()
127 func s:fcn(a, b=1, c)
128 endfunc
129endfunc
130
131func Test_default_arg()
Bram Moolenaar5feabe02020-01-30 18:24:53 +0100132 if has('float')
133 call assert_equal(1.0, Log(10))
134 call assert_equal(log(10), Log(10, exp(1)))
Bram Moolenaare2e40752020-09-04 21:18:46 +0200135 call assert_fails("call Log(1,2,3)", 'E118:')
Bram Moolenaar5feabe02020-01-30 18:24:53 +0100136 endif
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200137
138 let res = Args(1)
139 call assert_equal(res.mandatory, 1)
140 call assert_equal(res.optional, v:null)
141 call assert_equal(res['0'], 0)
142
143 let res = Args(1,2)
144 call assert_equal(res.mandatory, 1)
145 call assert_equal(res.optional, 2)
146 call assert_equal(res['0'], 0)
147
148 let res = Args(1,2,3)
149 call assert_equal(res.mandatory, 1)
150 call assert_equal(res.optional, 2)
151 call assert_equal(res['0'], 1)
152
Bram Moolenaare2e40752020-09-04 21:18:46 +0200153 call assert_fails("call MakeBadFunc()", 'E989:')
Bram Moolenaare9b8b782021-04-06 20:18:29 +0200154 call assert_fails("fu F(a=1 ,) | endf", 'E1068:')
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200155
156 let d = Args2(7, v:none, 9)
157 call assert_equal([7, 2, 9], [d.a, d.b, d.c])
158
159 call assert_equal("\n"
160 \ .. " function Args2(a = 1, b = 2, c = 3)\n"
161 \ .. "1 return deepcopy(a:)\n"
162 \ .. " endfunction",
163 \ execute('func Args2'))
Yegappan Lakshmanan34fcb692021-05-25 20:14:00 +0200164
165 " Error in default argument expression
166 let l =<< trim END
167 func F1(x = y)
168 return a:x * 2
169 endfunc
170 echo F1()
171 END
172 let @a = l->join("\n")
173 call assert_fails("exe @a", 'E121:')
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200174endfunc
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +0200175
176func s:addFoo(lead)
177 return a:lead .. 'foo'
178endfunc
179
180func Test_user_method()
181 eval 'bar'->s:addFoo()->assert_equal('barfoo')
182endfunc
Bram Moolenaare51bb172020-02-16 19:42:23 +0100183
184func Test_failed_call_in_try()
185 try | call UnknownFunc() | catch | endtry
186endfunc
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200187
188" Test for listing user-defined functions
189func Test_function_list()
190 call assert_fails("function Xabc", 'E123:')
191endfunc
192
Bram Moolenaar476a6132020-04-08 19:48:56 +0200193" Test for <sfile>, <slnum> in a function
194func Test_sfile_in_function()
195 func Xfunc()
196 call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('<sfile>'))
197 call assert_equal('2', expand('<slnum>'))
198 endfunc
199 call Xfunc()
200 delfunc Xfunc
201endfunc
202
203" Test trailing text after :endfunction {{{1
204func Test_endfunction_trailing()
205 call assert_false(exists('*Xtest'))
206
207 exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
208 call assert_true(exists('*Xtest'))
209 call assert_equal('yes', done)
210 delfunc Xtest
211 unlet done
212
213 exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
214 call assert_true(exists('*Xtest'))
215 call assert_equal('yes', done)
216 delfunc Xtest
217 unlet done
218
219 " trailing line break
220 exe "func Xtest()\necho 'hello'\nendfunc\n"
221 call assert_true(exists('*Xtest'))
222 delfunc Xtest
223
224 set verbose=1
225 exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
226 call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
227 call assert_true(exists('*Xtest'))
228 delfunc Xtest
229
230 exe "func Xtest()\necho 'hello'\nendfunc garbage"
231 call assert_match('W22:', split(execute('1messages'), "\n")[0])
232 call assert_true(exists('*Xtest'))
233 delfunc Xtest
234 set verbose=0
235
Bram Moolenaara0d072e2020-07-01 20:19:37 +0200236 func Xtest(a1, a2)
237 echo a:a1 .. a:a2
238 endfunc
239 set verbose=15
240 redir @a
241 call Xtest(123, repeat('x', 100))
242 redir END
243 call assert_match('calling Xtest(123, ''xxxxxxx.*x\.\.\.x.*xxxx'')', getreg('a'))
244 delfunc Xtest
245 set verbose=0
246
Bram Moolenaar476a6132020-04-08 19:48:56 +0200247 function Foo()
248 echo 'hello'
249 endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
250 delfunc Foo
251endfunc
252
253func Test_delfunction_force()
254 delfunc! Xtest
255 delfunc! Xtest
256 func Xtest()
257 echo 'nothing'
258 endfunc
259 delfunc! Xtest
260 delfunc! Xtest
261
262 " Try deleting the current function
263 call assert_fails('delfunc Test_delfunction_force', 'E131:')
264endfunc
265
266func Test_function_defined_line()
267 CheckNotGui
268
269 let lines =<< trim [CODE]
270 " F1
271 func F1()
272 " F2
273 func F2()
274 "
275 "
276 "
277 return
278 endfunc
279 " F3
280 execute "func F3()\n\n\n\nreturn\nendfunc"
281 " F4
282 execute "func F4()\n
283 \\n
284 \\n
285 \\n
286 \return\n
287 \endfunc"
288 endfunc
289 " F5
290 execute "func F5()\n\n\n\nreturn\nendfunc"
291 " F6
292 execute "func F6()\n
293 \\n
294 \\n
295 \\n
296 \return\n
297 \endfunc"
298 call F1()
299 verbose func F1
300 verbose func F2
301 verbose func F3
302 verbose func F4
303 verbose func F5
304 verbose func F6
305 qall!
306 [CODE]
307
308 call writefile(lines, 'Xtest.vim')
309 let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
310 call assert_equal(0, v:shell_error)
311
312 let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
313 call assert_match(' line 2$', m)
314
315 let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
316 call assert_match(' line 4$', m)
317
318 let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
319 call assert_match(' line 11$', m)
320
321 let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
322 call assert_match(' line 13$', m)
323
324 let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
325 call assert_match(' line 21$', m)
326
327 let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
328 call assert_match(' line 23$', m)
329
330 call delete('Xtest.vim')
331endfunc
332
333" Test for defining a function reference in the global scope
334func Test_add_funcref_to_global_scope()
335 let x = g:
336 let caught_E862 = 0
337 try
338 func x.Xfunc()
339 return 1
340 endfunc
341 catch /E862:/
342 let caught_E862 = 1
343 endtry
344 call assert_equal(1, caught_E862)
345endfunc
346
347func Test_funccall_garbage_collect()
348 func Func(x, ...)
349 call add(a:x, a:000)
350 endfunc
351 call Func([], [])
352 " Must not crash cause by invalid freeing
353 call test_garbagecollect_now()
354 call assert_true(v:true)
355 delfunc Func
356endfunc
357
358" Test for script-local function
359func <SID>DoLast()
360 call append(line('$'), "last line")
361endfunc
362
363func s:DoNothing()
364 call append(line('$'), "nothing line")
365endfunc
366
367func Test_script_local_func()
368 set nocp nomore viminfo+=nviminfo
369 new
370 nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
371
372 normal _x
373 call assert_equal('nothing line', getline(2))
374 call assert_equal('last line', getline(3))
375 close!
376
377 " Try to call a script local function in global scope
378 let lines =<< trim [CODE]
379 :call assert_fails('call s:Xfunc()', 'E81:')
380 :call assert_fails('let x = call("<SID>Xfunc", [])', 'E120:')
381 :call writefile(v:errors, 'Xresult')
382 :qall
383
384 [CODE]
385 call writefile(lines, 'Xscript')
386 if RunVim([], [], '-s Xscript')
387 call assert_equal([], readfile('Xresult'))
388 endif
389 call delete('Xresult')
390 call delete('Xscript')
391endfunc
392
393" Test for errors in defining new functions
394func Test_func_def_error()
395 call assert_fails('func Xfunc abc ()', 'E124:')
396 call assert_fails('func Xfunc(', 'E125:')
397 call assert_fails('func xfunc()', 'E128:')
398
399 " Try to redefine a function that is in use
400 let caught_E127 = 0
401 try
402 func! Test_func_def_error()
403 endfunc
404 catch /E127:/
405 let caught_E127 = 1
406 endtry
407 call assert_equal(1, caught_E127)
408
409 " Try to define a function in a dict twice
410 let d = {}
411 let lines =<< trim END
412 func d.F1()
413 return 1
414 endfunc
415 END
416 let l = join(lines, "\n") . "\n"
417 exe l
418 call assert_fails('exe l', 'E717:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200419 call assert_fails('call feedkeys(":func d.F1()\<CR>", "xt")', 'E717:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200420
421 " Define an autoload function with an incorrect file name
422 call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript')
423 call assert_fails('source Xscript', 'E746:')
424 call delete('Xscript')
Bram Moolenaar531be472020-09-23 22:38:05 +0200425
426 " Try to list functions using an invalid search pattern
427 call assert_fails('function /\%(/', 'E53:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200428endfunc
429
430" Test for deleting a function
431func Test_del_func()
Bram Moolenaarc553a212021-12-26 20:20:34 +0000432 call assert_fails('delfunction Xabc', 'E117:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200433 let d = {'a' : 10}
434 call assert_fails('delfunc d.a', 'E718:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200435 func d.fn()
436 return 1
437 endfunc
Bram Moolenaarddfc0512021-09-06 20:56:56 +0200438
439 " cannot delete the dict function by number
440 let nr = substitute(execute('echo d'), '.*function(''\(\d\+\)'').*', '\1', '')
441 call assert_fails('delfunction g:' .. nr, 'E475: Invalid argument: g:')
442
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200443 delfunc d.fn
444 call assert_equal({'a' : 10}, d)
Bram Moolenaar476a6132020-04-08 19:48:56 +0200445endfunc
446
447" Test for calling return outside of a function
448func Test_return_outside_func()
449 call writefile(['return 10'], 'Xscript')
450 call assert_fails('source Xscript', 'E133:')
451 call delete('Xscript')
452endfunc
453
454" Test for errors in calling a function
455func Test_func_arg_error()
456 " Too many arguments
457 call assert_fails("call call('min', range(1,20))", 'E118:')
458 call assert_fails("call call('min', range(1,21))", 'E699:')
459 call assert_fails('echo min(0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,0,1)',
460 \ 'E740:')
461
462 " Missing dict argument
463 func Xfunc() dict
464 return 1
465 endfunc
466 call assert_fails('call Xfunc()', 'E725:')
467 delfunc Xfunc
468endfunc
469
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100470func Test_func_dict()
471 let mydict = {'a': 'b'}
472 function mydict.somefunc() dict
473 return len(self)
474 endfunc
475
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200476 call assert_equal("{'a': 'b', 'somefunc': function('3')}", string(mydict))
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100477 call assert_equal(2, mydict.somefunc())
478 call assert_match("^\n function \\d\\\+() dict"
479 \ .. "\n1 return len(self)"
480 \ .. "\n endfunction$", execute('func mydict.somefunc'))
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200481 call assert_fails('call mydict.nonexist()', 'E716:')
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100482endfunc
483
484func Test_func_range()
485 new
486 call setline(1, range(1, 8))
487 func FuncRange() range
488 echo a:firstline
489 echo a:lastline
490 endfunc
491 3
492 call assert_equal("\n3\n3", execute('call FuncRange()'))
493 call assert_equal("\n4\n6", execute('4,6 call FuncRange()'))
494 call assert_equal("\n function FuncRange() range"
495 \ .. "\n1 echo a:firstline"
496 \ .. "\n2 echo a:lastline"
497 \ .. "\n endfunction",
498 \ execute('function FuncRange'))
499
500 bwipe!
501endfunc
502
Yegappan Lakshmanan7c7e19c2022-04-09 11:09:07 +0100503" Test for memory allocation failure when defining a new function
504func Test_funcdef_alloc_failure()
505 new
506 let lines =<< trim END
507 func Xtestfunc()
508 return 321
509 endfunc
510 END
511 call setline(1, lines)
512 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
513 call assert_fails('source', 'E342:')
514 call assert_false(exists('*Xtestfunc'))
515 call assert_fails('delfunc Xtestfunc', 'E117:')
516 %d _
517 let lines =<< trim END
518 def g:Xvim9func(): number
519 return 456
520 enddef
521 END
522 call setline(1, lines)
523 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
524 call assert_fails('source', 'E342:')
525 call assert_false(exists('*Xvim9func'))
526 "call test_alloc_fail(GetAllocId('get_func'), 0, 0)
527 "call assert_fails('source', 'E342:')
528 "call assert_false(exists('*Xtestfunc'))
529 "call assert_fails('delfunc Xtestfunc', 'E117:')
530 bw!
531endfunc
532
Bram Moolenaar86d87252022-09-05 21:21:25 +0100533func AddDefer(arg1, ...)
534 call extend(g:deferred, [a:arg1])
535 if a:0 == 1
536 call extend(g:deferred, [a:1])
537 endif
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100538endfunc
539
540func WithDeferTwo()
541 call extend(g:deferred, ['in Two'])
542 for nr in range(3)
543 defer AddDefer('Two' .. nr)
544 endfor
545 call extend(g:deferred, ['end Two'])
546endfunc
547
548func WithDeferOne()
549 call extend(g:deferred, ['in One'])
550 call writefile(['text'], 'Xfuncdefer')
551 defer delete('Xfuncdefer')
552 defer AddDefer('One')
553 call WithDeferTwo()
554 call extend(g:deferred, ['end One'])
555endfunc
556
Bram Moolenaar86d87252022-09-05 21:21:25 +0100557func WithPartialDefer()
558 call extend(g:deferred, ['in Partial'])
559 let Part = funcref('AddDefer', ['arg1'])
560 defer Part("arg2")
561 call extend(g:deferred, ['end Partial'])
562endfunc
563
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100564func Test_defer()
565 let g:deferred = []
566 call WithDeferOne()
567
568 call assert_equal(['in One', 'in Two', 'end Two', 'Two2', 'Two1', 'Two0', 'end One', 'One'], g:deferred)
569 unlet g:deferred
570
571 call assert_equal('', glob('Xfuncdefer'))
Bram Moolenaar86d87252022-09-05 21:21:25 +0100572
573 call assert_fails('defer delete("Xfuncdefer")->Another()', 'E488:')
574 call assert_fails('defer delete("Xfuncdefer").member', 'E488:')
575
576 let g:deferred = []
577 call WithPartialDefer()
578 call assert_equal(['in Partial', 'end Partial', 'arg1', 'arg2'], g:deferred)
579 unlet g:deferred
580
581 let Part = funcref('AddDefer', ['arg1'], {})
582 call assert_fails('defer Part("arg2")', 'E1300:')
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100583endfunc
584
Bram Moolenaar58779852022-09-06 18:31:14 +0100585func DeferLevelTwo()
586 call writefile(['text'], 'XDeleteTwo', 'D')
587 throw 'someerror'
588endfunc
589
590def DeferLevelOne()
591 call writefile(['text'], 'XDeleteOne', 'D')
592 call g:DeferLevelTwo()
593enddef
594
595func Test_defer_throw()
596 let caught = 'no'
597 try
598 call DeferLevelOne()
599 catch /someerror/
600 let caught = 'yes'
601 endtry
602 call assert_equal('yes', caught)
603 call assert_false(filereadable('XDeleteOne'))
604 call assert_false(filereadable('XDeleteTwo'))
605endfunc
606
607func Test_defer_quitall()
608 let lines =<< trim END
609 vim9script
610 func DeferLevelTwo()
611 call writefile(['text'], 'XQuitallTwo', 'D')
612 qa!
613 endfunc
614
615 def DeferLevelOne()
616 call writefile(['text'], 'XQuitallOne', 'D')
617 call DeferLevelTwo()
618 enddef
619
620 DeferLevelOne()
621 END
622 call writefile(lines, 'XdeferQuitall', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100623 let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
Bram Moolenaar58779852022-09-06 18:31:14 +0100624 call assert_equal(0, v:shell_error)
625 call assert_false(filereadable('XQuitallOne'))
626 call assert_false(filereadable('XQuitallTwo'))
627endfunc
628
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100629func Test_defer_quitall_in_expr_func()
630 let lines =<< trim END
631 def DefIndex(idx: number, val: string): bool
632 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
633 if val == 'b'
634 qa!
635 endif
636 return val == 'c'
637 enddef
638
639 def Test_defer_in_funcref()
640 assert_equal(2, indexof(['a', 'b', 'c'], funcref('g:DefIndex')))
641 enddef
642 call Test_defer_in_funcref()
643 END
644 call writefile(lines, 'XdeferQuitallExpr', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100645 let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100646 call assert_equal(0, v:shell_error)
647 call assert_false(filereadable('Xentry0'))
648 call assert_false(filereadable('Xentry1'))
649 call assert_false(filereadable('Xentry2'))
650endfunc
651
Bram Moolenaar98aff652022-09-06 21:02:35 +0100652func FuncIndex(idx, val)
653 call writefile([a:idx .. ': ' .. a:val], 'Xentry' .. a:idx, 'D')
654 return a:val == 'c'
655endfunc
656
657def DefIndex(idx: number, val: string): bool
658 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
659 return val == 'c'
660enddef
661
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100662def DefIndexXtra(xtra: string, idx: number, val: string): bool
663 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
664 return val == 'c'
665enddef
666
Bram Moolenaar98aff652022-09-06 21:02:35 +0100667def Test_defer_in_funcref()
668 assert_equal(2, indexof(['a', 'b', 'c'], function('g:FuncIndex')))
669 assert_false(filereadable('Xentry0'))
670 assert_false(filereadable('Xentry1'))
671 assert_false(filereadable('Xentry2'))
672
673 assert_equal(2, indexof(['a', 'b', 'c'], g:DefIndex))
674 assert_false(filereadable('Xentry0'))
675 assert_false(filereadable('Xentry1'))
676 assert_false(filereadable('Xentry2'))
677
678 assert_equal(2, indexof(['a', 'b', 'c'], function('g:DefIndex')))
679 assert_false(filereadable('Xentry0'))
680 assert_false(filereadable('Xentry1'))
681 assert_false(filereadable('Xentry2'))
682
683 assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndex)))
684 assert_false(filereadable('Xentry0'))
685 assert_false(filereadable('Xentry1'))
686 assert_false(filereadable('Xentry2'))
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100687
688 assert_equal(2, indexof(['a', 'b', 'c'], function(g:DefIndexXtra, ['xtra'])))
689 assert_false(filereadable('Xentry0'))
690 assert_false(filereadable('Xentry1'))
691 assert_false(filereadable('Xentry2'))
692
693 assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndexXtra, ['xtra'])))
694 assert_false(filereadable('Xentry0'))
695 assert_false(filereadable('Xentry1'))
696 assert_false(filereadable('Xentry2'))
Bram Moolenaar98aff652022-09-06 21:02:35 +0100697enddef
698
Bram Moolenaar16900322022-09-08 19:51:45 +0100699func Test_defer_wrong_arguments()
700 call assert_fails('defer delete()', 'E119:')
701 call assert_fails('defer FuncIndex(1)', 'E119:')
702 call assert_fails('defer delete(1, 2, 3)', 'E118:')
703 call assert_fails('defer FuncIndex(1, 2, 3)', 'E118:')
704
705 let lines =<< trim END
706 def DeferFunc0()
707 defer delete()
708 enddef
709 defcompile
710 END
711 call v9.CheckScriptFailure(lines, 'E119:')
712 let lines =<< trim END
713 def DeferFunc3()
714 defer delete(1, 2, 3)
715 enddef
716 defcompile
717 END
718 call v9.CheckScriptFailure(lines, 'E118:')
719 let lines =<< trim END
720 def DeferFunc2()
721 defer delete(1, 2)
722 enddef
723 defcompile
724 END
725 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
726
727 def g:FuncOneArg(arg: string)
728 echo arg
729 enddef
730
731 let lines =<< trim END
732 def DeferUserFunc0()
733 defer g:FuncOneArg()
734 enddef
735 defcompile
736 END
737 call v9.CheckScriptFailure(lines, 'E119:')
738 let lines =<< trim END
739 def DeferUserFunc2()
740 defer g:FuncOneArg(1, 2)
741 enddef
742 defcompile
743 END
744 call v9.CheckScriptFailure(lines, 'E118:')
745 let lines =<< trim END
746 def DeferUserFunc1()
747 defer g:FuncOneArg(1)
748 enddef
749 defcompile
750 END
751 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
752endfunc
753
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100754
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200755" vim: shiftwidth=2 sts=2 expandtab