blob: 4a74bc0be810191bd454d5cdbe589a7a81e0a942 [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 Moolenaar73e28dc2022-09-17 21:08:33 +0100132 call assert_equal(1.0, Log(10))
133 call assert_equal(log(10), Log(10, exp(1)))
134 call assert_fails("call Log(1,2,3)", 'E118:')
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200135
136 let res = Args(1)
137 call assert_equal(res.mandatory, 1)
138 call assert_equal(res.optional, v:null)
139 call assert_equal(res['0'], 0)
140
141 let res = Args(1,2)
142 call assert_equal(res.mandatory, 1)
143 call assert_equal(res.optional, 2)
144 call assert_equal(res['0'], 0)
145
146 let res = Args(1,2,3)
147 call assert_equal(res.mandatory, 1)
148 call assert_equal(res.optional, 2)
149 call assert_equal(res['0'], 1)
150
Bram Moolenaare2e40752020-09-04 21:18:46 +0200151 call assert_fails("call MakeBadFunc()", 'E989:')
Bram Moolenaare9b8b782021-04-06 20:18:29 +0200152 call assert_fails("fu F(a=1 ,) | endf", 'E1068:')
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200153
154 let d = Args2(7, v:none, 9)
155 call assert_equal([7, 2, 9], [d.a, d.b, d.c])
156
157 call assert_equal("\n"
158 \ .. " function Args2(a = 1, b = 2, c = 3)\n"
159 \ .. "1 return deepcopy(a:)\n"
160 \ .. " endfunction",
161 \ execute('func Args2'))
Yegappan Lakshmanan34fcb692021-05-25 20:14:00 +0200162
163 " Error in default argument expression
164 let l =<< trim END
165 func F1(x = y)
166 return a:x * 2
167 endfunc
168 echo F1()
169 END
170 let @a = l->join("\n")
171 call assert_fails("exe @a", 'E121:')
Bram Moolenaar42ae78c2019-05-09 21:08:58 +0200172endfunc
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +0200173
174func s:addFoo(lead)
175 return a:lead .. 'foo'
176endfunc
177
178func Test_user_method()
179 eval 'bar'->s:addFoo()->assert_equal('barfoo')
180endfunc
Bram Moolenaare51bb172020-02-16 19:42:23 +0100181
182func Test_failed_call_in_try()
183 try | call UnknownFunc() | catch | endtry
184endfunc
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200185
186" Test for listing user-defined functions
187func Test_function_list()
188 call assert_fails("function Xabc", 'E123:')
189endfunc
190
Bram Moolenaar476a6132020-04-08 19:48:56 +0200191" Test for <sfile>, <slnum> in a function
192func Test_sfile_in_function()
193 func Xfunc()
194 call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('<sfile>'))
195 call assert_equal('2', expand('<slnum>'))
196 endfunc
197 call Xfunc()
198 delfunc Xfunc
199endfunc
200
201" Test trailing text after :endfunction {{{1
202func Test_endfunction_trailing()
203 call assert_false(exists('*Xtest'))
204
205 exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
206 call assert_true(exists('*Xtest'))
207 call assert_equal('yes', done)
208 delfunc Xtest
209 unlet done
210
211 exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
212 call assert_true(exists('*Xtest'))
213 call assert_equal('yes', done)
214 delfunc Xtest
215 unlet done
216
217 " trailing line break
218 exe "func Xtest()\necho 'hello'\nendfunc\n"
219 call assert_true(exists('*Xtest'))
220 delfunc Xtest
221
222 set verbose=1
223 exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
224 call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
225 call assert_true(exists('*Xtest'))
226 delfunc Xtest
227
228 exe "func Xtest()\necho 'hello'\nendfunc garbage"
229 call assert_match('W22:', split(execute('1messages'), "\n")[0])
230 call assert_true(exists('*Xtest'))
231 delfunc Xtest
232 set verbose=0
233
Bram Moolenaara0d072e2020-07-01 20:19:37 +0200234 func Xtest(a1, a2)
235 echo a:a1 .. a:a2
236 endfunc
237 set verbose=15
238 redir @a
239 call Xtest(123, repeat('x', 100))
240 redir END
241 call assert_match('calling Xtest(123, ''xxxxxxx.*x\.\.\.x.*xxxx'')', getreg('a'))
242 delfunc Xtest
243 set verbose=0
244
Bram Moolenaar476a6132020-04-08 19:48:56 +0200245 function Foo()
246 echo 'hello'
247 endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
248 delfunc Foo
249endfunc
250
251func Test_delfunction_force()
252 delfunc! Xtest
253 delfunc! Xtest
254 func Xtest()
255 echo 'nothing'
256 endfunc
257 delfunc! Xtest
258 delfunc! Xtest
259
260 " Try deleting the current function
261 call assert_fails('delfunc Test_delfunction_force', 'E131:')
262endfunc
263
264func Test_function_defined_line()
265 CheckNotGui
266
267 let lines =<< trim [CODE]
268 " F1
269 func F1()
270 " F2
271 func F2()
272 "
273 "
274 "
275 return
276 endfunc
277 " F3
278 execute "func F3()\n\n\n\nreturn\nendfunc"
279 " F4
280 execute "func F4()\n
281 \\n
282 \\n
283 \\n
284 \return\n
285 \endfunc"
286 endfunc
287 " F5
288 execute "func F5()\n\n\n\nreturn\nendfunc"
289 " F6
290 execute "func F6()\n
291 \\n
292 \\n
293 \\n
294 \return\n
295 \endfunc"
296 call F1()
297 verbose func F1
298 verbose func F2
299 verbose func F3
300 verbose func F4
301 verbose func F5
302 verbose func F6
303 qall!
304 [CODE]
305
306 call writefile(lines, 'Xtest.vim')
307 let res = system(GetVimCommandClean() .. ' -es -X -S Xtest.vim')
308 call assert_equal(0, v:shell_error)
309
310 let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
311 call assert_match(' line 2$', m)
312
313 let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
314 call assert_match(' line 4$', m)
315
316 let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
317 call assert_match(' line 11$', m)
318
319 let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
320 call assert_match(' line 13$', m)
321
322 let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
323 call assert_match(' line 21$', m)
324
325 let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
326 call assert_match(' line 23$', m)
327
328 call delete('Xtest.vim')
329endfunc
330
331" Test for defining a function reference in the global scope
332func Test_add_funcref_to_global_scope()
333 let x = g:
334 let caught_E862 = 0
335 try
336 func x.Xfunc()
337 return 1
338 endfunc
339 catch /E862:/
340 let caught_E862 = 1
341 endtry
342 call assert_equal(1, caught_E862)
343endfunc
344
345func Test_funccall_garbage_collect()
346 func Func(x, ...)
347 call add(a:x, a:000)
348 endfunc
349 call Func([], [])
350 " Must not crash cause by invalid freeing
351 call test_garbagecollect_now()
352 call assert_true(v:true)
353 delfunc Func
354endfunc
355
356" Test for script-local function
357func <SID>DoLast()
358 call append(line('$'), "last line")
359endfunc
360
361func s:DoNothing()
362 call append(line('$'), "nothing line")
363endfunc
364
365func Test_script_local_func()
366 set nocp nomore viminfo+=nviminfo
367 new
368 nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
369
370 normal _x
371 call assert_equal('nothing line', getline(2))
372 call assert_equal('last line', getline(3))
373 close!
374
375 " Try to call a script local function in global scope
376 let lines =<< trim [CODE]
377 :call assert_fails('call s:Xfunc()', 'E81:')
378 :call assert_fails('let x = call("<SID>Xfunc", [])', 'E120:')
379 :call writefile(v:errors, 'Xresult')
380 :qall
381
382 [CODE]
383 call writefile(lines, 'Xscript')
384 if RunVim([], [], '-s Xscript')
385 call assert_equal([], readfile('Xresult'))
386 endif
387 call delete('Xresult')
388 call delete('Xscript')
389endfunc
390
391" Test for errors in defining new functions
392func Test_func_def_error()
393 call assert_fails('func Xfunc abc ()', 'E124:')
394 call assert_fails('func Xfunc(', 'E125:')
395 call assert_fails('func xfunc()', 'E128:')
396
397 " Try to redefine a function that is in use
398 let caught_E127 = 0
399 try
400 func! Test_func_def_error()
401 endfunc
402 catch /E127:/
403 let caught_E127 = 1
404 endtry
405 call assert_equal(1, caught_E127)
406
407 " Try to define a function in a dict twice
408 let d = {}
409 let lines =<< trim END
410 func d.F1()
411 return 1
412 endfunc
413 END
414 let l = join(lines, "\n") . "\n"
415 exe l
416 call assert_fails('exe l', 'E717:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200417 call assert_fails('call feedkeys(":func d.F1()\<CR>", "xt")', 'E717:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200418
419 " Define an autoload function with an incorrect file name
420 call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript')
421 call assert_fails('source Xscript', 'E746:')
422 call delete('Xscript')
Bram Moolenaar531be472020-09-23 22:38:05 +0200423
424 " Try to list functions using an invalid search pattern
425 call assert_fails('function /\%(/', 'E53:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200426endfunc
427
428" Test for deleting a function
429func Test_del_func()
Bram Moolenaarc553a212021-12-26 20:20:34 +0000430 call assert_fails('delfunction Xabc', 'E117:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200431 let d = {'a' : 10}
432 call assert_fails('delfunc d.a', 'E718:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200433 func d.fn()
434 return 1
435 endfunc
Bram Moolenaarddfc0512021-09-06 20:56:56 +0200436
437 " cannot delete the dict function by number
438 let nr = substitute(execute('echo d'), '.*function(''\(\d\+\)'').*', '\1', '')
439 call assert_fails('delfunction g:' .. nr, 'E475: Invalid argument: g:')
440
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200441 delfunc d.fn
442 call assert_equal({'a' : 10}, d)
Bram Moolenaar476a6132020-04-08 19:48:56 +0200443endfunc
444
445" Test for calling return outside of a function
446func Test_return_outside_func()
447 call writefile(['return 10'], 'Xscript')
448 call assert_fails('source Xscript', 'E133:')
449 call delete('Xscript')
450endfunc
451
452" Test for errors in calling a function
453func Test_func_arg_error()
454 " Too many arguments
455 call assert_fails("call call('min', range(1,20))", 'E118:')
456 call assert_fails("call call('min', range(1,21))", 'E699:')
457 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)',
458 \ 'E740:')
459
460 " Missing dict argument
461 func Xfunc() dict
462 return 1
463 endfunc
464 call assert_fails('call Xfunc()', 'E725:')
465 delfunc Xfunc
466endfunc
467
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100468func Test_func_dict()
469 let mydict = {'a': 'b'}
470 function mydict.somefunc() dict
471 return len(self)
472 endfunc
473
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200474 call assert_equal("{'a': 'b', 'somefunc': function('3')}", string(mydict))
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100475 call assert_equal(2, mydict.somefunc())
476 call assert_match("^\n function \\d\\\+() dict"
477 \ .. "\n1 return len(self)"
478 \ .. "\n endfunction$", execute('func mydict.somefunc'))
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200479 call assert_fails('call mydict.nonexist()', 'E716:')
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100480endfunc
481
482func Test_func_range()
483 new
484 call setline(1, range(1, 8))
485 func FuncRange() range
486 echo a:firstline
487 echo a:lastline
488 endfunc
489 3
490 call assert_equal("\n3\n3", execute('call FuncRange()'))
491 call assert_equal("\n4\n6", execute('4,6 call FuncRange()'))
492 call assert_equal("\n function FuncRange() range"
493 \ .. "\n1 echo a:firstline"
494 \ .. "\n2 echo a:lastline"
495 \ .. "\n endfunction",
496 \ execute('function FuncRange'))
497
498 bwipe!
499endfunc
500
Yegappan Lakshmanan7c7e19c2022-04-09 11:09:07 +0100501" Test for memory allocation failure when defining a new function
502func Test_funcdef_alloc_failure()
503 new
504 let lines =<< trim END
505 func Xtestfunc()
506 return 321
507 endfunc
508 END
509 call setline(1, lines)
510 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
511 call assert_fails('source', 'E342:')
512 call assert_false(exists('*Xtestfunc'))
513 call assert_fails('delfunc Xtestfunc', 'E117:')
514 %d _
515 let lines =<< trim END
516 def g:Xvim9func(): number
517 return 456
518 enddef
519 END
520 call setline(1, lines)
521 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
522 call assert_fails('source', 'E342:')
523 call assert_false(exists('*Xvim9func'))
524 "call test_alloc_fail(GetAllocId('get_func'), 0, 0)
525 "call assert_fails('source', 'E342:')
526 "call assert_false(exists('*Xtestfunc'))
527 "call assert_fails('delfunc Xtestfunc', 'E117:')
528 bw!
529endfunc
530
Bram Moolenaar86d87252022-09-05 21:21:25 +0100531func AddDefer(arg1, ...)
532 call extend(g:deferred, [a:arg1])
533 if a:0 == 1
534 call extend(g:deferred, [a:1])
535 endif
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100536endfunc
537
538func WithDeferTwo()
539 call extend(g:deferred, ['in Two'])
540 for nr in range(3)
541 defer AddDefer('Two' .. nr)
542 endfor
543 call extend(g:deferred, ['end Two'])
544endfunc
545
546func WithDeferOne()
547 call extend(g:deferred, ['in One'])
548 call writefile(['text'], 'Xfuncdefer')
549 defer delete('Xfuncdefer')
550 defer AddDefer('One')
551 call WithDeferTwo()
552 call extend(g:deferred, ['end One'])
553endfunc
554
Bram Moolenaar86d87252022-09-05 21:21:25 +0100555func WithPartialDefer()
556 call extend(g:deferred, ['in Partial'])
557 let Part = funcref('AddDefer', ['arg1'])
558 defer Part("arg2")
559 call extend(g:deferred, ['end Partial'])
560endfunc
561
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100562func Test_defer()
563 let g:deferred = []
564 call WithDeferOne()
565
566 call assert_equal(['in One', 'in Two', 'end Two', 'Two2', 'Two1', 'Two0', 'end One', 'One'], g:deferred)
567 unlet g:deferred
568
569 call assert_equal('', glob('Xfuncdefer'))
Bram Moolenaar86d87252022-09-05 21:21:25 +0100570
571 call assert_fails('defer delete("Xfuncdefer")->Another()', 'E488:')
572 call assert_fails('defer delete("Xfuncdefer").member', 'E488:')
573
574 let g:deferred = []
575 call WithPartialDefer()
576 call assert_equal(['in Partial', 'end Partial', 'arg1', 'arg2'], g:deferred)
577 unlet g:deferred
578
579 let Part = funcref('AddDefer', ['arg1'], {})
580 call assert_fails('defer Part("arg2")', 'E1300:')
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100581endfunc
582
Bram Moolenaar58779852022-09-06 18:31:14 +0100583func DeferLevelTwo()
584 call writefile(['text'], 'XDeleteTwo', 'D')
585 throw 'someerror'
586endfunc
587
588def DeferLevelOne()
589 call writefile(['text'], 'XDeleteOne', 'D')
590 call g:DeferLevelTwo()
591enddef
592
593func Test_defer_throw()
594 let caught = 'no'
595 try
596 call DeferLevelOne()
597 catch /someerror/
598 let caught = 'yes'
599 endtry
600 call assert_equal('yes', caught)
601 call assert_false(filereadable('XDeleteOne'))
602 call assert_false(filereadable('XDeleteTwo'))
603endfunc
604
605func Test_defer_quitall()
606 let lines =<< trim END
607 vim9script
608 func DeferLevelTwo()
609 call writefile(['text'], 'XQuitallTwo', 'D')
610 qa!
611 endfunc
612
613 def DeferLevelOne()
614 call writefile(['text'], 'XQuitallOne', 'D')
615 call DeferLevelTwo()
616 enddef
617
618 DeferLevelOne()
619 END
620 call writefile(lines, 'XdeferQuitall', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100621 let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
Bram Moolenaar58779852022-09-06 18:31:14 +0100622 call assert_equal(0, v:shell_error)
623 call assert_false(filereadable('XQuitallOne'))
624 call assert_false(filereadable('XQuitallTwo'))
625endfunc
626
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100627func Test_defer_quitall_in_expr_func()
628 let lines =<< trim END
629 def DefIndex(idx: number, val: string): bool
630 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
631 if val == 'b'
632 qa!
633 endif
634 return val == 'c'
635 enddef
636
637 def Test_defer_in_funcref()
638 assert_equal(2, indexof(['a', 'b', 'c'], funcref('g:DefIndex')))
639 enddef
640 call Test_defer_in_funcref()
641 END
642 call writefile(lines, 'XdeferQuitallExpr', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100643 let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100644 call assert_equal(0, v:shell_error)
645 call assert_false(filereadable('Xentry0'))
646 call assert_false(filereadable('Xentry1'))
647 call assert_false(filereadable('Xentry2'))
648endfunc
649
Bram Moolenaar98aff652022-09-06 21:02:35 +0100650func FuncIndex(idx, val)
651 call writefile([a:idx .. ': ' .. a:val], 'Xentry' .. a:idx, 'D')
652 return a:val == 'c'
653endfunc
654
655def DefIndex(idx: number, val: string): bool
656 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
657 return val == 'c'
658enddef
659
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100660def DefIndexXtra(xtra: string, idx: number, val: string): bool
661 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
662 return val == 'c'
663enddef
664
Bram Moolenaar98aff652022-09-06 21:02:35 +0100665def Test_defer_in_funcref()
666 assert_equal(2, indexof(['a', 'b', 'c'], function('g:FuncIndex')))
667 assert_false(filereadable('Xentry0'))
668 assert_false(filereadable('Xentry1'))
669 assert_false(filereadable('Xentry2'))
670
671 assert_equal(2, indexof(['a', 'b', 'c'], g:DefIndex))
672 assert_false(filereadable('Xentry0'))
673 assert_false(filereadable('Xentry1'))
674 assert_false(filereadable('Xentry2'))
675
676 assert_equal(2, indexof(['a', 'b', 'c'], function('g:DefIndex')))
677 assert_false(filereadable('Xentry0'))
678 assert_false(filereadable('Xentry1'))
679 assert_false(filereadable('Xentry2'))
680
681 assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndex)))
682 assert_false(filereadable('Xentry0'))
683 assert_false(filereadable('Xentry1'))
684 assert_false(filereadable('Xentry2'))
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100685
686 assert_equal(2, indexof(['a', 'b', 'c'], function(g:DefIndexXtra, ['xtra'])))
687 assert_false(filereadable('Xentry0'))
688 assert_false(filereadable('Xentry1'))
689 assert_false(filereadable('Xentry2'))
690
691 assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndexXtra, ['xtra'])))
692 assert_false(filereadable('Xentry0'))
693 assert_false(filereadable('Xentry1'))
694 assert_false(filereadable('Xentry2'))
Bram Moolenaar98aff652022-09-06 21:02:35 +0100695enddef
696
Bram Moolenaar16900322022-09-08 19:51:45 +0100697func Test_defer_wrong_arguments()
698 call assert_fails('defer delete()', 'E119:')
699 call assert_fails('defer FuncIndex(1)', 'E119:')
700 call assert_fails('defer delete(1, 2, 3)', 'E118:')
701 call assert_fails('defer FuncIndex(1, 2, 3)', 'E118:')
702
703 let lines =<< trim END
704 def DeferFunc0()
705 defer delete()
706 enddef
707 defcompile
708 END
709 call v9.CheckScriptFailure(lines, 'E119:')
710 let lines =<< trim END
711 def DeferFunc3()
712 defer delete(1, 2, 3)
713 enddef
714 defcompile
715 END
716 call v9.CheckScriptFailure(lines, 'E118:')
717 let lines =<< trim END
718 def DeferFunc2()
719 defer delete(1, 2)
720 enddef
721 defcompile
722 END
723 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
724
725 def g:FuncOneArg(arg: string)
726 echo arg
727 enddef
728
729 let lines =<< trim END
730 def DeferUserFunc0()
731 defer g:FuncOneArg()
732 enddef
733 defcompile
734 END
735 call v9.CheckScriptFailure(lines, 'E119:')
736 let lines =<< trim END
737 def DeferUserFunc2()
738 defer g:FuncOneArg(1, 2)
739 enddef
740 defcompile
741 END
742 call v9.CheckScriptFailure(lines, 'E118:')
743 let lines =<< trim END
744 def DeferUserFunc1()
745 defer g:FuncOneArg(1)
746 enddef
747 defcompile
748 END
749 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
750endfunc
751
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100752
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200753" vim: shiftwidth=2 sts=2 expandtab