test_user_func.vim 22 KB

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