blob: 79afea1e0e409ffd51af5e4986e913644fb5f3dc [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
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100306 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200307 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)
Bram Moolenaar476a6132020-04-08 19:48:56 +0200327endfunc
328
329" Test for defining a function reference in the global scope
330func Test_add_funcref_to_global_scope()
331 let x = g:
332 let caught_E862 = 0
333 try
334 func x.Xfunc()
335 return 1
336 endfunc
337 catch /E862:/
338 let caught_E862 = 1
339 endtry
340 call assert_equal(1, caught_E862)
341endfunc
342
343func Test_funccall_garbage_collect()
344 func Func(x, ...)
345 call add(a:x, a:000)
346 endfunc
347 call Func([], [])
348 " Must not crash cause by invalid freeing
349 call test_garbagecollect_now()
350 call assert_true(v:true)
351 delfunc Func
352endfunc
353
354" Test for script-local function
355func <SID>DoLast()
356 call append(line('$'), "last line")
357endfunc
358
359func s:DoNothing()
360 call append(line('$'), "nothing line")
361endfunc
362
363func Test_script_local_func()
364 set nocp nomore viminfo+=nviminfo
365 new
366 nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
367
368 normal _x
369 call assert_equal('nothing line', getline(2))
370 call assert_equal('last line', getline(3))
371 close!
372
373 " Try to call a script local function in global scope
374 let lines =<< trim [CODE]
375 :call assert_fails('call s:Xfunc()', 'E81:')
376 :call assert_fails('let x = call("<SID>Xfunc", [])', 'E120:')
377 :call writefile(v:errors, 'Xresult')
378 :qall
379
380 [CODE]
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100381 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200382 if RunVim([], [], '-s Xscript')
383 call assert_equal([], readfile('Xresult'))
384 endif
385 call delete('Xresult')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200386endfunc
387
388" Test for errors in defining new functions
389func Test_func_def_error()
390 call assert_fails('func Xfunc abc ()', 'E124:')
391 call assert_fails('func Xfunc(', 'E125:')
392 call assert_fails('func xfunc()', 'E128:')
393
394 " Try to redefine a function that is in use
395 let caught_E127 = 0
396 try
397 func! Test_func_def_error()
398 endfunc
399 catch /E127:/
400 let caught_E127 = 1
401 endtry
402 call assert_equal(1, caught_E127)
403
404 " Try to define a function in a dict twice
405 let d = {}
406 let lines =<< trim END
407 func d.F1()
408 return 1
409 endfunc
410 END
411 let l = join(lines, "\n") . "\n"
412 exe l
413 call assert_fails('exe l', 'E717:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200414 call assert_fails('call feedkeys(":func d.F1()\<CR>", "xt")', 'E717:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200415
416 " Define an autoload function with an incorrect file name
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100417 call writefile(['func foo#Bar()', 'return 1', 'endfunc'], 'Xscript', 'D')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200418 call assert_fails('source Xscript', 'E746:')
Bram Moolenaar531be472020-09-23 22:38:05 +0200419
420 " Try to list functions using an invalid search pattern
421 call assert_fails('function /\%(/', 'E53:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200422endfunc
423
424" Test for deleting a function
425func Test_del_func()
Bram Moolenaarc553a212021-12-26 20:20:34 +0000426 call assert_fails('delfunction Xabc', 'E117:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200427 let d = {'a' : 10}
428 call assert_fails('delfunc d.a', 'E718:')
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200429 func d.fn()
430 return 1
431 endfunc
Bram Moolenaarddfc0512021-09-06 20:56:56 +0200432
433 " cannot delete the dict function by number
434 let nr = substitute(execute('echo d'), '.*function(''\(\d\+\)'').*', '\1', '')
435 call assert_fails('delfunction g:' .. nr, 'E475: Invalid argument: g:')
436
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200437 delfunc d.fn
438 call assert_equal({'a' : 10}, d)
Bram Moolenaar476a6132020-04-08 19:48:56 +0200439endfunc
440
441" Test for calling return outside of a function
442func Test_return_outside_func()
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100443 call writefile(['return 10'], 'Xscript', 'D')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200444 call assert_fails('source Xscript', 'E133:')
Bram Moolenaar476a6132020-04-08 19:48:56 +0200445endfunc
446
447" Test for errors in calling a function
448func Test_func_arg_error()
449 " Too many arguments
450 call assert_fails("call call('min', range(1,20))", 'E118:')
451 call assert_fails("call call('min', range(1,21))", 'E699:')
452 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)',
453 \ 'E740:')
454
455 " Missing dict argument
456 func Xfunc() dict
457 return 1
458 endfunc
459 call assert_fails('call Xfunc()', 'E725:')
460 delfunc Xfunc
461endfunc
462
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100463func Test_func_dict()
464 let mydict = {'a': 'b'}
465 function mydict.somefunc() dict
466 return len(self)
467 endfunc
468
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200469 call assert_equal("{'a': 'b', 'somefunc': function('3')}", string(mydict))
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100470 call assert_equal(2, mydict.somefunc())
471 call assert_match("^\n function \\d\\\+() dict"
472 \ .. "\n1 return len(self)"
473 \ .. "\n endfunction$", execute('func mydict.somefunc'))
Yegappan Lakshmanan611728f2021-05-24 15:15:47 +0200474 call assert_fails('call mydict.nonexist()', 'E716:')
Bram Moolenaar67322bf2020-12-06 15:03:19 +0100475endfunc
476
477func Test_func_range()
478 new
479 call setline(1, range(1, 8))
480 func FuncRange() range
481 echo a:firstline
482 echo a:lastline
483 endfunc
484 3
485 call assert_equal("\n3\n3", execute('call FuncRange()'))
486 call assert_equal("\n4\n6", execute('4,6 call FuncRange()'))
487 call assert_equal("\n function FuncRange() range"
488 \ .. "\n1 echo a:firstline"
489 \ .. "\n2 echo a:lastline"
490 \ .. "\n endfunction",
491 \ execute('function FuncRange'))
492
493 bwipe!
494endfunc
495
Yegappan Lakshmanan7c7e19c2022-04-09 11:09:07 +0100496" Test for memory allocation failure when defining a new function
497func Test_funcdef_alloc_failure()
498 new
499 let lines =<< trim END
500 func Xtestfunc()
501 return 321
502 endfunc
503 END
504 call setline(1, lines)
505 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
506 call assert_fails('source', 'E342:')
507 call assert_false(exists('*Xtestfunc'))
508 call assert_fails('delfunc Xtestfunc', 'E117:')
509 %d _
510 let lines =<< trim END
511 def g:Xvim9func(): number
512 return 456
513 enddef
514 END
515 call setline(1, lines)
516 call test_alloc_fail(GetAllocId('get_func'), 0, 0)
517 call assert_fails('source', 'E342:')
518 call assert_false(exists('*Xvim9func'))
519 "call test_alloc_fail(GetAllocId('get_func'), 0, 0)
520 "call assert_fails('source', 'E342:')
521 "call assert_false(exists('*Xtestfunc'))
522 "call assert_fails('delfunc Xtestfunc', 'E117:')
523 bw!
524endfunc
525
Bram Moolenaar86d87252022-09-05 21:21:25 +0100526func AddDefer(arg1, ...)
527 call extend(g:deferred, [a:arg1])
528 if a:0 == 1
529 call extend(g:deferred, [a:1])
530 endif
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100531endfunc
532
533func WithDeferTwo()
534 call extend(g:deferred, ['in Two'])
535 for nr in range(3)
536 defer AddDefer('Two' .. nr)
537 endfor
538 call extend(g:deferred, ['end Two'])
539endfunc
540
541func WithDeferOne()
542 call extend(g:deferred, ['in One'])
543 call writefile(['text'], 'Xfuncdefer')
544 defer delete('Xfuncdefer')
545 defer AddDefer('One')
546 call WithDeferTwo()
547 call extend(g:deferred, ['end One'])
548endfunc
549
Bram Moolenaar86d87252022-09-05 21:21:25 +0100550func WithPartialDefer()
551 call extend(g:deferred, ['in Partial'])
552 let Part = funcref('AddDefer', ['arg1'])
553 defer Part("arg2")
554 call extend(g:deferred, ['end Partial'])
555endfunc
556
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100557func Test_defer()
558 let g:deferred = []
559 call WithDeferOne()
560
561 call assert_equal(['in One', 'in Two', 'end Two', 'Two2', 'Two1', 'Two0', 'end One', 'One'], g:deferred)
562 unlet g:deferred
563
564 call assert_equal('', glob('Xfuncdefer'))
Bram Moolenaar86d87252022-09-05 21:21:25 +0100565
566 call assert_fails('defer delete("Xfuncdefer")->Another()', 'E488:')
567 call assert_fails('defer delete("Xfuncdefer").member', 'E488:')
568
569 let g:deferred = []
570 call WithPartialDefer()
571 call assert_equal(['in Partial', 'end Partial', 'arg1', 'arg2'], g:deferred)
572 unlet g:deferred
573
574 let Part = funcref('AddDefer', ['arg1'], {})
575 call assert_fails('defer Part("arg2")', 'E1300:')
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100576endfunc
577
Bram Moolenaar58779852022-09-06 18:31:14 +0100578func DeferLevelTwo()
579 call writefile(['text'], 'XDeleteTwo', 'D')
580 throw 'someerror'
581endfunc
582
583def DeferLevelOne()
584 call writefile(['text'], 'XDeleteOne', 'D')
585 call g:DeferLevelTwo()
586enddef
587
588func Test_defer_throw()
589 let caught = 'no'
590 try
591 call DeferLevelOne()
592 catch /someerror/
593 let caught = 'yes'
594 endtry
595 call assert_equal('yes', caught)
596 call assert_false(filereadable('XDeleteOne'))
597 call assert_false(filereadable('XDeleteTwo'))
598endfunc
599
600func Test_defer_quitall()
601 let lines =<< trim END
602 vim9script
603 func DeferLevelTwo()
604 call writefile(['text'], 'XQuitallTwo', 'D')
605 qa!
606 endfunc
607
608 def DeferLevelOne()
609 call writefile(['text'], 'XQuitallOne', 'D')
610 call DeferLevelTwo()
611 enddef
612
613 DeferLevelOne()
614 END
615 call writefile(lines, 'XdeferQuitall', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100616 let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
Bram Moolenaar58779852022-09-06 18:31:14 +0100617 call assert_equal(0, v:shell_error)
618 call assert_false(filereadable('XQuitallOne'))
619 call assert_false(filereadable('XQuitallTwo'))
620endfunc
621
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100622func Test_defer_quitall_in_expr_func()
623 let lines =<< trim END
624 def DefIndex(idx: number, val: string): bool
625 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
626 if val == 'b'
627 qa!
628 endif
629 return val == 'c'
630 enddef
631
632 def Test_defer_in_funcref()
633 assert_equal(2, indexof(['a', 'b', 'c'], funcref('g:DefIndex')))
634 enddef
635 call Test_defer_in_funcref()
636 END
637 call writefile(lines, 'XdeferQuitallExpr', 'D')
Bram Moolenaar16900322022-09-08 19:51:45 +0100638 let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
Bram Moolenaar9667b2c2022-09-07 17:28:09 +0100639 call assert_equal(0, v:shell_error)
640 call assert_false(filereadable('Xentry0'))
641 call assert_false(filereadable('Xentry1'))
642 call assert_false(filereadable('Xentry2'))
643endfunc
644
Bram Moolenaar98aff652022-09-06 21:02:35 +0100645func FuncIndex(idx, val)
646 call writefile([a:idx .. ': ' .. a:val], 'Xentry' .. a:idx, 'D')
647 return a:val == 'c'
648endfunc
649
650def DefIndex(idx: number, val: string): bool
651 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
652 return val == 'c'
653enddef
654
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100655def DefIndexXtra(xtra: string, idx: number, val: string): bool
656 call writefile([idx .. ': ' .. val], 'Xentry' .. idx, 'D')
657 return val == 'c'
658enddef
659
Bram Moolenaar98aff652022-09-06 21:02:35 +0100660def Test_defer_in_funcref()
661 assert_equal(2, indexof(['a', 'b', 'c'], function('g:FuncIndex')))
662 assert_false(filereadable('Xentry0'))
663 assert_false(filereadable('Xentry1'))
664 assert_false(filereadable('Xentry2'))
665
666 assert_equal(2, indexof(['a', 'b', 'c'], g:DefIndex))
667 assert_false(filereadable('Xentry0'))
668 assert_false(filereadable('Xentry1'))
669 assert_false(filereadable('Xentry2'))
670
671 assert_equal(2, indexof(['a', 'b', 'c'], function('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'], funcref(g:DefIndex)))
677 assert_false(filereadable('Xentry0'))
678 assert_false(filereadable('Xentry1'))
679 assert_false(filereadable('Xentry2'))
Bram Moolenaarc9c967d2022-09-07 16:48:46 +0100680
681 assert_equal(2, indexof(['a', 'b', 'c'], function(g:DefIndexXtra, ['xtra'])))
682 assert_false(filereadable('Xentry0'))
683 assert_false(filereadable('Xentry1'))
684 assert_false(filereadable('Xentry2'))
685
686 assert_equal(2, indexof(['a', 'b', 'c'], funcref(g:DefIndexXtra, ['xtra'])))
687 assert_false(filereadable('Xentry0'))
688 assert_false(filereadable('Xentry1'))
689 assert_false(filereadable('Xentry2'))
Bram Moolenaar98aff652022-09-06 21:02:35 +0100690enddef
691
Bram Moolenaar16900322022-09-08 19:51:45 +0100692func Test_defer_wrong_arguments()
693 call assert_fails('defer delete()', 'E119:')
694 call assert_fails('defer FuncIndex(1)', 'E119:')
695 call assert_fails('defer delete(1, 2, 3)', 'E118:')
696 call assert_fails('defer FuncIndex(1, 2, 3)', 'E118:')
697
698 let lines =<< trim END
699 def DeferFunc0()
700 defer delete()
701 enddef
702 defcompile
703 END
704 call v9.CheckScriptFailure(lines, 'E119:')
705 let lines =<< trim END
706 def DeferFunc3()
707 defer delete(1, 2, 3)
708 enddef
709 defcompile
710 END
711 call v9.CheckScriptFailure(lines, 'E118:')
712 let lines =<< trim END
713 def DeferFunc2()
714 defer delete(1, 2)
715 enddef
716 defcompile
717 END
718 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
719
720 def g:FuncOneArg(arg: string)
721 echo arg
722 enddef
723
724 let lines =<< trim END
725 def DeferUserFunc0()
726 defer g:FuncOneArg()
727 enddef
728 defcompile
729 END
730 call v9.CheckScriptFailure(lines, 'E119:')
731 let lines =<< trim END
732 def DeferUserFunc2()
733 defer g:FuncOneArg(1, 2)
734 enddef
735 defcompile
736 END
737 call v9.CheckScriptFailure(lines, 'E118:')
738 let lines =<< trim END
739 def DeferUserFunc1()
740 defer g:FuncOneArg(1)
741 enddef
742 defcompile
743 END
744 call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
745endfunc
746
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100747
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200748" vim: shiftwidth=2 sts=2 expandtab