blob: 9ef91dffa44b0232a2d79c143bdf8be542c3049e [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim script language tests
2" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
Bram Moolenaara6296202020-08-05 11:23:13 +02003" Last Change: 2020 Jun 07
Bram Moolenaar071d4272004-06-13 20:20:40 +00004
5"-------------------------------------------------------------------------------
6" Test environment {{{1
7"-------------------------------------------------------------------------------
8
9
10" Adding new tests easily. {{{2
11"
12" Writing new tests is eased considerably with the following functions and
13" abbreviations (see "Commands for recording the execution path", "Automatic
14" argument generation").
15"
16" To get the abbreviations, execute the command
17"
18" :let test49_set_env = 1 | source test49.vim
19"
20" To get them always (from src/testdir), put a line
21"
22" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
23"
24" into the local .vimrc file in the src/testdir directory.
25"
26if exists("test49_set_env") && test49_set_env
27
28 " Automatic argument generation for the test environment commands.
29
30 function! Xsum()
31 let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
32 " Evaluate arithmetic expression.
33 if addend != ""
34 exec "let g:Xsum = g:Xsum + " . addend
35 endif
36 endfunction
37
38 function! Xcheck()
39 let g:Xsum=0
40 ?XpathINIT?,.call Xsum()
41 exec "norm A "
42 return g:Xsum
43 endfunction
44
45 iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
46
47 function! Xcomment(num)
48 let str = ""
49 let tabwidth = &sts ? &sts : &ts
50 let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
51 while tabs > 0
52 let str = str . "\t"
53 let tabs = tabs - 1
54 endwhile
55 let str = str . '" X:'
56 return str
57 endfunction
58
59 function! Xloop()
60 let back = line(".") . "|norm" . virtcol(".") . "|"
61 norm 0
62 let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
63 exec back
64 let theline = getline(last)
65 if theline =~ 'X\(loop\|path\)INIT'
66 let num = 1
67 else
68 let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
69 endif
70 ?X\(loop\|path\)INIT?
71 \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
72 exec back
73 exec "norm a "
74 return num . Xcomment(strlen(num))
75 endfunction
76
77 iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
78
79 function! Xpath(loopinit)
80 let back = line(".") . "|norm" . virtcol(".") . "|"
81 norm 0
82 let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
83 exec back
84 let theline = getline(last)
85 if theline =~ 'XpathINIT'
86 let num = 1
87 elseif theline =~ 'Xpath\>'
88 let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
89 else
90 let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
91 let num = substitute(theline, pattern, '\1', "")
92 let factor = substitute(theline, pattern, '\2', "")
93 " The "<C-O>x" from the "Xpath" iab and the character triggering its
94 " expansion are in the input buffer. Save and clear typeahead so
95 " that it is not read away by the call to "input()" below. Restore
96 " afterwards.
97 call inputsave()
98 let loops = input("Number of iterations in previous loop? ")
99 call inputrestore()
100 while (loops > 0)
101 let num = num * factor
102 let loops = loops - 1
103 endwhile
104 endif
105 exec "norm a "
106 if a:loopinit
107 return num . " 1"
108 endif
109 return num . Xcomment(strlen(num))
110 endfunction
111
112 iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
113 iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
114
115 " Also useful (see ExtraVim below):
116 aug ExtraVim
117 au!
118 au BufEnter <sfile> syn region ExtraVim
119 \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
120 \ transparent keepend
121 au BufEnter <sfile> syn match ExtraComment /^"/
122 \ contained containedin=ExtraVim
123 au BufEnter <sfile> hi link ExtraComment vimComment
124 aug END
125
126 aug Xpath
127 au BufEnter <sfile> syn keyword Xpath
128 \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
129 au BufEnter <sfile> hi link Xpath Special
130 aug END
131
132 do BufEnter <sfile>
133
134 " Do not execute the tests when sourcing this file for getting the functions
135 " and abbreviations above, which are intended for easily adding new test
136 " cases; they are not needed for test execution. Unlet the variable
137 " controlling this so that an explicit ":source" command for this file will
138 " execute the tests.
139 unlet test49_set_env
140 finish
141
142endif
143
144
145" Commands for recording the execution path. {{{2
146"
147" The Xpath/Xloop commands can be used for computing the eXecution path by
148" adding (different) powers of 2 from those script lines, for which the
149" execution should be checked. Xloop provides different addends for each
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000150" execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151" points (multiply counted inside loops) can be tested.
152"
153" Note that the arguments of the following commands can be generated
154" automatically, see below.
155"
156" Usage: {{{3
157"
158" - Use XpathINIT at the beginning of the test.
159"
160" - Use Xpath to check if a line is executed.
161" Argument: power of 2 (decimal).
162"
163" - To check multiple execution of loops use Xloop for automatically
164" computing Xpath values:
165"
166" - Use XloopINIT before the loop.
167" Two arguments:
168" - the first Xpath value (power of 2) to be used (Xnext),
169" - factor for computing a new Xnext value when reexecuting a loop
170" (by a ":continue" or ":endwhile"); this should be 2^n where
171" n is the number of Xloop commands inside the loop.
172" If XloopINIT! is used, the first execution of XloopNEXT is
173" a no-operation.
174"
175" - Use Xloop inside the loop:
176" One argument:
177" The argument and the Xnext value are multiplied to build the
178" next Xpath value. No new Xnext value is prepared. The argument
179" should be 2^(n-1) for the nth Xloop command inside the loop.
180" If the loop has only one Xloop command, the argument can be
Bram Moolenaarf48ee3c2019-12-06 22:18:20 +0100181" omitted (default: 1).
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182"
183" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new
184" Xnext value for the next execution of the loop by multiplying the old
185" one with the factor specified in the XloopINIT command. No Argument.
186" Alternatively, when XloopINIT! is used, a single XloopNEXT at the
187" beginning of the loop can be used.
188"
189" Nested loops are not supported.
190"
191" - Use Xcheck at end of each test. It prints the test number, the expected
192" execution path value, the test result ("OK" or "FAIL"), and, if the tests
193" fails, the actual execution path.
194" One argument:
195" Expected Xpath/Xloop sum for the correct execution path.
196" In order that this value can be computed automatically, do the
197" following: For each line in the test with an Xpath and Xloop
198" command, add a comment starting with "X:" and specifying an
199" expression that evaluates to the value contributed by this line to
200" the correct execution path. (For copying an Xpath argument of at
201" least two digits into the comment, press <C-P>.) At the end of the
202" test, just type "Xcheck" and press <Esc>.
203"
204" - In order to add additional information to the test output file, use the
205" Xout command. Argument(s) like ":echo".
206"
207" Automatic argument generation: {{{3
208"
209" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
210" generated automatically, so that new tests can easily be written without
211" mental arithmetic. The Xcheck argument is computed from the "X:" comments
212" of the preceding Xpath and Xloop commands. See the commands and
213" abbreviations at the beginning of this file.
214"
215" Implementation: {{{3
216" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
217"
218" The variants for existing g:ExtraVimResult are needed when executing a script
219" in an extra Vim process, see ExtraVim below.
220
221" EXTRA_VIM_START - do not change or remove this line.
222
223com! XpathINIT let g:Xpath = 0
224
225if exists("g:ExtraVimResult")
226 com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult
227else
228 com! -count -bar Xpath let g:Xpath = g:Xpath + <count>
229endif
230
231com! -count -nargs=1 -bang
232 \ XloopINIT let g:Xnext = <count> |
233 \ let g:Xfactor = <args> |
234 \ let g:Xskip = strlen("<bang>")
235
236if exists("g:ExtraVimResult")
237 com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" .
238 \ g:ExtraVimResult
239else
240 com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count>
241endif
242
243com! XloopNEXT let g:Xnext = g:Xnext *
244 \ (g:Xskip ? 1 : g:Xfactor) |
245 \ let g:Xskip = 0
246
247let @r = ""
248let Xtest = 1
249com! -count Xcheck let Xresult = "*** Test " .
250 \ (Xtest<10?" ":Xtest<100?" ":"") .
251 \ Xtest . ": " . (
252 \ (Xpath==<count>) ? "OK (".Xpath.")" :
253 \ "FAIL (".Xpath." instead of <count>)"
254 \ ) |
255 \ let @R = Xresult . "\n" |
256 \ echo Xresult |
257 \ let Xtest = Xtest + 1
258
259if exists("g:ExtraVimResult")
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000260 com! -nargs=+ Xoutq exec "!echo @R:'" .
261 \ substitute(substitute(<q-args>,
262 \ "'", '&\\&&', "g"), "\n", "@NL@", "g")
263 \ . "' >>" . g:ExtraVimResult
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264else
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000265 com! -nargs=+ Xoutq let @R = "--- Test " .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000266 \ (g:Xtest<10?" ":g:Xtest<100?" ":"") .
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000267 \ g:Xtest . ": " . substitute(<q-args>,
268 \ "\n", "&\t ", "g") . "\n"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269endif
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000270com! -nargs=+ Xout exec 'Xoutq' <args>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000271
272" Switch off storing of lines for undoing changes. Speeds things up a little.
273set undolevels=-1
274
275" EXTRA_VIM_STOP - do not change or remove this line.
276
277
278" ExtraVim() - Run a script file in an extra Vim process. {{{2
279"
280" This is useful for testing immediate abortion of the script processing due to
281" an error in a command dynamically enclosed by a :try/:tryend region or when an
282" exception is thrown but not caught or when an interrupt occurs. It can also
283" be used for testing :finish.
284"
285" An interrupt location can be specified by an "INTERRUPT" comment. A number
286" telling how often this location is reached (in a loop or in several function
287" calls) should be specified as argument. When missing, once per script
288" invocation or function call is assumed. INTERRUPT locations are tested by
289" setting a breakpoint in that line and using the ">quit" debug command when
290" the breakpoint is reached. A function for which an INTERRUPT location is
291" specified must be defined before calling it (or executing it as a script by
292" using ExecAsScript below).
293"
294" This function is only called in normal modus ("g:ExtraVimResult" undefined).
295"
296" Tests to be executed as an extra script should be written as follows:
297"
298" column 1 column 1
299" | |
300" v v
301"
302" XpathINIT XpathINIT
303" if ExtraVim() if ExtraVim()
304" ... " ...
305" ... " ...
306" endif endif
307" Xcheck <number> Xcheck <number>
308"
309" Double quotes in column 1 are removed before the script is executed.
310" They should be used if the test has unbalanced conditionals (:if/:endif,
311" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The
312" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
313"
314" A file name may be specified as argument. All messages of the extra Vim
315" process are then redirected to the file. An existing file is overwritten.
316"
317let ExtraVimCount = 0
318let ExtraVimBase = expand("<sfile>")
319let ExtraVimTestEnv = ""
320"
Bram Moolenaar1e115362019-01-09 23:01:02 +0100321function ExtraVim(...)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322 " Count how often this function is called.
323 let g:ExtraVimCount = g:ExtraVimCount + 1
324
325 " Disable folds to prevent that the ranges in the ":write" commands below
326 " are extended up to the end of a closed fold. This also speeds things up
327 " considerably.
328 set nofoldenable
329
330 " Open a buffer for this test script and copy the test environment to
331 " a temporary file. Take account of parts relevant for the extra script
332 " execution only.
333 let current_buffnr = bufnr("%")
334 execute "view +1" g:ExtraVimBase
335 if g:ExtraVimCount == 1
336 let g:ExtraVimTestEnv = tempname()
337 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
338 \ g:ExtraVimTestEnv "|']+"
339 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
340 \ g:ExtraVimTestEnv "|']+"
341 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
342 \ g:ExtraVimTestEnv "|']+"
343 execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
344 \ g:ExtraVimTestEnv "|']+"
345 endif
346
347 " Start the extra Vim script with a ":source" command for the test
348 " environment. The source line number where the extra script will be
349 " appended, needs to be passed as variable "ExtraVimBegin" to the script.
350 let extra_script = tempname()
351 exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
352 let extra_begin = 1
353
354 " Starting behind the test environment, skip over the first g:ExtraVimCount
355 " occurrences of "if ExtraVim()" and copy the following lines up to the
356 " matching "endif" to the extra Vim script.
357 execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
358 exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
359 execute ".,/^endif/-write >>" . extra_script
360
361 " Open a buffer for the extra Vim script, delete all ^", and write the
362 " script if was actually modified.
363 execute "edit +" . (extra_begin + 1) extra_script
364 ,$s/^"//e
365 update
366
367 " Count the INTERRUPTs and build the breakpoint and quit commands.
368 let breakpoints = ""
369 let debug_quits = ""
370 let in_func = 0
371 exec extra_begin
372 while search(
373 \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
374 \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
375 \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
376 \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
377 \ "W") > 0
378 let theline = getline(".")
379 if theline =~ '^\s*fu'
380 " Function definition.
381 let in_func = 1
382 let func_start = line(".")
383 let func_name = substitute(theline,
384 \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
Bram Moolenaar071d4272004-06-13 20:20:40 +0000385 elseif theline =~ '^\s*endf'
386 " End of function definition.
387 let in_func = 0
388 else
389 let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
390 \ '\1', "")
391 if finding =~ '^"\s*INTERRUPT\h\@!'
392 " Interrupt comment. Compose as many quit commands as
393 " specified.
394 let cnt = substitute(finding,
395 \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
396 let quits = ""
397 while cnt > 0
398 " Use "\r" rather than "\n" to separate the quit commands.
399 " "\r" is not interpreted as command separator by the ":!"
400 " command below but works to separate commands in the
401 " external vim.
402 let quits = quits . "q\r"
403 let cnt = cnt - 1
404 endwhile
405 if in_func
406 " Add the function breakpoint and note the number of quits
407 " to be used, if specified, or one for every call else.
408 let breakpoints = breakpoints . " -c 'breakadd func " .
Bram Moolenaare224ffa2006-03-01 00:01:28 +0000409 \ (line(".") - func_start) . " " .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410 \ func_name . "'"
411 if quits != ""
412 let debug_quits = debug_quits . quits
413 elseif !exists("quits{func_name}")
414 let quits{func_name} = "q\r"
415 else
416 let quits{func_name} = quits{func_name} . "q\r"
417 endif
418 else
419 " Add the file breakpoint and the quits to be used for it.
420 let breakpoints = breakpoints . " -c 'breakadd file " .
421 \ line(".") . " " . extra_script . "'"
422 if quits == ""
423 let quits = "q\r"
424 endif
425 let debug_quits = debug_quits . quits
426 endif
427 else
428 " Add the quits to be used for calling the function or executing
429 " it as script file.
430 if finding =~ '^ExecAsScript'
431 " Sourcing function as script.
432 let finding = substitute(finding,
433 \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
434 else
435 " Function call.
436 let finding = substitute(finding,
437 \ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
438 endif
439 if exists("quits{finding}")
440 let debug_quits = debug_quits . quits{finding}
441 endif
442 endif
443 endif
444 endwhile
445
446 " Close the buffer for the script and create an (empty) resultfile.
447 bwipeout
448 let resultfile = tempname()
449 exec "!>" . resultfile
450
451 " Run the script in an extra vim. Switch to extra modus by passing the
452 " resultfile in ExtraVimResult. Redirect messages to the file specified as
453 " argument if any. Use ":debuggreedy" so that the commands provided on the
454 " pipe are consumed at the debug prompt. Use "-N" to enable command-line
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000455 " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid
Bram Moolenaar071d4272004-06-13 20:20:40 +0000456 " messing up the user's viminfo file.
457 let redirect = a:0 ?
458 \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
Bram Moolenaar1ac41a52019-10-10 13:30:12 +0200459 exec "!echo '" . debug_quits . "q' | " .. v:progpath .. " -u NONE -N -Xes" . redirect .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460 \ " -c 'debuggreedy|set viminfo+=nviminfo'" .
461 \ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
462 \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
463 \ " -S " . extra_script
464
465 " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout
466 " information provided by the extra Vim process to the test output.
467 let sum = 0
468 exec "edit" resultfile
469 let line = 1
470 while line <= line("$")
471 let theline = getline(line)
472 if theline =~ '^@R:'
473 exec 'Xout "' . substitute(substitute(
474 \ escape(escape(theline, '"'), '\"'),
475 \ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
476 else
477 let sum = sum + getline(line)
478 endif
479 let line = line + 1
480 endwhile
481 bwipeout
482 let g:Xpath = g:Xpath + sum
483
484 " Delete the extra script and the resultfile.
485 call delete(extra_script)
486 call delete(resultfile)
487
488 " Switch back to the buffer that was active when this function was entered.
489 exec "buffer" current_buffnr
490
491 " Return 0. This protects extra scripts from being run in the main Vim
492 " process.
493 return 0
494endfunction
495
496
497" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2
498"
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000499" Evaluates v:throwpoint and returns the throwpoint relative to the beginning of
Bram Moolenaar071d4272004-06-13 20:20:40 +0000500" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
501"
502" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100503function ExtraVimThrowpoint()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504 if !exists("g:ExtraVimBegin")
505 Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
506 return v:throwpoint
507 endif
508
509 if v:throwpoint =~ '^function\>'
510 return v:throwpoint
511 endif
512
513 return "line " .
514 \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
515 \ " of ExtraVim() script"
516endfunction
517" EXTRA_VIM_STOP - do not change or remove this line.
518
519
520" MakeScript() - Make a script file from a function. {{{2
521"
522" Create a script that consists of the body of the function a:funcname.
523" Replace any ":return" by a ":finish", any argument variable by a global
Bram Moolenaar1bc353b2019-09-01 14:45:28 +0200524" variable, and every ":call" by a ":source" for the next following argument
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525" in the variable argument list. This function is useful if similar tests are
526" to be made for a ":return" from a function call or a ":finish" in a script
527" file.
528"
529" In order to execute a function specifying an INTERRUPT location (see ExtraVim)
530" as a script file, use ExecAsScript below.
531"
532" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100533function MakeScript(funcname, ...)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000534 let script = tempname()
535 execute "redir! >" . script
536 execute "function" a:funcname
537 redir END
538 execute "edit" script
539 " Delete the "function" and the "endfunction" lines. Do not include the
540 " word "function" in the pattern since it might be translated if LANG is
541 " set. When MakeScript() is being debugged, this deletes also the debugging
542 " output of its line 3 and 4.
543 exec '1,/.*' . a:funcname . '(.*)/d'
544 /^\d*\s*endfunction\>/,$d
545 %s/^\d*//e
546 %s/return/finish/e
547 %s/\<a:\(\h\w*\)/g:\1/ge
548 normal gg0
549 let cnt = 0
550 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
551 let cnt = cnt + 1
552 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
553 endwhile
554 g/^\s*$/d
555 write
556 bwipeout
557 return script
558endfunction
559" EXTRA_VIM_STOP - do not change or remove this line.
560
561
562" ExecAsScript - Source a temporary script made from a function. {{{2
563"
564" Make a temporary script file from the function a:funcname, ":source" it, and
565" delete it afterwards.
566"
567" When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
568" location specified in the function.
569"
570" EXTRA_VIM_START - do not change or remove this line.
Bram Moolenaar1e115362019-01-09 23:01:02 +0100571function ExecAsScript(funcname)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572 " Make a script from the function passed as argument.
573 let script = MakeScript(a:funcname)
574
575 " When running in an extra Vim process, add a file breakpoint for each
576 " function breakpoint set when the extra Vim process was invoked by
577 " ExtraVim().
578 if exists("g:ExtraVimResult")
579 let bplist = tempname()
580 execute "redir! >" . bplist
581 breaklist
582 redir END
583 execute "edit" bplist
584 " Get the line number from the function breakpoint. Works also when
585 " LANG is set.
586 execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
587 %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
588 let cnt = 0
589 while cnt < line("$")
590 let cnt = cnt + 1
591 if getline(cnt) != ""
592 execute "breakadd file" getline(cnt) script
593 endif
594 endwhile
595 bwipeout!
596 call delete(bplist)
597 endif
598
599 " Source and delete the script.
600 exec "source" script
601 call delete(script)
602endfunction
603
604com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
605" EXTRA_VIM_STOP - do not change or remove this line.
606
607
608" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
609
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610function! MESSAGES(...)
611 try
612 exec "edit" g:msgfile
613 catch /^Vim(edit):/
614 return 0
615 endtry
616
617 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
618 let match = 1
619 norm gg
620
621 let num = a:0 / 2
622 let cnt = 1
623 while cnt <= num
624 let enr = a:{2*cnt - 1}
625 let emsg= a:{2*cnt}
626 let cnt = cnt + 1
627
628 if enr == ""
629 Xout "TODO: Add message number for:" emsg
630 elseif enr == "INT"
631 let enr = ""
632 endif
633 if enr == "" && !english
634 continue
635 endif
636 let pattern = (enr != "") ? enr . ':.*' : ''
637 if english
638 let pattern = pattern . emsg
639 endif
640 if !search(pattern, "W")
641 let match = 0
642 Xout "No match for:" pattern
643 endif
644 norm $
645 endwhile
646
647 bwipeout!
648 return match
649endfunction
650
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651" Leave MESSAGES() for the next tests.
652
Bram Moolenaar9470a4d2020-08-07 16:49:11 +0200653" Tests 1 to 50, 52 to 57, 87 were moved to test_vimscript.vim
654" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim
655let Xtest = 59
Bram Moolenaar071d4272004-06-13 20:20:40 +0000656
657"-------------------------------------------------------------------------------
658"
659" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1
660"
661" When a :catch clause is left by a ":break" etc or an error or
662" interrupt exception, v:exception and v:throwpoint are reset. They
663" are not affected by an exception that is discarded before being
664" caught.
665"-------------------------------------------------------------------------------
666
667XpathINIT
668
669if ExtraVim()
670
671 XloopINIT! 1 2
672
673 let sfile = expand("<sfile>")
674
675 function! LineNumber()
676 return substitute(substitute(v:throwpoint, g:sfile, '', ""),
677 \ '\D*\(\d*\).*', '\1', "")
678 endfunction
679
680 command! -nargs=1 SetLineNumber
681 \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry
682
683 " Check v:exception/v:throwpoint against second/fourth parameter if
684 " specified, check for being empty else.
685 function! CHECK(n, ...)
686 XloopNEXT
687 let exception = a:0 != 0 ? a:1 : "" " second parameter (optional)
688 let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional)
689 let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional)
690 let error = 0
691 if emsg != ""
Bram Moolenaarbc045ea2005-06-05 22:01:26 +0000692 " exception is the error number, emsg the English error message text
Bram Moolenaar071d4272004-06-13 20:20:40 +0000693 if exception !~ '^E\d\+$'
694 Xout "TODO: Add message number for:" emsg
695 elseif v:lang == "C" || v:lang =~ '^[Ee]n'
696 if exception == "E492" && emsg == "Not an editor command"
697 let exception = '^Vim:' . exception . ': ' . emsg
698 else
699 let exception = '^Vim(\a\+):' . exception . ': ' . emsg
700 endif
701 else
702 if exception == "E492"
703 let exception = '^Vim:' . exception
704 else
705 let exception = '^Vim(\a\+):' . exception
706 endif
707 endif
708 endif
709 if exception == "" && v:exception != ""
710 Xout a:n.": v:exception is set:" v:exception
711 let error = 1
712 elseif exception != "" && v:exception !~ exception
713 Xout a:n.": v:exception (".v:exception.") does not match" exception
714 let error = 1
715 endif
716 if line == 0 && v:throwpoint != ""
717 Xout a:n.": v:throwpoint is set:" v:throwpoint
718 let error = 1
719 elseif line != 0 && v:throwpoint !~ '\<' . line . '\>'
720 Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
721 let error = 1
722 endif
723 if !error
724 Xloop 1 " X: 2097151
725 endif
726 endfunction
727
728 while 1
729 try
730 throw "x1"
731 catch /.*/
732 break
733 endtry
734 endwhile
735 call CHECK(1)
736
737 while 1
738 try
739 throw "x2"
740 catch /.*/
741 break
742 finally
743 call CHECK(2)
744 endtry
745 break
746 endwhile
747 call CHECK(3)
748
749 while 1
750 try
751 let errcaught = 0
752 try
753 try
754 throw "x3"
755 catch /.*/
756 SetLineNumber line_before_error
757 asdf
758 endtry
759 catch /.*/
760 let errcaught = 1
761 call CHECK(4, 'E492', "Not an editor command",
762 \ line_before_error + 1)
763 endtry
764 finally
765 if !errcaught && $VIMNOERRTHROW
766 call CHECK(4)
767 endif
768 break " discard error for $VIMNOERRTHROW
769 endtry
770 endwhile
771 call CHECK(5)
772
773 Xpath 2097152 " X: 2097152
774
775 while 1
776 try
777 let intcaught = 0
778 try
779 try
780 throw "x4"
781 catch /.*/
782 SetLineNumber two_lines_before_interrupt
783 "INTERRUPT
784 let dummy = 0
785 endtry
786 catch /.*/
787 let intcaught = 1
788 call CHECK(6, "Vim:Interrupt", '',
789 \ two_lines_before_interrupt + 2)
790 endtry
791 finally
792 if !intcaught && $VIMNOINTTHROW
793 call CHECK(6)
794 endif
795 break " discard interrupt for $VIMNOINTTHROW
796 endtry
797 endwhile
798 call CHECK(7)
799
800 Xpath 4194304 " X: 4194304
801
802 while 1
803 try
804 let errcaught = 0
805 try
806 try
807" if 1
808 SetLineNumber line_before_throw
809 throw "x5"
810 " missing endif
811 catch /.*/
812 Xpath 8388608 " X: 0
813 endtry
814 catch /.*/
815 let errcaught = 1
816 call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3)
817 endtry
818 finally
819 if !errcaught && $VIMNOERRTHROW
820 call CHECK(8)
821 endif
822 break " discard error for $VIMNOERRTHROW
823 endtry
824 endwhile
825 call CHECK(9)
826
827 Xpath 16777216 " X: 16777216
828
829 try
830 while 1
831 try
832 throw "x6"
833 finally
834 break
835 endtry
836 break
837 endwhile
838 catch /.*/
839 Xpath 33554432 " X: 0
840 endtry
841 call CHECK(10)
842
843 try
844 while 1
845 try
846 throw "x7"
847 finally
848 break
849 endtry
850 break
851 endwhile
852 catch /.*/
853 Xpath 67108864 " X: 0
854 finally
855 call CHECK(11)
856 endtry
857 call CHECK(12)
858
859 while 1
860 try
861 let errcaught = 0
862 try
863 try
864 throw "x8"
865 finally
866 SetLineNumber line_before_error
867 asdf
868 endtry
869 catch /.*/
870 let errcaught = 1
871 call CHECK(13, 'E492', "Not an editor command",
872 \ line_before_error + 1)
873 endtry
874 finally
875 if !errcaught && $VIMNOERRTHROW
876 call CHECK(13)
877 endif
878 break " discard error for $VIMNOERRTHROW
879 endtry
880 endwhile
881 call CHECK(14)
882
883 Xpath 134217728 " X: 134217728
884
885 while 1
886 try
887 let intcaught = 0
888 try
889 try
890 throw "x9"
891 finally
892 SetLineNumber two_lines_before_interrupt
893 "INTERRUPT
894 endtry
895 catch /.*/
896 let intcaught = 1
897 call CHECK(15, "Vim:Interrupt", '',
898 \ two_lines_before_interrupt + 2)
899 endtry
900 finally
901 if !intcaught && $VIMNOINTTHROW
902 call CHECK(15)
903 endif
904 break " discard interrupt for $VIMNOINTTHROW
905 endtry
906 endwhile
907 call CHECK(16)
908
909 Xpath 268435456 " X: 268435456
910
911 while 1
912 try
913 let errcaught = 0
914 try
915 try
916" if 1
917 SetLineNumber line_before_throw
918 throw "x10"
919 " missing endif
920 finally
921 call CHECK(17)
922 endtry
923 catch /.*/
924 let errcaught = 1
925 call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3)
926 endtry
927 finally
928 if !errcaught && $VIMNOERRTHROW
929 call CHECK(18)
930 endif
931 break " discard error for $VIMNOERRTHROW
932 endtry
933 endwhile
934 call CHECK(19)
935
936 Xpath 536870912 " X: 536870912
937
938 while 1
939 try
940 let errcaught = 0
941 try
942 try
943" if 1
944 SetLineNumber line_before_throw
945 throw "x11"
946 " missing endif
947 endtry
948 catch /.*/
949 let errcaught = 1
950 call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3)
951 endtry
952 finally
953 if !errcaught && $VIMNOERRTHROW
954 call CHECK(20)
955 endif
956 break " discard error for $VIMNOERRTHROW
957 endtry
958 endwhile
959 call CHECK(21)
960
961 Xpath 1073741824 " X: 1073741824
962
963endif
964
965Xcheck 2038431743
966
967
968"-------------------------------------------------------------------------------
969"
970" Test 60: (Re)throwing v:exception; :echoerr. {{{1
971"
972" A user exception can be rethrown after catching by throwing
973" v:exception. An error or interrupt exception cannot be rethrown
974" because Vim exceptions cannot be faked. A Vim exception using the
975" value of v:exception can, however, be triggered by the :echoerr
976" command.
977"-------------------------------------------------------------------------------
978
979XpathINIT
980
981try
982 try
983 Xpath 1 " X: 1
984 throw "oops"
985 catch /oops/
986 Xpath 2 " X: 2
987 throw v:exception " rethrow user exception
988 catch /.*/
989 Xpath 4 " X: 0
990 endtry
991catch /^oops$/ " catches rethrown user exception
992 Xpath 8 " X: 8
993catch /.*/
994 Xpath 16 " X: 0
995endtry
996
997function! F()
998 try
999 let caught = 0
1000 try
1001 Xpath 32 " X: 32
1002 write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
1003 Xpath 64 " X: 0
1004 Xout "did_emsg was reset before executing " .
1005 \ "BufWritePost autocommands."
1006 catch /^Vim(write):/
1007 let caught = 1
1008 throw v:exception " throw error: cannot fake Vim exception
1009 catch /.*/
1010 Xpath 128 " X: 0
1011 finally
1012 Xpath 256 " X: 256
1013 if !caught && !$VIMNOERRTHROW
1014 Xpath 512 " X: 0
1015 endif
1016 endtry
1017 catch /^Vim(throw):/ " catches throw error
1018 let caught = caught + 1
1019 catch /.*/
1020 Xpath 1024 " X: 0
1021 finally
1022 Xpath 2048 " X: 2048
1023 if caught != 2
1024 if !caught && !$VIMNOERRTHROW
1025 Xpath 4096 " X: 0
1026 elseif caught
1027 Xpath 8192 " X: 0
1028 endif
1029 return | " discard error for $VIMNOERRTHROW
1030 endif
1031 endtry
1032endfunction
1033
1034call F()
1035delfunction F
1036
1037function! G()
1038 try
1039 let caught = 0
1040 try
1041 Xpath 16384 " X: 16384
1042 asdf
1043 catch /^Vim/ " catch error exception
1044 let caught = 1
1045 " Trigger Vim error exception with value specified after :echoerr
1046 let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
1047 echoerr value
1048 catch /.*/
1049 Xpath 32768 " X: 0
1050 finally
1051 Xpath 65536 " X: 65536
1052 if !caught
1053 if !$VIMNOERRTHROW
1054 Xpath 131072 " X: 0
1055 else
1056 let value = "Error"
1057 echoerr value
1058 endif
1059 endif
1060 endtry
1061 catch /^Vim(echoerr):/
1062 let caught = caught + 1
1063 if v:exception !~ value
1064 Xpath 262144 " X: 0
1065 endif
1066 catch /.*/
1067 Xpath 524288 " X: 0
1068 finally
1069 Xpath 1048576 " X: 1048576
1070 if caught != 2
1071 if !caught && !$VIMNOERRTHROW
1072 Xpath 2097152 " X: 0
1073 elseif caught
1074 Xpath 4194304 " X: 0
1075 endif
1076 return | " discard error for $VIMNOERRTHROW
1077 endif
1078 endtry
1079endfunction
1080
1081call G()
1082delfunction G
1083
1084unlet! value caught
1085
1086if ExtraVim()
1087 try
1088 let errcaught = 0
1089 try
1090 Xpath 8388608 " X: 8388608
1091 let intcaught = 0
1092 "INTERRUPT
1093 catch /^Vim:/ " catch interrupt exception
1094 let intcaught = 1
1095 " Trigger Vim error exception with value specified after :echoerr
1096 echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
1097 catch /.*/
1098 Xpath 16777216 " X: 0
1099 finally
1100 Xpath 33554432 " X: 33554432
1101 if !intcaught
1102 if !$VIMNOINTTHROW
1103 Xpath 67108864 " X: 0
1104 else
1105 echoerr "Interrupt"
1106 endif
1107 endif
1108 endtry
1109 catch /^Vim(echoerr):/
1110 let errcaught = 1
1111 if v:exception !~ "Interrupt"
1112 Xpath 134217728 " X: 0
1113 endif
1114 finally
1115 Xpath 268435456 " X: 268435456
1116 if !errcaught && !$VIMNOERRTHROW
1117 Xpath 536870912 " X: 0
1118 endif
1119 endtry
1120endif
1121
1122Xcheck 311511339
1123
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02001124" Test 61 was moved to test_vimscript.vim
1125let Xtest = 62
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126
1127"-------------------------------------------------------------------------------
1128" Test 62: Catching error exceptions {{{1
1129"
1130" An error inside a :try/:endtry region is converted to an exception
1131" and can be caught. The error exception has a "Vim(cmdname):" prefix
1132" where cmdname is the name of the failing command, or a "Vim:" prefix
1133" if no command name is known. The "Vim" prefixes cannot be faked.
1134"-------------------------------------------------------------------------------
1135
1136XpathINIT
1137
1138function! MSG(enr, emsg)
1139 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1140 if a:enr == ""
1141 Xout "TODO: Add message number for:" a:emsg
1142 let v:errmsg = ":" . v:errmsg
1143 endif
1144 let match = 1
1145 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1146 let match = 0
1147 if v:errmsg == ""
1148 Xout "Message missing."
1149 else
1150 let v:errmsg = escape(v:errmsg, '"')
1151 Xout "Unexpected message:" v:errmsg
1152 endif
1153 endif
1154 return match
1155endfunction
1156
1157while 1
1158 try
1159 try
1160 let caught = 0
1161 unlet novar
1162 catch /^Vim(unlet):/
1163 let caught = 1
1164 let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
1165 finally
1166 Xpath 1 " X: 1
1167 if !caught && !$VIMNOERRTHROW
1168 Xpath 2 " X: 0
1169 endif
1170 if !MSG('E108', "No such variable")
1171 Xpath 4 " X: 0
1172 endif
1173 endtry
1174 catch /.*/
1175 Xpath 8 " X: 0
1176 Xout v:exception "in" v:throwpoint
1177 finally
1178 break " discard error for $VIMNOERRTHROW
1179 endtry
1180endwhile
1181
1182while 1
1183 try
1184 try
1185 let caught = 0
1186 throw novar " error in :throw
1187 catch /^Vim(throw):/
1188 let caught = 1
1189 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
1190 finally
1191 Xpath 16 " X: 16
1192 if !caught && !$VIMNOERRTHROW
1193 Xpath 32 " X: 0
1194 endif
1195 if caught ? !MSG('E121', "Undefined variable")
1196 \ : !MSG('E15', "Invalid expression")
1197 Xpath 64 " X: 0
1198 endif
1199 endtry
1200 catch /.*/
1201 Xpath 128 " X: 0
1202 Xout v:exception "in" v:throwpoint
1203 finally
1204 break " discard error for $VIMNOERRTHROW
1205 endtry
1206endwhile
1207
1208while 1
1209 try
1210 try
1211 let caught = 0
1212 throw "Vim:faked" " error: cannot fake Vim exception
1213 catch /^Vim(throw):/
1214 let caught = 1
1215 let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
1216 finally
1217 Xpath 256 " X: 256
1218 if !caught && !$VIMNOERRTHROW
1219 Xpath 512 " X: 0
1220 endif
1221 if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix")
1222 Xpath 1024 " X: 0
1223 endif
1224 endtry
1225 catch /.*/
1226 Xpath 2048 " X: 0
1227 Xout v:exception "in" v:throwpoint
1228 finally
1229 break " discard error for $VIMNOERRTHROW
1230 endtry
1231endwhile
1232
1233function! F()
1234 while 1
1235 " Missing :endwhile
1236endfunction
1237
1238while 1
1239 try
1240 try
1241 let caught = 0
1242 call F()
1243 catch /^Vim(endfunction):/
1244 let caught = 1
1245 let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
1246 finally
1247 Xpath 4096 " X: 4096
1248 if !caught && !$VIMNOERRTHROW
1249 Xpath 8192 " X: 0
1250 endif
1251 if !MSG('E170', "Missing :endwhile")
1252 Xpath 16384 " X: 0
1253 endif
1254 endtry
1255 catch /.*/
1256 Xpath 32768 " X: 0
1257 Xout v:exception "in" v:throwpoint
1258 finally
1259 break " discard error for $VIMNOERRTHROW
1260 endtry
1261endwhile
1262
1263while 1
1264 try
1265 try
1266 let caught = 0
1267 ExecAsScript F
1268 catch /^Vim:/
1269 let caught = 1
1270 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
1271 finally
1272 Xpath 65536 " X: 65536
1273 if !caught && !$VIMNOERRTHROW
1274 Xpath 131072 " X: 0
1275 endif
1276 if !MSG('E170', "Missing :endwhile")
1277 Xpath 262144 " X: 0
1278 endif
1279 endtry
1280 catch /.*/
1281 Xpath 524288 " X: 0
1282 Xout v:exception "in" v:throwpoint
1283 finally
1284 break " discard error for $VIMNOERRTHROW
1285 endtry
1286endwhile
1287
1288function! G()
1289 call G()
1290endfunction
1291
1292while 1
1293 try
1294 let mfd_save = &mfd
1295 set mfd=3
1296 try
1297 let caught = 0
1298 call G()
1299 catch /^Vim(call):/
1300 let caught = 1
1301 let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
1302 finally
1303 Xpath 1048576 " X: 1048576
1304 if !caught && !$VIMNOERRTHROW
1305 Xpath 2097152 " X: 0
1306 endif
1307 if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
1308 Xpath 4194304 " X: 0
1309 endif
1310 endtry
1311 catch /.*/
1312 Xpath 8388608 " X: 0
1313 Xout v:exception "in" v:throwpoint
1314 finally
1315 let &mfd = mfd_save
1316 break " discard error for $VIMNOERRTHROW
1317 endtry
1318endwhile
1319
1320function! H()
1321 return H()
1322endfunction
1323
1324while 1
1325 try
1326 let mfd_save = &mfd
1327 set mfd=3
1328 try
1329 let caught = 0
1330 call H()
1331 catch /^Vim(return):/
1332 let caught = 1
1333 let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
1334 finally
1335 Xpath 16777216 " X: 16777216
1336 if !caught && !$VIMNOERRTHROW
1337 Xpath 33554432 " X: 0
1338 endif
1339 if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
1340 Xpath 67108864 " X: 0
1341 endif
1342 endtry
1343 catch /.*/
1344 Xpath 134217728 " X: 0
1345 Xout v:exception "in" v:throwpoint
1346 finally
1347 let &mfd = mfd_save
1348 break " discard error for $VIMNOERRTHROW
1349 endtry
1350endwhile
1351
1352unlet! caught mfd_save
1353delfunction F
1354delfunction G
1355delfunction H
1356Xpath 268435456 " X: 268435456
1357
1358Xcheck 286331153
1359
1360" Leave MSG() for the next test.
1361
1362
1363"-------------------------------------------------------------------------------
1364" Test 63: Suppressing error exceptions by :silent!. {{{1
1365"
1366" A :silent! command inside a :try/:endtry region suppresses the
1367" conversion of errors to an exception and the immediate abortion on
1368" error. When the commands executed by the :silent! themselves open
1369" a new :try/:endtry region, conversion of errors to exception and
1370" immediate abortion is switched on again - until the next :silent!
1371" etc. The :silent! has the effect of setting v:errmsg to the error
1372" message text (without displaying it) and continuing with the next
1373" script line.
1374"
1375" When a command triggering autocommands is executed by :silent!
1376" inside a :try/:endtry, the autocommand execution is not suppressed
1377" on error.
1378"
1379" This test reuses the function MSG() from the previous test.
1380"-------------------------------------------------------------------------------
1381
1382XpathINIT
1383
1384XloopINIT! 1 4
1385
1386let taken = ""
1387
1388function! S(n) abort
1389 XloopNEXT
1390 let g:taken = g:taken . "E" . a:n
1391 let v:errmsg = ""
1392 exec "asdf" . a:n
1393
1394 " Check that ":silent!" continues:
1395 Xloop 1
1396
1397 " Check that ":silent!" sets "v:errmsg":
1398 if MSG('E492', "Not an editor command")
1399 Xloop 2
1400 endif
1401endfunction
1402
1403function! Foo()
1404 while 1
1405 try
1406 try
1407 let caught = 0
1408 " This is not silent:
1409 call S(3) " X: 0 * 16
1410 catch /^Vim:/
1411 let caught = 1
1412 let errmsg3 = substitute(v:exception, '^Vim:', '', "")
1413 silent! call S(4) " X: 3 * 64
1414 finally
1415 if !caught
1416 let errmsg3 = v:errmsg
1417 " Do call S(4) here if not executed in :catch.
1418 silent! call S(4)
1419 endif
1420 Xpath 1048576 " X: 1048576
1421 if !caught && !$VIMNOERRTHROW
1422 Xpath 2097152 " X: 0
1423 endif
1424 let v:errmsg = errmsg3
1425 if !MSG('E492', "Not an editor command")
1426 Xpath 4194304 " X: 0
1427 endif
1428 silent! call S(5) " X: 3 * 256
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001429 " Break out of try conditionals that cover ":silent!". This also
Bram Moolenaar071d4272004-06-13 20:20:40 +00001430 " discards the aborting error when $VIMNOERRTHROW is non-zero.
1431 break
1432 endtry
1433 catch /.*/
1434 Xpath 8388608 " X: 0
1435 Xout v:exception "in" v:throwpoint
1436 endtry
1437 endwhile
1438 " This is a double ":silent!" (see caller).
1439 silent! call S(6) " X: 3 * 1024
1440endfunction
1441
1442function! Bar()
1443 try
1444 silent! call S(2) " X: 3 * 4
1445 " X: 3 * 4096
1446 silent! execute "call Foo() | call S(7)"
1447 silent! call S(8) " X: 3 * 16384
1448 endtry " normal end of try cond that covers ":silent!"
1449 " This has a ":silent!" from the caller:
1450 call S(9) " X: 3 * 65536
1451endfunction
1452
1453silent! call S(1) " X: 3 * 1
1454silent! call Bar()
1455silent! call S(10) " X: 3 * 262144
1456
1457let expected = "E1E2E3E4E5E6E7E8E9E10"
1458if taken != expected
1459 Xpath 16777216 " X: 0
1460 Xout "'taken' is" taken "instead of" expected
1461endif
1462
1463augroup TMP
1464 autocmd BufWritePost * Xpath 33554432 " X: 33554432
1465augroup END
1466
1467Xpath 67108864 " X: 67108864
1468write /i/m/p/o/s/s/i/b/l/e
1469Xpath 134217728 " X: 134217728
1470
1471autocmd! TMP
1472unlet! caught errmsg3 taken expected
1473delfunction S
1474delfunction Foo
1475delfunction Bar
1476delfunction MSG
1477
1478Xcheck 236978127
1479
1480
1481"-------------------------------------------------------------------------------
1482" Test 64: Error exceptions after error, interrupt or :throw {{{1
1483"
1484" When an error occurs after an interrupt or a :throw but before
1485" a matching :catch is reached, all following :catches of that try
1486" block are ignored, but the error exception can be caught by the next
1487" surrounding try conditional. Any previous error exception is
1488" discarded. An error is ignored when there is a previous error that
1489" has not been caught.
1490"-------------------------------------------------------------------------------
1491
1492XpathINIT
1493
1494if ExtraVim()
1495
1496 while 1
1497 try
1498 try
1499 Xpath 1 " X: 1
1500 let caught = 0
1501 while 1
1502" if 1
1503 " Missing :endif
1504 endwhile " throw error exception
1505 catch /^Vim(/
1506 let caught = 1
1507 finally
1508 Xpath 2 " X: 2
1509 if caught || $VIMNOERRTHROW
1510 Xpath 4 " X: 4
1511 endif
1512 endtry
1513 catch /.*/
1514 Xpath 8 " X: 0
1515 Xout v:exception "in" v:throwpoint
1516 finally
1517 break " discard error for $VIMNOERRTHROW
1518 endtry
1519 endwhile
1520
1521 while 1
1522 try
1523 try
1524 Xpath 16 " X: 16
1525 let caught = 0
1526 try
1527" if 1
1528 " Missing :endif
1529 catch /.*/ " throw error exception
1530 Xpath 32 " X: 0
1531 catch /.*/
1532 Xpath 64 " X: 0
1533 endtry
1534 catch /^Vim(/
1535 let caught = 1
1536 finally
1537 Xpath 128 " X: 128
1538 if caught || $VIMNOERRTHROW
1539 Xpath 256 " X: 256
1540 endif
1541 endtry
1542 catch /.*/
1543 Xpath 512 " X: 0
1544 Xout v:exception "in" v:throwpoint
1545 finally
1546 break " discard error for $VIMNOERRTHROW
1547 endtry
1548 endwhile
1549
1550 while 1
1551 try
1552 try
1553 let caught = 0
1554 try
1555 Xpath 1024 " X: 1024
1556 "INTERRUPT
1557 catch /do_not_catch/
1558 Xpath 2048 " X: 0
1559" if 1
1560 " Missing :endif
1561 catch /.*/ " throw error exception
1562 Xpath 4096 " X: 0
1563 catch /.*/
1564 Xpath 8192 " X: 0
1565 endtry
1566 catch /^Vim(/
1567 let caught = 1
1568 finally
1569 Xpath 16384 " X: 16384
1570 if caught || $VIMNOERRTHROW
1571 Xpath 32768 " X: 32768
1572 endif
1573 endtry
1574 catch /.*/
1575 Xpath 65536 " X: 0
1576 Xout v:exception "in" v:throwpoint
1577 finally
1578 break " discard error for $VIMNOERRTHROW
1579 endtry
1580 endwhile
1581
1582 while 1
1583 try
1584 try
1585 let caught = 0
1586 try
1587 Xpath 131072 " X: 131072
1588 throw "x"
1589 catch /do_not_catch/
1590 Xpath 262144 " X: 0
1591" if 1
1592 " Missing :endif
1593 catch /x/ " throw error exception
1594 Xpath 524288 " X: 0
1595 catch /.*/
1596 Xpath 1048576 " X: 0
1597 endtry
1598 catch /^Vim(/
1599 let caught = 1
1600 finally
1601 Xpath 2097152 " X: 2097152
1602 if caught || $VIMNOERRTHROW
1603 Xpath 4194304 " X: 4194304
1604 endif
1605 endtry
1606 catch /.*/
1607 Xpath 8388608 " X: 0
1608 Xout v:exception "in" v:throwpoint
1609 finally
1610 break " discard error for $VIMNOERRTHROW
1611 endtry
1612 endwhile
1613
1614 while 1
1615 try
1616 try
1617 let caught = 0
1618 Xpath 16777216 " X: 16777216
1619" endif " :endif without :if; throw error exception
1620" if 1
1621 " Missing :endif
1622 catch /do_not_catch/ " ignore new error
1623 Xpath 33554432 " X: 0
1624 catch /^Vim(endif):/
1625 let caught = 1
1626 catch /^Vim(/
1627 Xpath 67108864 " X: 0
1628 finally
1629 Xpath 134217728 " X: 134217728
1630 if caught || $VIMNOERRTHROW
1631 Xpath 268435456 " X: 268435456
1632 endif
1633 endtry
1634 catch /.*/
1635 Xpath 536870912 " X: 0
1636 Xout v:exception "in" v:throwpoint
1637 finally
1638 break " discard error for $VIMNOERRTHROW
1639 endtry
1640 endwhile
1641
1642 Xpath 1073741824 " X: 1073741824
1643
1644endif
1645
1646Xcheck 1499645335
1647
Bram Moolenaar9470a4d2020-08-07 16:49:11 +02001648" Test 65 was moved to test_vimscript.vim
1649let Xtest = 66
Bram Moolenaar071d4272004-06-13 20:20:40 +00001650
1651"-------------------------------------------------------------------------------
1652" Test 66: Stop range :call on error, interrupt, or :throw {{{1
1653"
1654" When a function which is multiply called for a range since it
1655" doesn't handle the range itself has an error in a command
1656" dynamically enclosed by :try/:endtry or gets an interrupt or
1657" executes a :throw, no more calls for the remaining lines in the
1658" range are made. On an error in a command not dynamically enclosed
1659" by :try/:endtry, the function is executed again for the remaining
1660" lines in the range.
1661"-------------------------------------------------------------------------------
1662
1663XpathINIT
1664
1665if ExtraVim()
1666
1667 let file = tempname()
1668 exec "edit" file
1669
1670 insert
1671line 1
1672line 2
1673line 3
1674.
1675
1676 XloopINIT! 1 2
1677
1678 let taken = ""
1679 let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
1680
1681 function! F(reason, n) abort
1682 let g:taken = g:taken . "F" . a:n .
1683 \ substitute(a:reason, '\(\l\).*', '\u\1', "") .
1684 \ "(" . line(".") . ")"
1685
1686 if a:reason == "error"
1687 asdf
1688 elseif a:reason == "interrupt"
1689 "INTERRUPT
1690 let dummy = 0
1691 elseif a:reason == "throw"
1692 throw "xyz"
1693 elseif a:reason == "aborting error"
1694 XloopNEXT
1695 if g:taken != g:expected
1696 Xloop 1 " X: 0
1697 Xout "'taken' is" g:taken "instead of" g:expected
1698 endif
1699 try
1700 bwipeout!
1701 call delete(file)
1702 asdf
1703 endtry
1704 endif
1705 endfunction
1706
1707 function! G(reason, n)
1708 let g:taken = g:taken . "G" . a:n .
1709 \ substitute(a:reason, '\(\l\).*', '\u\1', "")
1710 1,3call F(a:reason, a:n)
1711 endfunction
1712
1713 Xpath 8 " X: 8
1714 call G("error", 1)
1715 try
1716 Xpath 16 " X: 16
1717 try
1718 call G("error", 2)
1719 Xpath 32 " X: 0
1720 finally
1721 Xpath 64 " X: 64
1722 try
1723 call G("interrupt", 3)
1724 Xpath 128 " X: 0
1725 finally
1726 Xpath 256 " X: 256
1727 try
1728 call G("throw", 4)
1729 Xpath 512 " X: 0
1730 endtry
1731 endtry
1732 endtry
1733 catch /xyz/
1734 Xpath 1024 " X: 1024
1735 catch /.*/
1736 Xpath 2048 " X: 0
1737 Xout v:exception "in" ExtraVimThrowpoint()
1738 endtry
1739 Xpath 4096 " X: 4096
1740 call G("aborting error", 5)
1741 Xpath 8192 " X: 0
1742 Xout "'taken' is" taken "instead of" expected
1743
1744endif
1745
1746Xcheck 5464
1747
1748
1749"-------------------------------------------------------------------------------
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001750" Test 67: :throw across :call command {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001751"
1752" On a call command, an exception might be thrown when evaluating the
1753" function name, during evaluation of the arguments, or when the
1754" function is being executed. The exception can be caught by the
1755" caller.
1756"-------------------------------------------------------------------------------
1757
1758XpathINIT
1759
1760function! THROW(x, n)
1761 if a:n == 1
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001762 Xpath 1 " X: 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001763 elseif a:n == 2
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001764 Xpath 2 " X: 2
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765 elseif a:n == 3
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001766 Xpath 4 " X: 4
Bram Moolenaar071d4272004-06-13 20:20:40 +00001767 endif
1768 throw a:x
1769endfunction
1770
1771function! NAME(x, n)
1772 if a:n == 1
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001773 Xpath 8 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001774 elseif a:n == 2
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001775 Xpath 16 " X: 16
Bram Moolenaar071d4272004-06-13 20:20:40 +00001776 elseif a:n == 3
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001777 Xpath 32 " X: 32
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778 elseif a:n == 4
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001779 Xpath 64 " X: 64
Bram Moolenaar071d4272004-06-13 20:20:40 +00001780 endif
1781 return a:x
1782endfunction
1783
1784function! ARG(x, n)
1785 if a:n == 1
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001786 Xpath 128 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001787 elseif a:n == 2
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001788 Xpath 256 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001789 elseif a:n == 3
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001790 Xpath 512 " X: 512
Bram Moolenaar071d4272004-06-13 20:20:40 +00001791 elseif a:n == 4
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001792 Xpath 1024 " X: 1024
Bram Moolenaar071d4272004-06-13 20:20:40 +00001793 endif
1794 return a:x
1795endfunction
1796
1797function! F(x, n)
1798 if a:n == 2
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001799 Xpath 2048 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001800 elseif a:n == 4
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001801 Xpath 4096 " X: 4096
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802 endif
1803endfunction
1804
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001805while 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001806 try
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001807 let error = 0
1808 let v:errmsg = ""
Bram Moolenaar071d4272004-06-13 20:20:40 +00001809
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001810 while 1
1811 try
1812 Xpath 8192 " X: 8192
1813 call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
1814 Xpath 16384 " X: 0
1815 catch /^name$/
1816 Xpath 32768 " X: 32768
1817 catch /.*/
1818 let error = 1
1819 Xout "1:" v:exception "in" v:throwpoint
1820 finally
1821 if !error && $VIMNOERRTHROW && v:errmsg != ""
1822 let error = 1
1823 Xout "1:" v:errmsg
1824 endif
1825 if error
1826 Xpath 65536 " X: 0
1827 endif
1828 let error = 0
1829 let v:errmsg = ""
1830 break " discard error for $VIMNOERRTHROW
1831 endtry
1832 endwhile
Bram Moolenaar071d4272004-06-13 20:20:40 +00001833
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001834 while 1
1835 try
1836 Xpath 131072 " X: 131072
1837 call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
1838 Xpath 262144 " X: 0
1839 catch /^arg$/
1840 Xpath 524288 " X: 524288
1841 catch /.*/
1842 let error = 1
1843 Xout "2:" v:exception "in" v:throwpoint
1844 finally
1845 if !error && $VIMNOERRTHROW && v:errmsg != ""
1846 let error = 1
1847 Xout "2:" v:errmsg
1848 endif
1849 if error
1850 Xpath 1048576 " X: 0
1851 endif
1852 let error = 0
1853 let v:errmsg = ""
1854 break " discard error for $VIMNOERRTHROW
1855 endtry
1856 endwhile
1857
1858 while 1
1859 try
1860 Xpath 2097152 " X: 2097152
1861 call {NAME("THROW", 3)}(ARG("call", 3), 3)
1862 Xpath 4194304 " X: 0
1863 catch /^call$/
1864 Xpath 8388608 " X: 8388608
1865 catch /^0$/ " default return value
1866 Xpath 16777216 " X: 0
1867 Xout "3:" v:throwpoint
1868 catch /.*/
1869 let error = 1
1870 Xout "3:" v:exception "in" v:throwpoint
1871 finally
1872 if !error && $VIMNOERRTHROW && v:errmsg != ""
1873 let error = 1
1874 Xout "3:" v:errmsg
1875 endif
1876 if error
1877 Xpath 33554432 " X: 0
1878 endif
1879 let error = 0
1880 let v:errmsg = ""
1881 break " discard error for $VIMNOERRTHROW
1882 endtry
1883 endwhile
1884
1885 while 1
1886 try
1887 Xpath 67108864 " X: 67108864
1888 call {NAME("F", 4)}(ARG(4711, 4), 4)
1889 Xpath 134217728 " X: 134217728
1890 catch /.*/
1891 let error = 1
1892 Xout "4:" v:exception "in" v:throwpoint
1893 finally
1894 if !error && $VIMNOERRTHROW && v:errmsg != ""
1895 let error = 1
1896 Xout "4:" v:errmsg
1897 endif
1898 if error
1899 Xpath 268435456 " X: 0
1900 endif
1901 let error = 0
1902 let v:errmsg = ""
1903 break " discard error for $VIMNOERRTHROW
1904 endtry
1905 endwhile
1906
Bram Moolenaar071d4272004-06-13 20:20:40 +00001907 catch /^0$/ " default return value
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001908 Xpath 536870912 " X: 0
1909 Xout v:throwpoint
Bram Moolenaar071d4272004-06-13 20:20:40 +00001910 catch /.*/
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001911 let error = 1
1912 Xout v:exception "in" v:throwpoint
1913 finally
1914 if !error && $VIMNOERRTHROW && v:errmsg != ""
1915 let error = 1
1916 Xout v:errmsg
1917 endif
1918 if error
1919 Xpath 1073741824 " X: 0
1920 endif
1921 break " discard error for $VIMNOERRTHROW
Bram Moolenaar071d4272004-06-13 20:20:40 +00001922 endtry
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001923endwhile
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001925unlet error
Bram Moolenaar071d4272004-06-13 20:20:40 +00001926delfunction F
1927
1928Xcheck 212514423
1929
1930" Leave THROW(), NAME(), and ARG() for the next test.
1931
1932
1933"-------------------------------------------------------------------------------
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001934" Test 68: :throw across function calls in expressions {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935"
1936" On a function call within an expression, an exception might be
1937" thrown when evaluating the function name, during evaluation of the
1938" arguments, or when the function is being executed. The exception
1939" can be caught by the caller.
1940"
1941" This test reuses the functions THROW(), NAME(), and ARG() from the
1942" previous test.
1943"-------------------------------------------------------------------------------
1944
1945XpathINIT
1946
1947function! F(x, n)
1948 if a:n == 2
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001949 Xpath 2048 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00001950 elseif a:n == 4
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001951 Xpath 4096 " X: 4096
Bram Moolenaar071d4272004-06-13 20:20:40 +00001952 endif
1953 return a:x
1954endfunction
1955
1956unlet! var1 var2 var3 var4
1957
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001958while 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00001959 try
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001960 let error = 0
1961 let v:errmsg = ""
Bram Moolenaar071d4272004-06-13 20:20:40 +00001962
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001963 while 1
1964 try
1965 Xpath 8192 " X: 8192
1966 let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
1967 Xpath 16384 " X: 0
1968 catch /^name$/
1969 Xpath 32768 " X: 32768
1970 catch /.*/
1971 let error = 1
1972 Xout "1:" v:exception "in" v:throwpoint
1973 finally
1974 if !error && $VIMNOERRTHROW && v:errmsg != ""
1975 let error = 1
1976 Xout "1:" v:errmsg
1977 endif
1978 if error
1979 Xpath 65536 " X: 0
1980 endif
1981 let error = 0
1982 let v:errmsg = ""
1983 break " discard error for $VIMNOERRTHROW
1984 endtry
1985 endwhile
Bram Moolenaar071d4272004-06-13 20:20:40 +00001986
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00001987 while 1
1988 try
1989 Xpath 131072 " X: 131072
1990 let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
1991 Xpath 262144 " X: 0
1992 catch /^arg$/
1993 Xpath 524288 " X: 524288
1994 catch /.*/
1995 let error = 1
1996 Xout "2:" v:exception "in" v:throwpoint
1997 finally
1998 if !error && $VIMNOERRTHROW && v:errmsg != ""
1999 let error = 1
2000 Xout "2:" v:errmsg
2001 endif
2002 if error
2003 Xpath 1048576 " X: 0
2004 endif
2005 let error = 0
2006 let v:errmsg = ""
2007 break " discard error for $VIMNOERRTHROW
2008 endtry
2009 endwhile
2010
2011 while 1
2012 try
2013 Xpath 2097152 " X: 2097152
2014 let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
2015 Xpath 4194304 " X: 0
2016 catch /^call$/
2017 Xpath 8388608 " X: 8388608
2018 catch /^0$/ " default return value
2019 Xpath 16777216 " X: 0
2020 Xout "3:" v:throwpoint
2021 catch /.*/
2022 let error = 1
2023 Xout "3:" v:exception "in" v:throwpoint
2024 finally
2025 if !error && $VIMNOERRTHROW && v:errmsg != ""
2026 let error = 1
2027 Xout "3:" v:errmsg
2028 endif
2029 if error
2030 Xpath 33554432 " X: 0
2031 endif
2032 let error = 0
2033 let v:errmsg = ""
2034 break " discard error for $VIMNOERRTHROW
2035 endtry
2036 endwhile
2037
2038 while 1
2039 try
2040 Xpath 67108864 " X: 67108864
2041 let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
2042 Xpath 134217728 " X: 134217728
2043 catch /.*/
2044 let error = 1
2045 Xout "4:" v:exception "in" v:throwpoint
2046 finally
2047 if !error && $VIMNOERRTHROW && v:errmsg != ""
2048 let error = 1
2049 Xout "4:" v:errmsg
2050 endif
2051 if error
2052 Xpath 268435456 " X: 0
2053 endif
2054 let error = 0
2055 let v:errmsg = ""
2056 break " discard error for $VIMNOERRTHROW
2057 endtry
2058 endwhile
2059
Bram Moolenaar071d4272004-06-13 20:20:40 +00002060 catch /^0$/ " default return value
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002061 Xpath 536870912 " X: 0
2062 Xout v:throwpoint
Bram Moolenaar071d4272004-06-13 20:20:40 +00002063 catch /.*/
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002064 let error = 1
2065 Xout v:exception "in" v:throwpoint
2066 finally
2067 if !error && $VIMNOERRTHROW && v:errmsg != ""
2068 let error = 1
2069 Xout v:errmsg
2070 endif
2071 if error
2072 Xpath 1073741824 " X: 0
2073 endif
2074 break " discard error for $VIMNOERRTHROW
Bram Moolenaar071d4272004-06-13 20:20:40 +00002075 endtry
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002076endwhile
Bram Moolenaar071d4272004-06-13 20:20:40 +00002077
2078if exists("var1") || exists("var2") || exists("var3") ||
2079 \ !exists("var4") || var4 != 4711
2080 " The Xpath command does not accept 2^31 (negative); add explicitly:
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002081 let Xpath = Xpath + 2147483648 " X: 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00002082 if exists("var1")
2083 Xout "var1 =" var1
2084 endif
2085 if exists("var2")
2086 Xout "var2 =" var2
2087 endif
2088 if exists("var3")
2089 Xout "var3 =" var3
2090 endif
2091 if !exists("var4")
2092 Xout "var4 unset"
2093 elseif var4 != 4711
2094 Xout "var4 =" var4
2095 endif
2096endif
2097
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002098unlet! error var1 var2 var3 var4
Bram Moolenaar071d4272004-06-13 20:20:40 +00002099delfunction THROW
2100delfunction NAME
2101delfunction ARG
2102delfunction F
2103
2104Xcheck 212514423
2105
Bram Moolenaar1f068232019-11-03 16:17:26 +01002106" Tests 69 to 75 were moved to test_trycatch.vim
2107let Xtest = 76
Bram Moolenaar071d4272004-06-13 20:20:40 +00002108
2109
2110"-------------------------------------------------------------------------------
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002111" Test 76: Errors, interrupts, :throw during expression evaluation {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00002112"
2113" When a function call made during expression evaluation is aborted
2114" due to an error inside a :try/:endtry region or due to an interrupt
2115" or a :throw, the expression evaluation is aborted as well. No
2116" message is displayed for the cancelled expression evaluation. On an
2117" error not inside :try/:endtry, the expression evaluation continues.
2118"-------------------------------------------------------------------------------
2119
2120XpathINIT
2121
2122if ExtraVim()
2123
2124 let taken = ""
2125
2126 function! ERR(n)
2127 let g:taken = g:taken . "E" . a:n
2128 asdf
2129 endfunction
2130
2131 function! ERRabort(n) abort
2132 let g:taken = g:taken . "A" . a:n
2133 asdf
Bram Moolenaare13305e2005-06-19 22:54:15 +00002134 endfunction " returns -1; may cause follow-up msg for illegal var/func name
2135
2136 function! WRAP(n, arg)
2137 let g:taken = g:taken . "W" . a:n
2138 let g:saved_errmsg = v:errmsg
2139 return arg
2140 endfunction
Bram Moolenaar071d4272004-06-13 20:20:40 +00002141
2142 function! INT(n)
2143 let g:taken = g:taken . "I" . a:n
2144 "INTERRUPT9
2145 let dummy = 0
2146 endfunction
2147
2148 function! THR(n)
2149 let g:taken = g:taken . "T" . a:n
2150 throw "should not be caught"
2151 endfunction
2152
2153 function! CONT(n)
2154 let g:taken = g:taken . "C" . a:n
2155 endfunction
2156
2157 function! MSG(n)
2158 let g:taken = g:taken . "M" . a:n
Bram Moolenaare13305e2005-06-19 22:54:15 +00002159 let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
2160 let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
2161 if errmsg !~ msgptn
2162 let g:taken = g:taken . "x"
2163 Xout "Expr" a:n.": Unexpected message:" v:errmsg
Bram Moolenaar071d4272004-06-13 20:20:40 +00002164 endif
2165 let v:errmsg = ""
Bram Moolenaare13305e2005-06-19 22:54:15 +00002166 let g:saved_errmsg = ""
Bram Moolenaar071d4272004-06-13 20:20:40 +00002167 endfunction
2168
2169 let v:errmsg = ""
2170
2171 try
2172 let t = 1
2173 XloopINIT 1 2
2174 while t <= 9
2175 Xloop 1 " X: 511
2176 try
2177 if t == 1
2178 let v{ERR(t) + CONT(t)} = 0
2179 elseif t == 2
2180 let v{ERR(t) + CONT(t)}
2181 elseif t == 3
2182 let var = exists('v{ERR(t) + CONT(t)}')
2183 elseif t == 4
2184 unlet v{ERR(t) + CONT(t)}
2185 elseif t == 5
2186 function F{ERR(t) + CONT(t)}()
2187 endfunction
2188 elseif t == 6
2189 function F{ERR(t) + CONT(t)}
2190 elseif t == 7
2191 let var = exists('*F{ERR(t) + CONT(t)}')
2192 elseif t == 8
2193 delfunction F{ERR(t) + CONT(t)}
2194 elseif t == 9
2195 let var = ERR(t) + CONT(t)
2196 endif
2197 catch /asdf/
2198 " v:errmsg is not set when the error message is converted to an
2199 " exception. Set it to the original error message.
2200 let v:errmsg = substitute(v:exception, '^Vim:', '', "")
2201 catch /^Vim\((\a\+)\)\=:/
2202 " An error exception has been thrown after the original error.
2203 let v:errmsg = ""
2204 finally
2205 call MSG(t)
2206 let t = t + 1
2207 XloopNEXT
2208 continue " discard an aborting error
2209 endtry
2210 endwhile
2211 catch /.*/
2212 Xpath 512 " X: 0
2213 Xout v:exception "in" ExtraVimThrowpoint()
2214 endtry
2215
2216 try
2217 let t = 10
2218 XloopINIT 1024 2
2219 while t <= 18
2220 Xloop 1 " X: 1024 * 511
2221 try
2222 if t == 10
2223 let v{INT(t) + CONT(t)} = 0
2224 elseif t == 11
2225 let v{INT(t) + CONT(t)}
2226 elseif t == 12
2227 let var = exists('v{INT(t) + CONT(t)}')
2228 elseif t == 13
2229 unlet v{INT(t) + CONT(t)}
2230 elseif t == 14
2231 function F{INT(t) + CONT(t)}()
2232 endfunction
2233 elseif t == 15
2234 function F{INT(t) + CONT(t)}
2235 elseif t == 16
2236 let var = exists('*F{INT(t) + CONT(t)}')
2237 elseif t == 17
2238 delfunction F{INT(t) + CONT(t)}
2239 elseif t == 18
2240 let var = INT(t) + CONT(t)
2241 endif
2242 catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
2243 " An error exception has been triggered after the interrupt.
2244 let v:errmsg = substitute(v:exception,
2245 \ '^Vim\((\a\+)\)\=:', '', "")
2246 finally
2247 call MSG(t)
2248 let t = t + 1
2249 XloopNEXT
2250 continue " discard interrupt
2251 endtry
2252 endwhile
2253 catch /.*/
2254 Xpath 524288 " X: 0
2255 Xout v:exception "in" ExtraVimThrowpoint()
2256 endtry
2257
2258 try
2259 let t = 19
2260 XloopINIT 1048576 2
2261 while t <= 27
2262 Xloop 1 " X: 1048576 * 511
2263 try
2264 if t == 19
2265 let v{THR(t) + CONT(t)} = 0
2266 elseif t == 20
2267 let v{THR(t) + CONT(t)}
2268 elseif t == 21
2269 let var = exists('v{THR(t) + CONT(t)}')
2270 elseif t == 22
2271 unlet v{THR(t) + CONT(t)}
2272 elseif t == 23
2273 function F{THR(t) + CONT(t)}()
2274 endfunction
2275 elseif t == 24
2276 function F{THR(t) + CONT(t)}
2277 elseif t == 25
2278 let var = exists('*F{THR(t) + CONT(t)}')
2279 elseif t == 26
2280 delfunction F{THR(t) + CONT(t)}
2281 elseif t == 27
2282 let var = THR(t) + CONT(t)
2283 endif
2284 catch /^Vim\((\a\+)\)\=:/
2285 " An error exception has been triggered after the :throw.
2286 let v:errmsg = substitute(v:exception,
2287 \ '^Vim\((\a\+)\)\=:', '', "")
2288 finally
2289 call MSG(t)
2290 let t = t + 1
2291 XloopNEXT
2292 continue " discard exception
2293 endtry
2294 endwhile
2295 catch /.*/
2296 Xpath 536870912 " X: 0
2297 Xout v:exception "in" ExtraVimThrowpoint()
2298 endtry
2299
2300 let v{ERR(28) + CONT(28)} = 0
2301 call MSG(28)
2302 let v{ERR(29) + CONT(29)}
2303 call MSG(29)
2304 let var = exists('v{ERR(30) + CONT(30)}')
2305 call MSG(30)
2306 unlet v{ERR(31) + CONT(31)}
2307 call MSG(31)
2308 function F{ERR(32) + CONT(32)}()
2309 endfunction
2310 call MSG(32)
2311 function F{ERR(33) + CONT(33)}
2312 call MSG(33)
2313 let var = exists('*F{ERR(34) + CONT(34)}')
2314 call MSG(34)
2315 delfunction F{ERR(35) + CONT(35)}
2316 call MSG(35)
2317 let var = ERR(36) + CONT(36)
2318 call MSG(36)
2319
Bram Moolenaare13305e2005-06-19 22:54:15 +00002320 let saved_errmsg = ""
2321
2322 let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00002323 call MSG(37)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002324 let v{WRAP(38, ERRabort(38)) + CONT(38)}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002325 call MSG(38)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002326 let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002327 call MSG(39)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002328 unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002329 call MSG(40)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002330 function F{WRAP(41, ERRabort(41)) + CONT(41)}()
Bram Moolenaar071d4272004-06-13 20:20:40 +00002331 endfunction
2332 call MSG(41)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002333 function F{WRAP(42, ERRabort(42)) + CONT(42)}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002334 call MSG(42)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002335 let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002336 call MSG(43)
Bram Moolenaare13305e2005-06-19 22:54:15 +00002337 delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002338 call MSG(44)
2339 let var = ERRabort(45) + CONT(45)
2340 call MSG(45)
2341
2342 Xpath 1073741824 " X: 1073741824
2343
2344 let expected = ""
2345 \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
2346 \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
2347 \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
2348 \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
2349 \ . "E34C34M34E35C35M35E36C36M36"
Bram Moolenaare13305e2005-06-19 22:54:15 +00002350 \ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
2351 \ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
Bram Moolenaar071d4272004-06-13 20:20:40 +00002352
2353 if taken != expected
2354 " The Xpath command does not accept 2^31 (negative); display explicitly:
2355 exec "!echo 2147483648 >>" . g:ExtraVimResult
2356 " X: 0
2357 Xout "'taken' is" taken "instead of" expected
2358 if substitute(taken,
2359 \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)',
2360 \ '\1E3M3\2E30C30M30\3A39C39M39\4',
2361 \ "") == expected
2362 Xout "Is ++emsg_skip for var with expr_start non-NULL"
2363 \ "in f_exists ok?"
2364 endif
2365 endif
2366
Bram Moolenaare13305e2005-06-19 22:54:15 +00002367 unlet! v var saved_errmsg taken expected
Bram Moolenaar071d4272004-06-13 20:20:40 +00002368 call delete(WA_t5)
2369 call delete(WA_t14)
2370 call delete(WA_t23)
2371 unlet! WA_t5 WA_t14 WA_t23
2372 delfunction WA_t5
2373 delfunction WA_t14
2374 delfunction WA_t23
2375
2376endif
2377
2378Xcheck 1610087935
2379
2380
2381"-------------------------------------------------------------------------------
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002382" Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00002383"
2384" When a function call made during evaluation of an expression in
2385" braces as part of a function name after ":function" is aborted due
2386" to an error inside a :try/:endtry region or due to an interrupt or
2387" a :throw, the expression evaluation is aborted as well, and the
2388" function definition is ignored, skipping all commands to the
2389" ":endfunction". On an error not inside :try/:endtry, the expression
2390" evaluation continues and the function gets defined, and can be
2391" called and deleted.
2392"-------------------------------------------------------------------------------
2393
2394XpathINIT
2395
2396XloopINIT 1 4
2397
2398function! ERR() abort
2399 Xloop 1 " X: 1 + 4 + 16 + 64
2400 asdf
2401endfunction " returns -1
2402
2403function! OK()
2404 Xloop 2 " X: 2 * (1 + 4 + 16)
2405 let v:errmsg = ""
2406 return 0
2407endfunction
2408
2409let v:errmsg = ""
2410
2411Xpath 4096 " X: 4096
2412function! F{1 + ERR() + OK()}(arg)
2413 " F0 should be defined.
2414 if exists("a:arg") && a:arg == "calling"
2415 Xpath 8192 " X: 8192
2416 else
2417 Xpath 16384 " X: 0
2418 endif
2419endfunction
2420if v:errmsg != ""
2421 Xpath 32768 " X: 0
2422endif
2423XloopNEXT
2424
2425Xpath 65536 " X: 65536
2426call F{1 + ERR() + OK()}("calling")
2427if v:errmsg != ""
2428 Xpath 131072 " X: 0
2429endif
2430XloopNEXT
2431
2432Xpath 262144 " X: 262144
2433delfunction F{1 + ERR() + OK()}
2434if v:errmsg != ""
2435 Xpath 524288 " X: 0
2436endif
2437XloopNEXT
2438
2439try
2440 while 1
2441 let caught = 0
2442 try
2443 Xpath 1048576 " X: 1048576
2444 function! G{1 + ERR() + OK()}(arg)
2445 " G0 should not be defined, and the function body should be
2446 " skipped.
2447 if exists("a:arg") && a:arg == "calling"
2448 Xpath 2097152 " X: 0
2449 else
2450 Xpath 4194304 " X: 0
2451 endif
2452 " Use an unmatched ":finally" to check whether the body is
2453 " skipped when an error occurs in ERR(). This works whether or
2454 " not the exception is converted to an exception.
2455 finally
2456 Xpath 8388608 " X: 0
2457 Xout "Body of G{1 + ERR() + OK()}() not skipped"
2458 " Discard the aborting error or exception, and break the
2459 " while loop.
2460 break
2461 " End the try conditional and start a new one to avoid
2462 " ":catch after :finally" errors.
2463 endtry
2464 try
2465 Xpath 16777216 " X: 0
2466 endfunction
2467
2468 " When the function was not defined, this won't be reached - whether
2469 " the body was skipped or not. When the function was defined, it
2470 " can be called and deleted here.
2471 Xpath 33554432 " X: 0
2472 Xout "G0() has been defined"
2473 XloopNEXT
2474 try
2475 call G{1 + ERR() + OK()}("calling")
2476 catch /.*/
2477 Xpath 67108864 " X: 0
2478 endtry
2479 Xpath 134217728 " X: 0
2480 XloopNEXT
2481 try
2482 delfunction G{1 + ERR() + OK()}
2483 catch /.*/
2484 Xpath 268435456 " X: 0
2485 endtry
2486 catch /asdf/
2487 " Jumped to when the function is not defined and the body is
2488 " skipped.
2489 let caught = 1
2490 catch /.*/
2491 Xpath 536870912 " X: 0
2492 finally
2493 if !caught && !$VIMNOERRTHROW
2494 Xpath 1073741824 " X: 0
2495 endif
2496 break " discard error for $VIMNOERRTHROW
2497 endtry " jumped to when the body is not skipped
2498 endwhile
2499catch /.*/
2500 " The Xpath command does not accept 2^31 (negative); add explicitly:
2501 let Xpath = Xpath + 2147483648 " X: 0
2502 Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught"
2503 Xout v:exception "in" v:throwpoint
2504endtry
2505
2506Xcheck 1388671
2507
2508
2509"-------------------------------------------------------------------------------
2510" Test 78: Messages on parsing errors in expression evaluation {{{1
2511"
2512" When an expression evaluation detects a parsing error, an error
2513" message is given and converted to an exception, and the expression
2514" evaluation is aborted.
2515"-------------------------------------------------------------------------------
2516
2517XpathINIT
2518
2519if ExtraVim()
2520
2521 let taken = ""
2522
2523 function! F(n)
2524 let g:taken = g:taken . "F" . a:n
2525 endfunction
2526
2527 function! MSG(n, enr, emsg)
2528 let g:taken = g:taken . "M" . a:n
2529 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
2530 if a:enr == ""
2531 Xout "TODO: Add message number for:" a:emsg
2532 let v:errmsg = ":" . v:errmsg
2533 endif
2534 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
2535 if v:errmsg == ""
2536 Xout "Expr" a:n.": Message missing."
2537 let g:taken = g:taken . "x"
2538 else
2539 let v:errmsg = escape(v:errmsg, '"')
2540 Xout "Expr" a:n.": Unexpected message:" v:errmsg
Bram Moolenaar383f9bc2005-01-19 22:18:32 +00002541 Xout "Expected: " . a:enr . ': ' . a:emsg
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542 let g:taken = g:taken . "X"
2543 endif
2544 endif
2545 endfunction
2546
2547 function! CONT(n)
2548 let g:taken = g:taken . "C" . a:n
2549 endfunction
2550
2551 let v:errmsg = ""
2552 XloopINIT 1 2
2553
2554 try
2555 let t = 1
2556 while t <= 14
2557 let g:taken = g:taken . "T" . t
2558 let v:errmsg = ""
2559 try
2560 let caught = 0
2561 if t == 1
2562 let v{novar + CONT(t)} = 0
2563 elseif t == 2
2564 let v{novar + CONT(t)}
2565 elseif t == 3
2566 let var = exists('v{novar + CONT(t)}')
2567 elseif t == 4
2568 unlet v{novar + CONT(t)}
2569 elseif t == 5
2570 function F{novar + CONT(t)}()
2571 endfunction
2572 elseif t == 6
2573 function F{novar + CONT(t)}
2574 elseif t == 7
2575 let var = exists('*F{novar + CONT(t)}')
2576 elseif t == 8
2577 delfunction F{novar + CONT(t)}
2578 elseif t == 9
2579 echo novar + CONT(t)
2580 elseif t == 10
2581 echo v{novar + CONT(t)}
2582 elseif t == 11
2583 echo F{novar + CONT(t)}
2584 elseif t == 12
2585 let var = novar + CONT(t)
2586 elseif t == 13
2587 let var = v{novar + CONT(t)}
2588 elseif t == 14
2589 let var = F{novar + CONT(t)}()
2590 endif
2591 catch /^Vim\((\a\+)\)\=:/
2592 " v:errmsg is not set when the error message is converted to an
2593 " exception. Set it to the original error message.
2594 let v:errmsg = substitute(v:exception,
2595 \ '^Vim\((\a\+)\)\=:', '', "")
2596 let caught = 1
2597 finally
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002598 if t <= 8 && t != 3 && t != 7
2599 call MSG(t, 'E475', 'Invalid argument\>')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 else
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00002601 if !caught " no error exceptions ($VIMNOERRTHROW set)
2602 call MSG(t, 'E15', "Invalid expression")
Bram Moolenaar071d4272004-06-13 20:20:40 +00002603 else
2604 call MSG(t, 'E121', "Undefined variable")
2605 endif
2606 endif
2607 let t = t + 1
2608 XloopNEXT
2609 continue " discard an aborting error
2610 endtry
2611 endwhile
2612 catch /.*/
2613 Xloop 1 " X: 0
2614 Xout t.":" v:exception "in" ExtraVimThrowpoint()
2615 endtry
2616
2617 function! T(n, expr, enr, emsg)
2618 try
2619 let g:taken = g:taken . "T" . a:n
2620 let v:errmsg = ""
2621 try
2622 let caught = 0
2623 execute "let var = " . a:expr
2624 catch /^Vim\((\a\+)\)\=:/
2625 " v:errmsg is not set when the error message is converted to an
2626 " exception. Set it to the original error message.
2627 let v:errmsg = substitute(v:exception,
2628 \ '^Vim\((\a\+)\)\=:', '', "")
2629 let caught = 1
2630 finally
2631 if !caught " no error exceptions ($VIMNOERRTHROW set)
2632 call MSG(a:n, 'E15', "Invalid expression")
2633 else
2634 call MSG(a:n, a:enr, a:emsg)
2635 endif
2636 XloopNEXT
2637 " Discard an aborting error:
2638 return
2639 endtry
2640 catch /.*/
2641 Xloop 1 " X: 0
2642 Xout a:n.":" v:exception "in" ExtraVimThrowpoint()
2643 endtry
2644 endfunction
2645
2646 call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function")
2647 call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments")
2648 call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments")
2649 call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments")
2650 call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
2651 call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
2652 call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
2653 call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
2654 call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
2655 call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
2656 call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
Bram Moolenaar2fda12f2005-01-15 22:14:15 +00002657 call T(26, '& + CONT(26)', 'E112', "Option name missing")
Bram Moolenaar071d4272004-06-13 20:20:40 +00002658 call T(27, '&asdf + CONT(27)', 'E113', "Unknown option")
2659
2660 Xpath 134217728 " X: 134217728
2661
2662 let expected = ""
2663 \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
2664 \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
2665 \ . "T26M26T27M27"
2666
2667 if taken != expected
2668 Xpath 268435456 " X: 0
2669 Xout "'taken' is" taken "instead of" expected
2670 if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected
2671 Xout "Is ++emsg_skip for var with expr_start non-NULL"
2672 \ "in f_exists ok?"
2673 endif
2674 endif
2675
2676 unlet! var caught taken expected
2677 call delete(WA_t5)
2678 unlet! WA_t5
2679 delfunction WA_t5
2680
2681endif
2682
2683Xcheck 134217728
2684
2685
2686"-------------------------------------------------------------------------------
2687" Test 79: Throwing one of several errors for the same command {{{1
2688"
2689" When several errors appear in a row (for instance during expression
2690" evaluation), the first as the most specific one is used when
2691" throwing an error exception. If, however, a syntax error is
2692" detected afterwards, this one is used for the error exception.
2693" On a syntax error, the next command is not executed, on a normal
2694" error, however, it is (relevant only in a function without the
2695" "abort" flag). v:errmsg is not set.
2696"
2697" If throwing error exceptions is configured off, v:errmsg is always
2698" set to the latest error message, that is, to the more general
2699" message or the syntax error, respectively.
2700"-------------------------------------------------------------------------------
2701
2702XpathINIT
2703
2704XloopINIT 1 2
2705
2706function! NEXT(cmd)
2707 exec a:cmd . " | Xloop 1"
2708endfunction
2709
2710call NEXT('echo novar') " X: 1 * 1 (checks nextcmd)
2711XloopNEXT
2712call NEXT('let novar #') " X: 0 * 2 (skips nextcmd)
2713XloopNEXT
2714call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd)
2715XloopNEXT
2716call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd)
2717XloopNEXT
2718call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd)
2719
2720function! EXEC(cmd)
2721 exec a:cmd
2722endfunction
2723
2724function! MATCH(expected, msg, enr, emsg)
2725 let msg = a:msg
2726 if a:enr == ""
2727 Xout "TODO: Add message number for:" a:emsg
2728 let msg = ":" . msg
2729 endif
2730 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
2731 if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg)
2732 let match = 0
2733 if a:expected " no match although expected
2734 if a:msg == ""
2735 Xout "Message missing."
2736 else
2737 let msg = escape(msg, '"')
2738 Xout "Unexpected message:" msg
Bram Moolenaar9cd15162005-01-16 22:02:49 +00002739 Xout "Expected:" a:enr . ": " . a:emsg
Bram Moolenaar071d4272004-06-13 20:20:40 +00002740 endif
2741 endif
2742 else
2743 let match = 1
2744 if !a:expected " match although not expected
2745 let msg = escape(msg, '"')
2746 Xout "Unexpected message:" msg
Bram Moolenaar9cd15162005-01-16 22:02:49 +00002747 Xout "Expected none."
Bram Moolenaar071d4272004-06-13 20:20:40 +00002748 endif
2749 endif
2750 return match
2751endfunction
2752
2753try
2754
2755 while 1 " dummy loop
2756 try
2757 let v:errmsg = ""
2758 let caught = 0
2759 let thrmsg = ""
2760 call EXEC('echo novar') " normal error
2761 catch /^Vim\((\a\+)\)\=:/
2762 let caught = 1
2763 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
2764 finally
2765 Xpath 32 " X: 32
2766 if !caught
2767 if !$VIMNOERRTHROW
2768 Xpath 64 " X: 0
2769 endif
2770 elseif !MATCH(1, thrmsg, 'E121', "Undefined variable")
2771 \ || v:errmsg != ""
2772 Xpath 128 " X: 0
2773 endif
2774 if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression")
2775 Xpath 256 " X: 0
2776 endif
2777 break " discard error if $VIMNOERRTHROW == 1
2778 endtry
2779 endwhile
2780
2781 Xpath 512 " X: 512
2782 let cmd = "let"
2783 XloopINIT 1024 32
2784 while cmd != ""
2785 try
2786 let v:errmsg = ""
2787 let caught = 0
2788 let thrmsg = ""
2789 call EXEC(cmd . ' novar #') " normal plus syntax error
2790 catch /^Vim\((\a\+)\)\=:/
2791 let caught = 1
2792 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
2793 finally
2794 Xloop 1 " X: 1024 * (1 + 32)
2795 if !caught
2796 if !$VIMNOERRTHROW
2797 Xloop 2 " X: 0
2798 endif
2799 else
2800 if cmd == "let"
Bram Moolenaar39676922010-09-29 16:55:49 +02002801 let match = MATCH(0, thrmsg, 'E121', "Undefined variable")
Bram Moolenaar071d4272004-06-13 20:20:40 +00002802 elseif cmd == "unlet"
2803 let match = MATCH(0, thrmsg, 'E108', "No such variable")
2804 endif
2805 if match " normal error
2806 Xloop 4 " X: 0
2807 endif
2808 if !MATCH(1, thrmsg, 'E488', "Trailing characters")
2809 \|| v:errmsg != ""
2810 " syntax error
2811 Xloop 8 " X: 0
2812 endif
2813 endif
2814 if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters")
2815 " last error
2816 Xloop 16 " X: 0
2817 endif
2818 if cmd == "let"
2819 let cmd = "unlet"
2820 else
2821 let cmd = ""
2822 endif
2823 XloopNEXT
2824 continue " discard error if $VIMNOERRTHROW == 1
2825 endtry
2826 endwhile
2827
2828 Xpath 1048576 " X: 1048576
2829 let cmd = "let"
2830 XloopINIT 2097152 32
2831 while cmd != ""
2832 try
2833 let v:errmsg = ""
2834 let caught = 0
2835 let thrmsg = ""
2836 call EXEC(cmd . ' {novar}') " normal plus syntax error
2837 catch /^Vim\((\a\+)\)\=:/
2838 let caught = 1
2839 let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
2840 finally
2841 Xloop 1 " X: 2097152 * (1 + 32)
2842 if !caught
2843 if !$VIMNOERRTHROW
2844 Xloop 2 " X: 0
2845 endif
2846 else
2847 if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error
2848 Xloop 4 " X: 0
2849 endif
2850 if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>')
2851 \ || v:errmsg != "" " syntax error
2852 Xloop 8 " X: 0
2853 endif
2854 endif
2855 if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>')
2856 " last error
2857 Xloop 16 " X: 0
2858 endif
2859 if cmd == "let"
2860 let cmd = "unlet"
2861 else
2862 let cmd = ""
2863 endif
2864 XloopNEXT
2865 continue " discard error if $VIMNOERRTHROW == 1
2866 endtry
2867 endwhile
2868
2869catch /.*/
2870 " The Xpath command does not accept 2^31 (negative); add explicitly:
2871 let Xpath = Xpath + 2147483648 " X: 0
2872 Xout v:exception "in" v:throwpoint
2873endtry
2874
2875unlet! next_command thrmsg match
2876delfunction NEXT
2877delfunction EXEC
2878delfunction MATCH
2879
2880Xcheck 70288929
2881
2882
2883"-------------------------------------------------------------------------------
2884" Test 80: Syntax error in expression for illegal :elseif {{{1
2885"
2886" If there is a syntax error in the expression after an illegal
2887" :elseif, an error message is given (or an error exception thrown)
2888" for the illegal :elseif rather than the expression error.
2889"-------------------------------------------------------------------------------
2890
2891XpathINIT
2892
2893function! MSG(enr, emsg)
2894 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
2895 if a:enr == ""
2896 Xout "TODO: Add message number for:" a:emsg
2897 let v:errmsg = ":" . v:errmsg
2898 endif
2899 let match = 1
2900 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
2901 let match = 0
2902 if v:errmsg == ""
2903 Xout "Message missing."
2904 else
2905 let v:errmsg = escape(v:errmsg, '"')
2906 Xout "Unexpected message:" v:errmsg
2907 endif
2908 endif
2909 return match
2910endfunction
2911
2912let v:errmsg = ""
2913if 0
2914else
2915elseif 1 ||| 2
2916endif
2917Xpath 1 " X: 1
2918if !MSG('E584', ":elseif after :else")
2919 Xpath 2 " X: 0
2920endif
2921
2922let v:errmsg = ""
2923if 1
2924else
2925elseif 1 ||| 2
2926endif
2927Xpath 4 " X: 4
2928if !MSG('E584', ":elseif after :else")
2929 Xpath 8 " X: 0
2930endif
2931
2932let v:errmsg = ""
2933elseif 1 ||| 2
2934Xpath 16 " X: 16
2935if !MSG('E582', ":elseif without :if")
2936 Xpath 32 " X: 0
2937endif
2938
2939let v:errmsg = ""
2940while 1
2941 elseif 1 ||| 2
2942endwhile
2943Xpath 64 " X: 64
2944if !MSG('E582', ":elseif without :if")
2945 Xpath 128 " X: 0
2946endif
2947
2948while 1
2949 try
2950 try
2951 let v:errmsg = ""
2952 let caught = 0
2953 if 0
2954 else
2955 elseif 1 ||| 2
2956 endif
2957 catch /^Vim\((\a\+)\)\=:/
2958 let caught = 1
2959 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
2960 finally
2961 Xpath 256 " X: 256
2962 if !caught && !$VIMNOERRTHROW
2963 Xpath 512 " X: 0
2964 endif
2965 if !MSG('E584', ":elseif after :else")
2966 Xpath 1024 " X: 0
2967 endif
2968 endtry
2969 catch /.*/
2970 Xpath 2048 " X: 0
2971 Xout v:exception "in" v:throwpoint
2972 finally
2973 break " discard error for $VIMNOERRTHROW
2974 endtry
2975endwhile
2976
2977while 1
2978 try
2979 try
2980 let v:errmsg = ""
2981 let caught = 0
2982 if 1
2983 else
2984 elseif 1 ||| 2
2985 endif
2986 catch /^Vim\((\a\+)\)\=:/
2987 let caught = 1
2988 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
2989 finally
2990 Xpath 4096 " X: 4096
2991 if !caught && !$VIMNOERRTHROW
2992 Xpath 8192 " X: 0
2993 endif
2994 if !MSG('E584', ":elseif after :else")
2995 Xpath 16384 " X: 0
2996 endif
2997 endtry
2998 catch /.*/
2999 Xpath 32768 " X: 0
3000 Xout v:exception "in" v:throwpoint
3001 finally
3002 break " discard error for $VIMNOERRTHROW
3003 endtry
3004endwhile
3005
3006while 1
3007 try
3008 try
3009 let v:errmsg = ""
3010 let caught = 0
3011 elseif 1 ||| 2
3012 catch /^Vim\((\a\+)\)\=:/
3013 let caught = 1
3014 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
3015 finally
3016 Xpath 65536 " X: 65536
3017 if !caught && !$VIMNOERRTHROW
3018 Xpath 131072 " X: 0
3019 endif
3020 if !MSG('E582', ":elseif without :if")
3021 Xpath 262144 " X: 0
3022 endif
3023 endtry
3024 catch /.*/
3025 Xpath 524288 " X: 0
3026 Xout v:exception "in" v:throwpoint
3027 finally
3028 break " discard error for $VIMNOERRTHROW
3029 endtry
3030endwhile
3031
3032while 1
3033 try
3034 try
3035 let v:errmsg = ""
3036 let caught = 0
3037 while 1
3038 elseif 1 ||| 2
3039 endwhile
3040 catch /^Vim\((\a\+)\)\=:/
3041 let caught = 1
3042 let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
3043 finally
3044 Xpath 1048576 " X: 1048576
3045 if !caught && !$VIMNOERRTHROW
3046 Xpath 2097152 " X: 0
3047 endif
3048 if !MSG('E582', ":elseif without :if")
3049 Xpath 4194304 " X: 0
3050 endif
3051 endtry
3052 catch /.*/
3053 Xpath 8388608 " X: 0
3054 Xout v:exception "in" v:throwpoint
3055 finally
3056 break " discard error for $VIMNOERRTHROW
3057 endtry
3058endwhile
3059
3060Xpath 16777216 " X: 16777216
3061
3062unlet! caught
3063delfunction MSG
3064
3065Xcheck 17895765
3066
3067
3068"-------------------------------------------------------------------------------
3069" Test 81: Discarding exceptions after an error or interrupt {{{1
3070"
3071" When an exception is thrown from inside a :try conditional without
3072" :catch and :finally clauses and an error or interrupt occurs before
3073" the :endtry is reached, the exception is discarded.
3074"-------------------------------------------------------------------------------
3075
3076XpathINIT
3077
3078if ExtraVim()
3079 try
3080 Xpath 1 " X: 1
3081 try
3082 Xpath 2 " X: 2
3083 throw "arrgh"
3084 Xpath 4 " X: 0
3085" if 1
3086 Xpath 8 " X: 0
3087 " error after :throw: missing :endif
3088 endtry
3089 Xpath 16 " X: 0
3090 catch /arrgh/
3091 Xpath 32 " X: 0
3092 endtry
3093 Xpath 64 " X: 0
3094endif
3095
3096if ExtraVim()
3097 try
3098 Xpath 128 " X: 128
3099 try
3100 Xpath 256 " X: 256
3101 throw "arrgh"
3102 Xpath 512 " X: 0
3103 endtry " INTERRUPT
3104 Xpath 1024 " X: 0
3105 catch /arrgh/
3106 Xpath 2048 " X: 0
3107 endtry
3108 Xpath 4096 " X: 0
3109endif
3110
3111Xcheck 387
3112
3113
3114"-------------------------------------------------------------------------------
3115" Test 82: Ignoring :catch clauses after an error or interrupt {{{1
3116"
3117" When an exception is thrown and an error or interrupt occurs before
3118" the matching :catch clause is reached, the exception is discarded
3119" and the :catch clause is ignored (also for the error or interrupt
3120" exception being thrown then).
3121"-------------------------------------------------------------------------------
3122
3123XpathINIT
3124
3125if ExtraVim()
3126 try
3127 try
3128 Xpath 1 " X: 1
3129 throw "arrgh"
3130 Xpath 2 " X: 0
3131" if 1
3132 Xpath 4 " X: 0
3133 " error after :throw: missing :endif
3134 catch /.*/
3135 Xpath 8 " X: 0
3136 Xout v:exception "in" ExtraVimThrowpoint()
3137 catch /.*/
3138 Xpath 16 " X: 0
3139 Xout v:exception "in" ExtraVimThrowpoint()
3140 endtry
3141 Xpath 32 " X: 0
3142 catch /arrgh/
3143 Xpath 64 " X: 0
3144 endtry
3145 Xpath 128 " X: 0
3146endif
3147
3148if ExtraVim()
3149 function! E()
3150 try
3151 try
3152 Xpath 256 " X: 256
3153 throw "arrgh"
3154 Xpath 512 " X: 0
3155" if 1
3156 Xpath 1024 " X: 0
3157 " error after :throw: missing :endif
3158 catch /.*/
3159 Xpath 2048 " X: 0
3160 Xout v:exception "in" ExtraVimThrowpoint()
3161 catch /.*/
3162 Xpath 4096 " X: 0
3163 Xout v:exception "in" ExtraVimThrowpoint()
3164 endtry
3165 Xpath 8192 " X: 0
3166 catch /arrgh/
3167 Xpath 16384 " X: 0
3168 endtry
3169 endfunction
3170
3171 call E()
3172 Xpath 32768 " X: 0
3173endif
3174
3175if ExtraVim()
3176 try
3177 try
3178 Xpath 65536 " X: 65536
3179 throw "arrgh"
3180 Xpath 131072 " X: 0
3181 catch /.*/ "INTERRUPT
3182 Xpath 262144 " X: 0
3183 Xout v:exception "in" ExtraVimThrowpoint()
3184 catch /.*/
3185 Xpath 524288 " X: 0
3186 Xout v:exception "in" ExtraVimThrowpoint()
3187 endtry
3188 Xpath 1048576 " X: 0
3189 catch /arrgh/
3190 Xpath 2097152 " X: 0
3191 endtry
3192 Xpath 4194304 " X: 0
3193endif
3194
3195if ExtraVim()
3196 function I()
3197 try
3198 try
3199 Xpath 8388608 " X: 8388608
3200 throw "arrgh"
3201 Xpath 16777216 " X: 0
3202 catch /.*/ "INTERRUPT
3203 Xpath 33554432 " X: 0
3204 Xout v:exception "in" ExtraVimThrowpoint()
3205 catch /.*/
3206 Xpath 67108864 " X: 0
3207 Xout v:exception "in" ExtraVimThrowpoint()
3208 endtry
3209 Xpath 134217728 " X: 0
3210 catch /arrgh/
3211 Xpath 268435456 " X: 0
3212 endtry
3213 endfunction
3214
3215 call I()
3216 Xpath 536870912 " X: 0
3217endif
3218
3219Xcheck 8454401
3220
3221
3222"-------------------------------------------------------------------------------
3223" Test 83: Executing :finally clauses after an error or interrupt {{{1
3224"
3225" When an exception is thrown and an error or interrupt occurs before
3226" the :finally of the innermost :try is reached, the exception is
3227" discarded and the :finally clause is executed.
3228"-------------------------------------------------------------------------------
3229
3230XpathINIT
3231
3232if ExtraVim()
3233 try
3234 Xpath 1 " X: 1
3235 try
3236 Xpath 2 " X: 2
3237 throw "arrgh"
3238 Xpath 4 " X: 0
3239" if 1
3240 Xpath 8 " X: 0
3241 " error after :throw: missing :endif
3242 finally
3243 Xpath 16 " X: 16
3244 endtry
3245 Xpath 32 " X: 0
3246 catch /arrgh/
3247 Xpath 64 " X: 0
3248 endtry
3249 Xpath 128 " X: 0
3250endif
3251
3252if ExtraVim()
3253 try
3254 Xpath 256 " X: 256
3255 try
3256 Xpath 512 " X: 512
3257 throw "arrgh"
3258 Xpath 1024 " X: 0
3259 finally "INTERRUPT
3260 Xpath 2048 " X: 2048
3261 endtry
3262 Xpath 4096 " X: 0
3263 catch /arrgh/
3264 Xpath 8192 " X: 0
3265 endtry
3266 Xpath 16384 " X: 0
3267endif
3268
3269Xcheck 2835
3270
3271
3272"-------------------------------------------------------------------------------
3273" Test 84: Exceptions in autocommand sequences. {{{1
3274"
3275" When an exception occurs in a sequence of autocommands for
3276" a specific event, the rest of the sequence is not executed. The
3277" command that triggered the autocommand execution aborts, and the
3278" exception is propagated to the caller.
3279"
3280" For the FuncUndefined event under a function call expression or
Bram Moolenaarbc045ea2005-06-05 22:01:26 +00003281" :call command, the function is not executed, even when it has
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282" been defined by the autocommands before the exception occurred.
3283"-------------------------------------------------------------------------------
3284
3285XpathINIT
3286
3287if ExtraVim()
3288
3289 function! INT()
3290 "INTERRUPT
3291 let dummy = 0
3292 endfunction
3293
3294 aug TMP
3295 autocmd!
3296
3297 autocmd User x1 Xpath 1 " X: 1
3298 autocmd User x1 throw "x1"
3299 autocmd User x1 Xpath 2 " X: 0
3300
3301 autocmd User x2 Xpath 4 " X: 4
3302 autocmd User x2 asdf
3303 autocmd User x2 Xpath 8 " X: 0
3304
3305 autocmd User x3 Xpath 16 " X: 16
3306 autocmd User x3 call INT()
3307 autocmd User x3 Xpath 32 " X: 0
3308
3309 autocmd FuncUndefined U1 function! U1()
3310 autocmd FuncUndefined U1 Xpath 64 " X: 0
3311 autocmd FuncUndefined U1 endfunction
3312 autocmd FuncUndefined U1 Xpath 128 " X: 128
3313 autocmd FuncUndefined U1 throw "U1"
3314 autocmd FuncUndefined U1 Xpath 256 " X: 0
3315
3316 autocmd FuncUndefined U2 function! U2()
3317 autocmd FuncUndefined U2 Xpath 512 " X: 0
3318 autocmd FuncUndefined U2 endfunction
3319 autocmd FuncUndefined U2 Xpath 1024 " X: 1024
3320 autocmd FuncUndefined U2 ASDF
3321 autocmd FuncUndefined U2 Xpath 2048 " X: 0
3322
3323 autocmd FuncUndefined U3 function! U3()
3324 autocmd FuncUndefined U3 Xpath 4096 " X: 0
3325 autocmd FuncUndefined U3 endfunction
3326 autocmd FuncUndefined U3 Xpath 8192 " X: 8192
3327 autocmd FuncUndefined U3 call INT()
3328 autocmd FuncUndefined U3 Xpath 16384 " X: 0
3329 aug END
3330
3331 try
3332 try
3333 Xpath 32768 " X: 32768
3334 doautocmd User x1
3335 catch /x1/
3336 Xpath 65536 " X: 65536
3337 endtry
3338
3339 while 1
3340 try
3341 Xpath 131072 " X: 131072
3342 let caught = 0
3343 doautocmd User x2
3344 catch /asdf/
3345 let caught = 1
3346 finally
3347 Xpath 262144 " X: 262144
3348 if !caught && !$VIMNOERRTHROW
3349 Xpath 524288 " X: 0
3350 " Propagate uncaught error exception,
3351 else
3352 " ... but break loop for caught error exception,
3353 " or discard error and break loop if $VIMNOERRTHROW
3354 break
3355 endif
3356 endtry
3357 endwhile
3358
3359 while 1
3360 try
3361 Xpath 1048576 " X: 1048576
3362 let caught = 0
3363 doautocmd User x3
3364 catch /Vim:Interrupt/
3365 let caught = 1
3366 finally
3367 Xpath 2097152 " X: 2097152
3368 if !caught && !$VIMNOINTTHROW
3369 Xpath 4194304 " X: 0
3370 " Propagate uncaught interrupt exception,
3371 else
3372 " ... but break loop for caught interrupt exception,
3373 " or discard interrupt and break loop if $VIMNOINTTHROW
3374 break
3375 endif
3376 endtry
3377 endwhile
3378
3379 if exists("*U1") | delfunction U1 | endif
3380 if exists("*U2") | delfunction U2 | endif
3381 if exists("*U3") | delfunction U3 | endif
3382
3383 try
3384 Xpath 8388608 " X: 8388608
3385 call U1()
3386 catch /U1/
3387 Xpath 16777216 " X: 16777216
3388 endtry
3389
3390 while 1
3391 try
3392 Xpath 33554432 " X: 33554432
3393 let caught = 0
3394 call U2()
3395 catch /ASDF/
3396 let caught = 1
3397 finally
3398 Xpath 67108864 " X: 67108864
3399 if !caught && !$VIMNOERRTHROW
3400 Xpath 134217728 " X: 0
3401 " Propagate uncaught error exception,
3402 else
3403 " ... but break loop for caught error exception,
3404 " or discard error and break loop if $VIMNOERRTHROW
3405 break
3406 endif
3407 endtry
3408 endwhile
3409
3410 while 1
3411 try
3412 Xpath 268435456 " X: 268435456
3413 let caught = 0
3414 call U3()
3415 catch /Vim:Interrupt/
3416 let caught = 1
3417 finally
3418 Xpath 536870912 " X: 536870912
3419 if !caught && !$VIMNOINTTHROW
3420 Xpath 1073741824 " X: 0
3421 " Propagate uncaught interrupt exception,
3422 else
3423 " ... but break loop for caught interrupt exception,
3424 " or discard interrupt and break loop if $VIMNOINTTHROW
3425 break
3426 endif
3427 endtry
3428 endwhile
3429 catch /.*/
3430 " The Xpath command does not accept 2^31 (negative); display explicitly:
3431 exec "!echo 2147483648 >>" . g:ExtraVimResult
3432 Xout "Caught" v:exception "in" v:throwpoint
3433 endtry
3434
3435 unlet caught
3436 delfunction INT
3437 delfunction U1
3438 delfunction U2
3439 delfunction U3
3440 au! TMP
3441 aug! TMP
3442endif
3443
3444Xcheck 934782101
3445
3446
3447"-------------------------------------------------------------------------------
3448" Test 85: Error exceptions in autocommands for I/O command events {{{1
3449"
3450" When an I/O command is inside :try/:endtry, autocommands to be
3451" executed after it should be skipped on an error (exception) in the
3452" command itself or in autocommands to be executed before the command.
3453" In the latter case, the I/O command should not be executed either.
3454" Example 1: BufWritePre, :write, BufWritePost
3455" Example 2: FileReadPre, :read, FileReadPost.
3456"-------------------------------------------------------------------------------
3457
3458XpathINIT
3459
3460function! MSG(enr, emsg)
3461 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
3462 if a:enr == ""
3463 Xout "TODO: Add message number for:" a:emsg
3464 let v:errmsg = ":" . v:errmsg
3465 endif
3466 let match = 1
3467 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
3468 let match = 0
3469 if v:errmsg == ""
3470 Xout "Message missing."
3471 else
3472 let v:errmsg = escape(v:errmsg, '"')
3473 Xout "Unexpected message:" v:errmsg
3474 endif
3475 endif
3476 return match
3477endfunction
3478
3479" Remove the autocommands for the events specified as arguments in all used
3480" autogroups.
Bram Moolenaar1e115362019-01-09 23:01:02 +01003481function Delete_autocommands(...)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003482 let augfile = tempname()
3483 while 1
3484 try
3485 exec "redir >" . augfile
3486 aug
3487 redir END
3488 exec "edit" augfile
3489 g/^$/d
3490 norm G$
3491 let wrap = "w"
3492 while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
3493 let wrap = "W"
3494 exec "norm y/ \n"
3495 let argno = 1
3496 while argno <= a:0
3497 exec "au!" escape(@", " ") a:{argno}
3498 let argno = argno + 1
3499 endwhile
3500 endwhile
3501 catch /.*/
3502 finally
3503 bwipeout!
3504 call delete(augfile)
3505 break " discard errors for $VIMNOERRTHROW
3506 endtry
3507 endwhile
3508endfunction
3509
3510call Delete_autocommands("BufWritePre", "BufWritePost")
3511
3512while 1
3513 try
3514 try
3515 let post = 0
3516 aug TMP
3517 au! BufWritePost * let post = 1
3518 aug END
3519 let caught = 0
3520 write /n/o/n/e/x/i/s/t/e/n/t
3521 catch /^Vim(write):/
3522 let caught = 1
3523 let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
3524 finally
3525 Xpath 1 " X: 1
3526 if !caught && !$VIMNOERRTHROW
3527 Xpath 2 " X: 0
3528 endif
3529 let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
3530 \ '', "")
3531 if !MSG('E212', "Can't open file for writing")
3532 Xpath 4 " X: 0
3533 endif
3534 if post
3535 Xpath 8 " X: 0
3536 Xout "BufWritePost commands executed after write error"
3537 endif
3538 au! TMP
3539 aug! TMP
3540 endtry
3541 catch /.*/
3542 Xpath 16 " X: 0
3543 Xout v:exception "in" v:throwpoint
3544 finally
3545 break " discard error for $VIMNOERRTHROW
3546 endtry
3547endwhile
3548
3549while 1
3550 try
3551 try
3552 let post = 0
3553 aug TMP
3554 au! BufWritePre * asdf
3555 au! BufWritePost * let post = 1
3556 aug END
3557 let tmpfile = tempname()
3558 let caught = 0
3559 exec "write" tmpfile
3560 catch /^Vim\((write)\)\=:/
3561 let caught = 1
3562 let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
3563 finally
3564 Xpath 32 " X: 32
3565 if !caught && !$VIMNOERRTHROW
3566 Xpath 64 " X: 0
3567 endif
3568 let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
3569 if !MSG('E492', "Not an editor command")
3570 Xpath 128 " X: 0
3571 endif
3572 if filereadable(tmpfile)
3573 Xpath 256 " X: 0
3574 Xout ":write command not suppressed after BufWritePre error"
3575 endif
3576 if post
3577 Xpath 512 " X: 0
3578 Xout "BufWritePost commands executed after BufWritePre error"
3579 endif
3580 au! TMP
3581 aug! TMP
3582 endtry
3583 catch /.*/
3584 Xpath 1024 " X: 0
3585 Xout v:exception "in" v:throwpoint
3586 finally
3587 break " discard error for $VIMNOERRTHROW
3588 endtry
3589endwhile
3590
3591call delete(tmpfile)
3592
3593call Delete_autocommands("BufWritePre", "BufWritePost",
3594 \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
3595
3596while 1
3597 try
3598 try
3599 let post = 0
3600 aug TMP
3601 au! FileReadPost * let post = 1
3602 aug END
3603 let caught = 0
3604 read /n/o/n/e/x/i/s/t/e/n/t
3605 catch /^Vim(read):/
3606 let caught = 1
3607 let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
3608 finally
3609 Xpath 2048 " X: 2048
3610 if !caught && !$VIMNOERRTHROW
3611 Xpath 4096 " X: 0
3612 endif
3613 let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
3614 \ '', "")
3615 if !MSG('E484', "Can't open file")
3616 Xpath 8192 " X: 0
3617 endif
3618 if post
3619 Xpath 16384 " X: 0
3620 Xout "FileReadPost commands executed after write error"
3621 endif
3622 au! TMP
3623 aug! TMP
3624 endtry
3625 catch /.*/
3626 Xpath 32768 " X: 0
3627 Xout v:exception "in" v:throwpoint
3628 finally
3629 break " discard error for $VIMNOERRTHROW
3630 endtry
3631endwhile
3632
3633while 1
3634 try
3635 let infile = tempname()
3636 let tmpfile = tempname()
3637 exec "!echo XYZ >" . infile
3638 exec "edit" tmpfile
3639 try
3640 Xpath 65536 " X: 65536
3641 try
3642 let post = 0
3643 aug TMP
3644 au! FileReadPre * asdf
3645 au! FileReadPost * let post = 1
3646 aug END
3647 let caught = 0
3648 exec "0read" infile
3649 catch /^Vim\((read)\)\=:/
3650 let caught = 1
3651 let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
3652 \ "")
3653 finally
3654 Xpath 131072 " X: 131072
3655 if !caught && !$VIMNOERRTHROW
3656 Xpath 262144 " X: 0
3657 endif
3658 let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
3659 if !MSG('E492', "Not an editor command")
3660 Xpath 524288 " X: 0
3661 endif
3662 if getline("1") == "XYZ"
3663 Xpath 1048576 " X: 0
3664 Xout ":read command not suppressed after FileReadPre error"
3665 endif
3666 if post
3667 Xpath 2097152 " X: 0
3668 Xout "FileReadPost commands executed after " .
3669 \ "FileReadPre error"
3670 endif
3671 au! TMP
3672 aug! TMP
3673 endtry
3674 finally
3675 bwipeout!
3676 endtry
3677 catch /.*/
3678 Xpath 4194304 " X: 0
3679 Xout v:exception "in" v:throwpoint
3680 finally
3681 break " discard error for $VIMNOERRTHROW
3682 endtry
3683endwhile
3684
3685call delete(infile)
3686call delete(tmpfile)
3687unlet! caught post infile tmpfile
3688delfunction MSG
3689delfunction Delete_autocommands
3690
3691Xcheck 198689
3692
Bram Moolenaar41b884b2012-11-14 22:38:08 +01003693"-------------------------------------------------------------------------------
Bram Moolenaar32c8f1c2012-12-05 19:00:06 +01003694" Test 86: setloclist crash {{{1
Bram Moolenaar41b884b2012-11-14 22:38:08 +01003695"
3696" Executing a setloclist() on BufUnload shouldn't crash Vim
3697"-------------------------------------------------------------------------------
3698
3699func F
3700 au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 'tango down'}])
3701
Bram Moolenaarcc908ad2013-06-06 18:55:49 +02003702 :lvimgrep /.*/ *.mak
Bram Moolenaar41b884b2012-11-14 22:38:08 +01003703endfunc
3704
3705XpathINIT
3706
3707ExecAsScript F
3708
3709delfunction F
3710Xout "No Crash for vimgrep on BufUnload"
3711Xcheck 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003712
Bram Moolenaar1f068232019-11-03 16:17:26 +01003713" Test 87 was moved to test_vimscript.vim
3714let Xtest = 88
Bram Moolenaarb8f84612013-02-26 22:54:11 +01003715
Bram Moolenaarb8f84612013-02-26 22:54:11 +01003716
3717"-------------------------------------------------------------------------------
3718" Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
Bram Moolenaar071d4272004-06-13 20:20:40 +00003719"
3720" It is possible to configure Vim for throwing exceptions on error
3721" or interrupt, controlled by variables $VIMNOERRTHROW and
3722" $VIMNOINTTHROW. This is just for increasing the number of tests.
3723" All tests here should run for all four combinations of setting
3724" these variables to 0 or 1. The variables are intended for the
3725" development phase only. In the final release, Vim should be
3726" configured to always use error and interrupt exceptions.
3727"
3728" The test result is "OK",
3729"
3730" - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
3731" configured and exceptions are thrown on error and on
3732" interrupt.
3733"
3734" - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
3735" configured and works as intended.
3736"
3737" What actually happens, is shown in the test output.
3738"
3739" Otherwise, the test result is "FAIL", and the test output describes
3740" the problem.
3741"
3742" IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and
3743" $VIMNOINTTHROW.
3744"-------------------------------------------------------------------------------
3745
3746XpathINIT
3747
3748if ExtraVim()
3749
3750 function! ThrowOnError()
3751 XloopNEXT
3752 let caught = 0
3753 try
3754 Xloop 1 " X: 1 + 8 + 64
3755 asdf
3756 catch /.*/
3757 let caught = 1 " error exception caught
3758 finally
3759 Xloop 2 " X: 2 + 16 + 128
3760 return caught " discard aborting error
3761 endtry
3762 Xloop 4 " X: 0
3763 endfunction
3764
3765 let quits_skipped = 0
3766
3767 function! ThrowOnInterrupt()
3768 XloopNEXT
3769 let caught = 0
3770 try
3771 Xloop 1 " X: (1 + 8 + 64) * 512
3772 "INTERRUPT3
3773 let dummy = 0
3774 let g:quits_skipped = g:quits_skipped + 1
3775 catch /.*/
3776 let caught = 1 " interrupt exception caught
3777 finally
3778 Xloop 2 " X: (2 + 16 + 128) * 512
3779 return caught " discard interrupt
3780 endtry
3781 Xloop 4 " X: 0
3782 endfunction
3783
3784 function! CheckThrow(Type)
3785 execute 'return ThrowOn' . a:Type . '()'
3786 endfunction
3787
3788 function! CheckConfiguration(type) " type is "error" or "interrupt"
3789
3790 let type = a:type
3791 let Type = substitute(type, '.*', '\u&', "")
3792 let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
3793
3794 if type == "error"
3795 XloopINIT! 1 8
3796 elseif type == "interrupt"
3797 XloopINIT! 512 8
3798 endif
3799
3800 exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
3801 exec 'let suppressed_for_tests = ' . VAR . ' != 0'
3802 let used_in_tests = CheckThrow(Type)
3803
3804 exec 'let ' . VAR . ' = 0'
3805 let request_works = CheckThrow(Type)
3806
3807 exec 'let ' . VAR . ' = 1'
3808 let suppress_works = !CheckThrow(Type)
3809
3810 if type == "error"
3811 XloopINIT! 262144 8
3812 elseif type == "interrupt"
3813 XloopINIT! 2097152 8
3814
3815 if g:quits_skipped != 0
3816 Xloop 1 " X: 0*2097152
3817 Xout "Test environment error. Interrupt breakpoints skipped: "
3818 \ . g:quits_skipped . ".\n"
3819 \ . "Cannot check whether interrupt exceptions are thrown."
3820 return
3821 endif
3822 endif
3823
3824 let failure =
3825 \ !suppressed_for_tests && !used_in_tests
3826 \ || !request_works
3827
3828 let contradiction =
3829 \ used_in_tests
3830 \ ? suppressed_for_tests && !request_works
3831 \ : !suppressed_for_tests
3832
3833 if failure
3834 " Failure in configuration.
3835 Xloop 2 " X: 0 * 2* (262144 + 2097152)
3836 elseif contradiction
3837 " Failure in test logic. Should not happen.
3838 Xloop 4 " X: 0 * 4 * (262144 + 2097152)
3839 endif
3840
3841 let var_control_configured =
3842 \ request_works != used_in_tests
3843 \ || suppress_works == used_in_tests
3844
3845 let var_control_not_configured =
3846 \ requested_for_tests || suppressed_for_tests
3847 \ ? request_works && !suppress_works
3848 \ : request_works == used_in_tests
3849 \ && suppress_works != used_in_tests
3850
3851 let with = used_in_tests ? "with" : "without"
3852
3853 let set = suppressed_for_tests ? "non-zero" :
3854 \ requested_for_tests ? "0" : "unset"
3855
3856 let although = contradiction && !var_control_not_configured
3857 \ ? ",\nalthough "
3858 \ : ".\n"
3859
3860 let output = "All tests were run " . with . " throwing exceptions on "
3861 \ . type . although
3862
3863 if !var_control_not_configured
3864 let output = output . VAR . " was " . set . "."
3865
3866 if !request_works && !requested_for_tests
3867 let output = output .
3868 \ "\n" . Type . " exceptions are not thrown when " . VAR .
3869 \ " is\nset to 0."
3870 endif
3871
3872 if !suppress_works && (!used_in_tests ||
3873 \ !request_works &&
3874 \ !requested_for_tests && !suppressed_for_tests)
3875 let output = output .
3876 \ "\n" . Type . " exceptions are thrown when " . VAR .
3877 \ " is set to 1."
3878 endif
3879
3880 if !failure && var_control_configured
3881 let output = output .
3882 \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
3883 \ . "=" . used_in_tests . "."
3884 \ . "\nThis is for testing in the development phase only."
3885 \ . " Remove the \n"
3886 \ . VAR . " control in the final release."
3887 endif
3888 else
3889 let output = output .
3890 \ "The " . VAR . " control is not configured."
3891 endif
3892
3893 Xout output
3894 endfunction
3895
3896 call CheckConfiguration("error")
3897 Xpath 16777216 " X: 16777216
3898 call CheckConfiguration("interrupt")
3899 Xpath 33554432 " X: 33554432
3900endif
3901
3902Xcheck 50443995
3903
3904" IMPORTANT: No test should be added after this test because it changes
3905" $VIMNOERRTHROW and $VIMNOINTTHROW.
3906
3907
3908"-------------------------------------------------------------------------------
3909" Modelines {{{1
3910" vim: ts=8 sw=4 tw=80 fdm=marker
Bram Moolenaar071d4272004-06-13 20:20:40 +00003911"-------------------------------------------------------------------------------