| " Vim script language tests |
| " Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com> |
| " Last Change: 2005 Jun 18 |
| |
| "------------------------------------------------------------------------------- |
| " Test environment {{{1 |
| "------------------------------------------------------------------------------- |
| |
| |
| " Adding new tests easily. {{{2 |
| " |
| " Writing new tests is eased considerably with the following functions and |
| " abbreviations (see "Commands for recording the execution path", "Automatic |
| " argument generation"). |
| " |
| " To get the abbreviations, execute the command |
| " |
| " :let test49_set_env = 1 | source test49.vim |
| " |
| " To get them always (from src/testdir), put a line |
| " |
| " au! BufRead test49.vim let test49_set_env = 1 | source test49.vim |
| " |
| " into the local .vimrc file in the src/testdir directory. |
| " |
| if exists("test49_set_env") && test49_set_env |
| |
| " Automatic argument generation for the test environment commands. |
| |
| function! Xsum() |
| let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "") |
| " Evaluate arithmetic expression. |
| if addend != "" |
| exec "let g:Xsum = g:Xsum + " . addend |
| endif |
| endfunction |
| |
| function! Xcheck() |
| let g:Xsum=0 |
| ?XpathINIT?,.call Xsum() |
| exec "norm A " |
| return g:Xsum |
| endfunction |
| |
| iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x |
| |
| function! Xcomment(num) |
| let str = "" |
| let tabwidth = &sts ? &sts : &ts |
| let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth |
| while tabs > 0 |
| let str = str . "\t" |
| let tabs = tabs - 1 |
| endwhile |
| let str = str . '" X:' |
| return str |
| endfunction |
| |
| function! Xloop() |
| let back = line(".") . "|norm" . virtcol(".") . "|" |
| norm 0 |
| let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW") |
| exec back |
| let theline = getline(last) |
| if theline =~ 'X\(loop\|path\)INIT' |
| let num = 1 |
| else |
| let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "") |
| endif |
| ?X\(loop\|path\)INIT? |
| \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/ |
| exec back |
| exec "norm a " |
| return num . Xcomment(strlen(num)) |
| endfunction |
| |
| iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x |
| |
| function! Xpath(loopinit) |
| let back = line(".") . "|norm" . virtcol(".") . "|" |
| norm 0 |
| let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW") |
| exec back |
| let theline = getline(last) |
| if theline =~ 'XpathINIT' |
| let num = 1 |
| elseif theline =~ 'Xpath\>' |
| let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "") |
| else |
| let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*' |
| let num = substitute(theline, pattern, '\1', "") |
| let factor = substitute(theline, pattern, '\2', "") |
| " The "<C-O>x" from the "Xpath" iab and the character triggering its |
| " expansion are in the input buffer. Save and clear typeahead so |
| " that it is not read away by the call to "input()" below. Restore |
| " afterwards. |
| call inputsave() |
| let loops = input("Number of iterations in previous loop? ") |
| call inputrestore() |
| while (loops > 0) |
| let num = num * factor |
| let loops = loops - 1 |
| endwhile |
| endif |
| exec "norm a " |
| if a:loopinit |
| return num . " 1" |
| endif |
| return num . Xcomment(strlen(num)) |
| endfunction |
| |
| iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x |
| iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x |
| |
| " Also useful (see ExtraVim below): |
| aug ExtraVim |
| au! |
| au BufEnter <sfile> syn region ExtraVim |
| \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+ |
| \ transparent keepend |
| au BufEnter <sfile> syn match ExtraComment /^"/ |
| \ contained containedin=ExtraVim |
| au BufEnter <sfile> hi link ExtraComment vimComment |
| aug END |
| |
| aug Xpath |
| au BufEnter <sfile> syn keyword Xpath |
| \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout |
| au BufEnter <sfile> hi link Xpath Special |
| aug END |
| |
| do BufEnter <sfile> |
| |
| " Do not execute the tests when sourcing this file for getting the functions |
| " and abbreviations above, which are intended for easily adding new test |
| " cases; they are not needed for test execution. Unlet the variable |
| " controlling this so that an explicit ":source" command for this file will |
| " execute the tests. |
| unlet test49_set_env |
| finish |
| |
| endif |
| |
| |
| " Commands for recording the execution path. {{{2 |
| " |
| " The Xpath/Xloop commands can be used for computing the eXecution path by |
| " adding (different) powers of 2 from those script lines, for which the |
| " execution should be checked. Xloop provides different addends for each |
| " execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution |
| " points (multiply counted inside loops) can be tested. |
| " |
| " Note that the arguments of the following commands can be generated |
| " automatically, see below. |
| " |
| " Usage: {{{3 |
| " |
| " - Use XpathINIT at the beginning of the test. |
| " |
| " - Use Xpath to check if a line is executed. |
| " Argument: power of 2 (decimal). |
| " |
| " - To check multiple execution of loops use Xloop for automatically |
| " computing Xpath values: |
| " |
| " - Use XloopINIT before the loop. |
| " Two arguments: |
| " - the first Xpath value (power of 2) to be used (Xnext), |
| " - factor for computing a new Xnext value when reexecuting a loop |
| " (by a ":continue" or ":endwhile"); this should be 2^n where |
| " n is the number of Xloop commands inside the loop. |
| " If XloopINIT! is used, the first execution of XloopNEXT is |
| " a no-operation. |
| " |
| " - Use Xloop inside the loop: |
| " One argument: |
| " The argument and the Xnext value are multiplied to build the |
| " next Xpath value. No new Xnext value is prepared. The argument |
| " should be 2^(n-1) for the nth Xloop command inside the loop. |
| " If the loop has only one Xloop command, the argument can be |
| " ommitted (default: 1). |
| " |
| " - Use XloopNEXT before ":continue" and ":endwhile". This computes a new |
| " Xnext value for the next execution of the loop by multiplying the old |
| " one with the factor specified in the XloopINIT command. No Argument. |
| " Alternatively, when XloopINIT! is used, a single XloopNEXT at the |
| " beginning of the loop can be used. |
| " |
| " Nested loops are not supported. |
| " |
| " - Use Xcheck at end of each test. It prints the test number, the expected |
| " execution path value, the test result ("OK" or "FAIL"), and, if the tests |
| " fails, the actual execution path. |
| " One argument: |
| " Expected Xpath/Xloop sum for the correct execution path. |
| " In order that this value can be computed automatically, do the |
| " following: For each line in the test with an Xpath and Xloop |
| " command, add a comment starting with "X:" and specifying an |
| " expression that evaluates to the value contributed by this line to |
| " the correct execution path. (For copying an Xpath argument of at |
| " least two digits into the comment, press <C-P>.) At the end of the |
| " test, just type "Xcheck" and press <Esc>. |
| " |
| " - In order to add additional information to the test output file, use the |
| " Xout command. Argument(s) like ":echo". |
| " |
| " Automatic argument generation: {{{3 |
| " |
| " The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be |
| " generated automatically, so that new tests can easily be written without |
| " mental arithmetic. The Xcheck argument is computed from the "X:" comments |
| " of the preceding Xpath and Xloop commands. See the commands and |
| " abbreviations at the beginning of this file. |
| " |
| " Implementation: {{{3 |
| " XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout. |
| " |
| " The variants for existing g:ExtraVimResult are needed when executing a script |
| " in an extra Vim process, see ExtraVim below. |
| |
| " EXTRA_VIM_START - do not change or remove this line. |
| |
| com! XpathINIT let g:Xpath = 0 |
| |
| if exists("g:ExtraVimResult") |
| com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult |
| else |
| com! -count -bar Xpath let g:Xpath = g:Xpath + <count> |
| endif |
| |
| com! -count -nargs=1 -bang |
| \ XloopINIT let g:Xnext = <count> | |
| \ let g:Xfactor = <args> | |
| \ let g:Xskip = strlen("<bang>") |
| |
| if exists("g:ExtraVimResult") |
| com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" . |
| \ g:ExtraVimResult |
| else |
| com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count> |
| endif |
| |
| com! XloopNEXT let g:Xnext = g:Xnext * |
| \ (g:Xskip ? 1 : g:Xfactor) | |
| \ let g:Xskip = 0 |
| |
| let @r = "" |
| let Xtest = 1 |
| com! -count Xcheck let Xresult = "*** Test " . |
| \ (Xtest<10?" ":Xtest<100?" ":"") . |
| \ Xtest . ": " . ( |
| \ (Xpath==<count>) ? "OK (".Xpath.")" : |
| \ "FAIL (".Xpath." instead of <count>)" |
| \ ) | |
| \ let @R = Xresult . "\n" | |
| \ echo Xresult | |
| \ let Xtest = Xtest + 1 |
| |
| if exists("g:ExtraVimResult") |
| com! -nargs=+ Xoutq exec "!echo @R:'" . |
| \ substitute(substitute(<q-args>, |
| \ "'", '&\\&&', "g"), "\n", "@NL@", "g") |
| \ . "' >>" . g:ExtraVimResult |
| else |
| com! -nargs=+ Xoutq let @R = "--- Test " . |
| \ (g:Xtest<10?" ":g:Xtest<100?" ":"") . |
| \ g:Xtest . ": " . substitute(<q-args>, |
| \ "\n", "&\t ", "g") . "\n" |
| endif |
| com! -nargs=+ Xout exec 'Xoutq' <args> |
| |
| " Switch off storing of lines for undoing changes. Speeds things up a little. |
| set undolevels=-1 |
| |
| " EXTRA_VIM_STOP - do not change or remove this line. |
| |
| |
| " ExtraVim() - Run a script file in an extra Vim process. {{{2 |
| " |
| " This is useful for testing immediate abortion of the script processing due to |
| " an error in a command dynamically enclosed by a :try/:tryend region or when an |
| " exception is thrown but not caught or when an interrupt occurs. It can also |
| " be used for testing :finish. |
| " |
| " An interrupt location can be specified by an "INTERRUPT" comment. A number |
| " telling how often this location is reached (in a loop or in several function |
| " calls) should be specified as argument. When missing, once per script |
| " invocation or function call is assumed. INTERRUPT locations are tested by |
| " setting a breakpoint in that line and using the ">quit" debug command when |
| " the breakpoint is reached. A function for which an INTERRUPT location is |
| " specified must be defined before calling it (or executing it as a script by |
| " using ExecAsScript below). |
| " |
| " This function is only called in normal modus ("g:ExtraVimResult" undefined). |
| " |
| " Tests to be executed as an extra script should be written as follows: |
| " |
| " column 1 column 1 |
| " | | |
| " v v |
| " |
| " XpathINIT XpathINIT |
| " if ExtraVim() if ExtraVim() |
| " ... " ... |
| " ... " ... |
| " endif endif |
| " Xcheck <number> Xcheck <number> |
| " |
| " Double quotes in column 1 are removed before the script is executed. |
| " They should be used if the test has unbalanced conditionals (:if/:endif, |
| " :while:/endwhile, :try/:endtry) or for a line with a syntax error. The |
| " extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual. |
| " |
| " A file name may be specified as argument. All messages of the extra Vim |
| " process are then redirected to the file. An existing file is overwritten. |
| " |
| let ExtraVimCount = 0 |
| let ExtraVimBase = expand("<sfile>") |
| let ExtraVimTestEnv = "" |
| " |
| function! ExtraVim(...) |
| " Count how often this function is called. |
| let g:ExtraVimCount = g:ExtraVimCount + 1 |
| |
| " Disable folds to prevent that the ranges in the ":write" commands below |
| " are extended up to the end of a closed fold. This also speeds things up |
| " considerably. |
| set nofoldenable |
| |
| " Open a buffer for this test script and copy the test environment to |
| " a temporary file. Take account of parts relevant for the extra script |
| " execution only. |
| let current_buffnr = bufnr("%") |
| execute "view +1" g:ExtraVimBase |
| if g:ExtraVimCount == 1 |
| let g:ExtraVimTestEnv = tempname() |
| execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w" |
| \ g:ExtraVimTestEnv "|']+" |
| execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" |
| \ g:ExtraVimTestEnv "|']+" |
| execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" |
| \ g:ExtraVimTestEnv "|']+" |
| execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" |
| \ g:ExtraVimTestEnv "|']+" |
| endif |
| |
| " Start the extra Vim script with a ":source" command for the test |
| " environment. The source line number where the extra script will be |
| " appended, needs to be passed as variable "ExtraVimBegin" to the script. |
| let extra_script = tempname() |
| exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script |
| let extra_begin = 1 |
| |
| " Starting behind the test environment, skip over the first g:ExtraVimCount |
| " occurrences of "if ExtraVim()" and copy the following lines up to the |
| " matching "endif" to the extra Vim script. |
| execute "/E" . "ND_OF_TEST_ENVIRONMENT/" |
| exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n" |
| execute ".,/^endif/-write >>" . extra_script |
| |
| " Open a buffer for the extra Vim script, delete all ^", and write the |
| " script if was actually modified. |
| execute "edit +" . (extra_begin + 1) extra_script |
| ,$s/^"//e |
| update |
| |
| " Count the INTERRUPTs and build the breakpoint and quit commands. |
| let breakpoints = "" |
| let debug_quits = "" |
| let in_func = 0 |
| exec extra_begin |
| while search( |
| \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|' |
| \ . '^\s*\\\|^\s*endf\%[unction]\>\|' |
| \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|' |
| \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*', |
| \ "W") > 0 |
| let theline = getline(".") |
| if theline =~ '^\s*fu' |
| " Function definition. |
| let in_func = 1 |
| let func_start = line(".") |
| let func_name = substitute(theline, |
| \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "") |
| let func_conts = 0 |
| elseif theline =~ '^\s*\\' |
| if in_func |
| let func_conts = func_conts + 1 |
| endif |
| elseif theline =~ '^\s*endf' |
| " End of function definition. |
| let in_func = 0 |
| else |
| let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)', |
| \ '\1', "") |
| if finding =~ '^"\s*INTERRUPT\h\@!' |
| " Interrupt comment. Compose as many quit commands as |
| " specified. |
| let cnt = substitute(finding, |
| \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "") |
| let quits = "" |
| while cnt > 0 |
| " Use "\r" rather than "\n" to separate the quit commands. |
| " "\r" is not interpreted as command separator by the ":!" |
| " command below but works to separate commands in the |
| " external vim. |
| let quits = quits . "q\r" |
| let cnt = cnt - 1 |
| endwhile |
| if in_func |
| " Add the function breakpoint and note the number of quits |
| " to be used, if specified, or one for every call else. |
| let breakpoints = breakpoints . " -c 'breakadd func " . |
| \ (line(".") - func_start - func_conts) . " " . |
| \ func_name . "'" |
| if quits != "" |
| let debug_quits = debug_quits . quits |
| elseif !exists("quits{func_name}") |
| let quits{func_name} = "q\r" |
| else |
| let quits{func_name} = quits{func_name} . "q\r" |
| endif |
| else |
| " Add the file breakpoint and the quits to be used for it. |
| let breakpoints = breakpoints . " -c 'breakadd file " . |
| \ line(".") . " " . extra_script . "'" |
| if quits == "" |
| let quits = "q\r" |
| endif |
| let debug_quits = debug_quits . quits |
| endif |
| else |
| " Add the quits to be used for calling the function or executing |
| " it as script file. |
| if finding =~ '^ExecAsScript' |
| " Sourcing function as script. |
| let finding = substitute(finding, |
| \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "") |
| else |
| " Function call. |
| let finding = substitute(finding, |
| \ '^\(\%(\u\|s:\)\w*\).*', '\1', "") |
| endif |
| if exists("quits{finding}") |
| let debug_quits = debug_quits . quits{finding} |
| endif |
| endif |
| endif |
| endwhile |
| |
| " Close the buffer for the script and create an (empty) resultfile. |
| bwipeout |
| let resultfile = tempname() |
| exec "!>" . resultfile |
| |
| " Run the script in an extra vim. Switch to extra modus by passing the |
| " resultfile in ExtraVimResult. Redirect messages to the file specified as |
| " argument if any. Use ":debuggreedy" so that the commands provided on the |
| " pipe are consumed at the debug prompt. Use "-N" to enable command-line |
| " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid |
| " messing up the user's viminfo file. |
| let redirect = a:0 ? |
| \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : "" |
| exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect . |
| \ " -c 'debuggreedy|set viminfo+=nviminfo'" . |
| \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . |
| \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . |
| \ " -S " . extra_script |
| |
| " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout |
| " information provided by the extra Vim process to the test output. |
| let sum = 0 |
| exec "edit" resultfile |
| let line = 1 |
| while line <= line("$") |
| let theline = getline(line) |
| if theline =~ '^@R:' |
| exec 'Xout "' . substitute(substitute( |
| \ escape(escape(theline, '"'), '\"'), |
| \ '^@R:', '', ""), '@NL@', "\n", "g") . '"' |
| else |
| let sum = sum + getline(line) |
| endif |
| let line = line + 1 |
| endwhile |
| bwipeout |
| let g:Xpath = g:Xpath + sum |
| |
| " Delete the extra script and the resultfile. |
| call delete(extra_script) |
| call delete(resultfile) |
| |
| " Switch back to the buffer that was active when this function was entered. |
| exec "buffer" current_buffnr |
| |
| " Return 0. This protects extra scripts from being run in the main Vim |
| " process. |
| return 0 |
| endfunction |
| |
| |
| " ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2 |
| " |
| " Evaluates v:throwpoint and returns the throwpoint relative to the beginning of |
| " an ExtraVim script as passed by ExtraVim() in ExtraVimBegin. |
| " |
| " EXTRA_VIM_START - do not change or remove this line. |
| function! ExtraVimThrowpoint() |
| if !exists("g:ExtraVimBegin") |
| Xout "ExtraVimThrowpoint() used outside ExtraVim() script." |
| return v:throwpoint |
| endif |
| |
| if v:throwpoint =~ '^function\>' |
| return v:throwpoint |
| endif |
| |
| return "line " . |
| \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) . |
| \ " of ExtraVim() script" |
| endfunction |
| " EXTRA_VIM_STOP - do not change or remove this line. |
| |
| |
| " MakeScript() - Make a script file from a function. {{{2 |
| " |
| " Create a script that consists of the body of the function a:funcname. |
| " Replace any ":return" by a ":finish", any argument variable by a global |
| " variable, and and every ":call" by a ":source" for the next following argument |
| " in the variable argument list. This function is useful if similar tests are |
| " to be made for a ":return" from a function call or a ":finish" in a script |
| " file. |
| " |
| " In order to execute a function specifying an INTERRUPT location (see ExtraVim) |
| " as a script file, use ExecAsScript below. |
| " |
| " EXTRA_VIM_START - do not change or remove this line. |
| function! MakeScript(funcname, ...) |
| let script = tempname() |
| execute "redir! >" . script |
| execute "function" a:funcname |
| redir END |
| execute "edit" script |
| " Delete the "function" and the "endfunction" lines. Do not include the |
| " word "function" in the pattern since it might be translated if LANG is |
| " set. When MakeScript() is being debugged, this deletes also the debugging |
| " output of its line 3 and 4. |
| exec '1,/.*' . a:funcname . '(.*)/d' |
| /^\d*\s*endfunction\>/,$d |
| %s/^\d*//e |
| %s/return/finish/e |
| %s/\<a:\(\h\w*\)/g:\1/ge |
| normal gg0 |
| let cnt = 0 |
| while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0 |
| let cnt = cnt + 1 |
| s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/ |
| endwhile |
| g/^\s*$/d |
| write |
| bwipeout |
| return script |
| endfunction |
| " EXTRA_VIM_STOP - do not change or remove this line. |
| |
| |
| " ExecAsScript - Source a temporary script made from a function. {{{2 |
| " |
| " Make a temporary script file from the function a:funcname, ":source" it, and |
| " delete it afterwards. |
| " |
| " When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT |
| " location specified in the function. |
| " |
| " EXTRA_VIM_START - do not change or remove this line. |
| function! ExecAsScript(funcname) |
| " Make a script from the function passed as argument. |
| let script = MakeScript(a:funcname) |
| |
| " When running in an extra Vim process, add a file breakpoint for each |
| " function breakpoint set when the extra Vim process was invoked by |
| " ExtraVim(). |
| if exists("g:ExtraVimResult") |
| let bplist = tempname() |
| execute "redir! >" . bplist |
| breaklist |
| redir END |
| execute "edit" bplist |
| " Get the line number from the function breakpoint. Works also when |
| " LANG is set. |
| execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d' |
| %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e |
| let cnt = 0 |
| while cnt < line("$") |
| let cnt = cnt + 1 |
| if getline(cnt) != "" |
| execute "breakadd file" getline(cnt) script |
| endif |
| endwhile |
| bwipeout! |
| call delete(bplist) |
| endif |
| |
| " Source and delete the script. |
| exec "source" script |
| call delete(script) |
| endfunction |
| |
| com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>) |
| " EXTRA_VIM_STOP - do not change or remove this line. |
| |
| |
| " END_OF_TEST_ENVIRONMENT - do not change or remove this line. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 1: :endwhile in function {{{1 |
| " |
| " Detect if a broken loop is (incorrectly) reactivated by the |
| " :endwhile. Use a :return to prevent an endless loop, and make |
| " this test first to get a meaningful result on an error before other |
| " tests will hang. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| Xpath 1 " X: 1 |
| let first = 1 |
| XloopINIT 2 8 |
| while 1 |
| Xloop 1 " X: 2 + 0 * 16 |
| if first |
| Xloop 2 " X: 4 + 0 * 32 |
| let first = 0 |
| XloopNEXT |
| break |
| else |
| Xloop 4 " X: 0 + 0 * 64 |
| return |
| endif |
| endwhile |
| endfunction |
| |
| call F() |
| Xpath 128 " X: 128 |
| |
| function! G() |
| Xpath 256 " X: 256 + 0 * 2048 |
| let first = 1 |
| XloopINIT 512 8 |
| while 1 |
| Xloop 1 " X: 512 + 0 * 4096 |
| if first |
| Xloop 2 " X: 1024 + 0 * 8192 |
| let first = 0 |
| XloopNEXT |
| break |
| else |
| Xloop 4 " X: 0 + 0 * 16384 |
| return |
| endif |
| if 1 " unmatched :if |
| endwhile |
| endfunction |
| |
| call G() |
| Xpath 32768 " X: 32768 |
| |
| Xcheck 34695 |
| |
| " Leave F and G for execution as scripts in the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 2: :endwhile in script {{{1 |
| " |
| " Detect if a broken loop is (incorrectly) reactivated by the |
| " :endwhile. Use a :finish to prevent an endless loop, and place |
| " this test before others that might hang to get a meaningful result |
| " on an error. |
| " |
| " This test executes the bodies of the functions F and G from the |
| " previous test as script files (:return replaced by :finish). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| ExecAsScript F " X: 1 + 2 + 4 |
| Xpath 128 " X: 128 |
| |
| ExecAsScript G " X: 256 + 512 + 1024 |
| Xpath 32768 " X: 32768 |
| |
| unlet first |
| delfunction F |
| delfunction G |
| |
| Xcheck 34695 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 3: :if, :elseif, :while, :continue, :break {{{1 |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| if 1 |
| Xpath 1 " X: 1 |
| let loops = 3 |
| XloopINIT 2 512 |
| while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) |
| if loops <= 0 |
| let break_err = 1 |
| let loops = -1 |
| else " 3: 2: 1: |
| Xloop 1 " X: 2 + 2*512 + 2*512*512 |
| endif |
| if (loops == 2) |
| while loops == 2 " dummy loop |
| Xloop 2 " X: 4*512 |
| let loops = loops - 1 |
| continue " stop dummy loop |
| Xloop 4 " X: 0 |
| endwhile |
| XloopNEXT |
| continue " continue main loop |
| Xloop 8 " X: 0 |
| elseif (loops == 1) |
| let p = 1 |
| while p " dummy loop |
| Xloop 16 " X: 32*512*512 |
| let p = 0 |
| break " break dummy loop |
| Xloop 32 " X: 0 |
| endwhile |
| Xloop 64 " X: 128*512*512 |
| unlet p |
| break " break main loop |
| Xloop 128 " X: 0 |
| endif |
| if (loops > 0) |
| Xloop 256 " X: 512 |
| endif |
| while loops == 3 " dummy loop |
| let loops = loops - 1 |
| endwhile " end dummy loop |
| XloopNEXT |
| endwhile " end main loop |
| Xpath 268435456 " X: 1024*512*512 |
| else |
| Xpath 536870912 " X: 0 |
| endif |
| Xpath 1073741824 " X: 4096*512*512 |
| if exists("break_err") |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| unlet break_err |
| endif |
| |
| unlet loops |
| |
| Xcheck 1384648195 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 4: :return {{{1 |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| if 1 |
| Xpath 1 " X: 1 |
| let loops = 3 |
| XloopINIT 2 16 |
| while loops > 0 " 3: 2: 1: |
| Xloop 1 " X: 2 + 2*16 + 0*16*16 |
| if (loops == 2) |
| Xloop 2 " X: 4*16 |
| return |
| Xloop 4 " X: 0 |
| endif |
| Xloop 8 " X: 16 |
| let loops = loops - 1 |
| XloopNEXT |
| endwhile |
| Xpath 8192 " X: 0 |
| else |
| Xpath 16384 " X: 0 |
| endif |
| endfunction |
| |
| call F() |
| Xpath 32768 " X: 8*16*16*16 |
| |
| Xcheck 32883 |
| |
| " Leave F for execution as a script in the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 5: :finish {{{1 |
| " |
| " This test executes the body of the function F from the previous test |
| " as a script file (:return replaced by :finish). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| ExecAsScript F " X: 1 + 2 + 2*16 + 4*16 + 16 |
| Xpath 32768 " X: 32768 |
| |
| unlet loops |
| delfunction F |
| |
| Xcheck 32883 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 6: Defining functions in :while loops {{{1 |
| " |
| " Functions can be defined inside other functions. An inner function |
| " gets defined when the outer function is executed. Functions may |
| " also be defined inside while loops. Expressions in braces for |
| " defining the function name are allowed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| " The command CALL collects the argument of all its invocations in "calls" |
| " when used from a function (that is, when the global variable "calls" needs |
| " the "g:" prefix). This is to check that the function code is skipped when |
| " the function is defined. For inner functions, do so only if the outer |
| " function is not being executed. |
| " |
| let calls = "" |
| com! -nargs=1 CALL |
| \ if !exists("calls") && !exists("outer") | |
| \ let g:calls = g:calls . <args> | |
| \ endif |
| |
| |
| XloopINIT! 1 16 |
| |
| let i = 0 |
| while i < 3 |
| |
| XloopNEXT |
| let i = i + 1 |
| |
| if i == 1 |
| Xloop 1 " X: 1 |
| function! F1(arg) |
| CALL a:arg |
| let outer = 1 |
| |
| XloopINIT! 4096 4 |
| let j = 0 |
| while j < 1 |
| XloopNEXT |
| Xloop 1 " X: 4096 |
| let j = j + 1 |
| function! G1(arg) |
| CALL a:arg |
| endfunction |
| Xloop 2 " X: 8192 |
| endwhile |
| endfunction |
| Xloop 2 " X: 2 |
| |
| continue |
| endif |
| |
| Xloop 4 " X: 4 * (16 + 256) |
| function! F{i}(i, arg) |
| CALL a:arg |
| let outer = 1 |
| |
| XloopINIT! 16384 4 |
| if a:i == 3 |
| XloopNEXT |
| XloopNEXT |
| XloopNEXT |
| endif |
| let k = 0 |
| while k < 3 |
| XloopNEXT |
| Xloop 1 " X: 16384*(1+4+16+64+256+1024) |
| let k = k + 1 |
| function! G{a:i}{k}(arg) |
| CALL a:arg |
| endfunction |
| Xloop 2 " X: 32768*(1+4+16+64+256+1024) |
| endwhile |
| endfunction |
| Xloop 8 " X: 8 * (16 + 256) |
| |
| endwhile |
| |
| if exists("*G1") |
| Xpath 67108864 " X: 0 |
| endif |
| if exists("*F1") |
| call F1("F1") |
| if exists("*G1") |
| call G1("G1") |
| endif |
| endif |
| |
| if exists("G21") || exists("G21") || exists("G21") |
| Xpath 134217728 " X: 0 |
| endif |
| if exists("*F2") |
| call F2(2, "F2") |
| if exists("*G21") |
| call G21("G21") |
| endif |
| if exists("*G22") |
| call G22("G22") |
| endif |
| if exists("*G23") |
| call G23("G23") |
| endif |
| endif |
| |
| if exists("G31") || exists("G31") || exists("G31") |
| Xpath 268435456 " X: 0 |
| endif |
| if exists("*F3") |
| call F3(3, "F3") |
| if exists("*G31") |
| call G31("G31") |
| endif |
| if exists("*G32") |
| call G32("G32") |
| endif |
| if exists("*G33") |
| call G33("G33") |
| endif |
| endif |
| |
| Xpath 536870912 " X: 536870912 |
| |
| if calls != "F1G1F2G21G22G23F3G31G32G33" |
| Xpath 1073741824 " X: 0 |
| Xout "calls is" calls |
| endif |
| |
| delfunction F1 |
| delfunction G1 |
| delfunction F2 |
| delfunction G21 |
| delfunction G22 |
| delfunction G23 |
| delfunction G31 |
| delfunction G32 |
| delfunction G33 |
| |
| endif |
| |
| Xcheck 603978947 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 7: Continuing on errors outside functions {{{1 |
| " |
| " On an error outside a function, the script processing continues |
| " at the line following the outermost :endif or :endwhile. When not |
| " inside an :if or :while, the script processing continues at the next |
| " line. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if 1 |
| Xpath 1 " X: 1 |
| while 1 |
| Xpath 2 " X: 2 |
| asdf |
| Xpath 4 " X: 0 |
| break |
| endwhile | Xpath 8 " X: 0 |
| Xpath 16 " X: 0 |
| endif | Xpath 32 " X: 0 |
| Xpath 64 " X: 64 |
| |
| while 1 |
| Xpath 128 " X: 128 |
| if 1 |
| Xpath 256 " X: 256 |
| asdf |
| Xpath 512 " X: 0 |
| endif | Xpath 1024 " X: 0 |
| Xpath 2048 " X: 0 |
| break |
| endwhile | Xpath 4096 " X: 0 |
| Xpath 8192 " X: 8192 |
| |
| asdf |
| Xpath 16384 " X: 16384 |
| |
| asdf | Xpath 32768 " X: 0 |
| Xpath 65536 " X: 65536 |
| |
| Xcheck 90563 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 8: Aborting and continuing on errors inside functions {{{1 |
| " |
| " On an error inside a function without the "abort" attribute, the |
| " script processing continues at the next line (unless the error was |
| " in a :return command). On an error inside a function with the |
| " "abort" attribute, the function is aborted and the script processing |
| " continues after the function call; the value -1 is returned then. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| if 1 |
| Xpath 1 " X: 1 |
| while 1 |
| Xpath 2 " X: 2 |
| asdf |
| Xpath 4 " X: 4 |
| asdf | Xpath 8 " X: 0 |
| Xpath 16 " X: 16 |
| break |
| endwhile |
| Xpath 32 " X: 32 |
| endif | Xpath 64 " X: 64 |
| Xpath 128 " X: 128 |
| |
| while 1 |
| Xpath 256 " X: 256 |
| if 1 |
| Xpath 512 " X: 512 |
| asdf |
| Xpath 1024 " X: 1024 |
| asdf | Xpath 2048 " X: 0 |
| Xpath 4096 " X: 4096 |
| endif |
| Xpath 8192 " X: 8192 |
| break |
| endwhile | Xpath 16384 " X: 16384 |
| Xpath 32768 " X: 32768 |
| |
| return novar " returns (default return value 0) |
| Xpath 65536 " X: 0 |
| return 1 " not reached |
| endfunction |
| |
| function! G() abort |
| if 1 |
| Xpath 131072 " X: 131072 |
| while 1 |
| Xpath 262144 " X: 262144 |
| asdf " returns -1 |
| Xpath 524288 " X: 0 |
| break |
| endwhile |
| Xpath 1048576 " X: 0 |
| endif | Xpath 2097152 " X: 0 |
| Xpath Xpath 4194304 " X: 0 |
| |
| return -4 " not reached |
| endfunction |
| |
| function! H() abort |
| while 1 |
| Xpath 8388608 " X: 8388608 |
| if 1 |
| Xpath 16777216 " X: 16777216 |
| asdf " returns -1 |
| Xpath 33554432 " X: 0 |
| endif |
| Xpath 67108864 " X: 0 |
| break |
| endwhile | Xpath 134217728 " X: 0 |
| Xpath 268435456 " X: 0 |
| |
| return -4 " not reached |
| endfunction |
| |
| " Aborted functions (G and H) return -1. |
| let sum = (F() + 1) - 4*G() - 8*H() |
| Xpath 536870912 " X: 536870912 |
| if sum != 13 |
| Xpath 1073741824 " X: 0 |
| Xout "sum is" sum |
| endif |
| |
| unlet sum |
| delfunction F |
| delfunction G |
| delfunction H |
| |
| Xcheck 562493431 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 9: Continuing after aborted functions {{{1 |
| " |
| " When a function with the "abort" attribute is aborted due to an |
| " error, the next function back in the call hierarchy without an |
| " "abort" attribute continues; the value -1 is returned then. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() abort |
| Xpath 1 " X: 1 |
| let result = G() " not aborted |
| Xpath 2 " X: 2 |
| if result != 2 |
| Xpath 4 " X: 0 |
| endif |
| return 1 |
| endfunction |
| |
| function! G() " no abort attribute |
| Xpath 8 " X: 8 |
| if H() != -1 " aborted |
| Xpath 16 " X: 0 |
| endif |
| Xpath 32 " X: 32 |
| return 2 |
| endfunction |
| |
| function! H() abort |
| Xpath 64 " X: 64 |
| call I() " aborted |
| Xpath 128 " X: 0 |
| return 4 |
| endfunction |
| |
| function! I() abort |
| Xpath 256 " X: 256 |
| asdf " error |
| Xpath 512 " X: 0 |
| return 8 |
| endfunction |
| |
| if F() != 1 |
| Xpath 1024 " X: 0 |
| endif |
| |
| delfunction F |
| delfunction G |
| delfunction H |
| delfunction I |
| |
| Xcheck 363 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 10: :if, :elseif, :while argument parsing {{{1 |
| " |
| " A '"' or '|' in an argument expression must not be mixed up with |
| " a comment or a next command after a bar. Parsing errors should |
| " be recognized. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| if 1 || strlen("\"") | Xpath 1 " X: 1 |
| Xpath 2 " X: 2 |
| endif |
| Xpath 4 " X: 4 |
| |
| if 0 |
| elseif 1 || strlen("\"") | Xpath 8 " X: 8 |
| Xpath 16 " X: 16 |
| endif |
| Xpath 32 " X: 32 |
| |
| while 1 || strlen("\"") | Xpath 64 " X: 64 |
| Xpath 128 " X: 128 |
| break |
| endwhile |
| Xpath 256 " X: 256 |
| |
| let v:errmsg = "" |
| if 1 ||| strlen("\"") | Xpath 512 " X: 0 |
| Xpath 1024 " X: 0 |
| endif |
| Xpath 2048 " X: 2048 |
| if !MSG('E15', "Invalid expression") |
| Xpath 4096 " X: 0 |
| endif |
| |
| let v:errmsg = "" |
| if 0 |
| elseif 1 ||| strlen("\"") | Xpath 8192 " X: 0 |
| Xpath 16384 " X: 0 |
| endif |
| Xpath 32768 " X: 32768 |
| if !MSG('E15', "Invalid expression") |
| Xpath 65536 " X: 0 |
| endif |
| |
| let v:errmsg = "" |
| while 1 ||| strlen("\"") | Xpath 131072 " X: 0 |
| Xpath 262144 " X: 0 |
| break |
| endwhile |
| Xpath 524288 " X: 524288 |
| if !MSG('E15', "Invalid expression") |
| Xpath 1048576 " X: 0 |
| endif |
| |
| delfunction MSG |
| |
| Xcheck 559615 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 11: :if, :elseif, :while argument evaluation after abort {{{1 |
| " |
| " When code is skipped over due to an error, the boolean argument to |
| " an :if, :elseif, or :while must not be evaluated. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let calls = 0 |
| |
| function! P(num) |
| let g:calls = g:calls + a:num " side effect on call |
| return 0 |
| endfunction |
| |
| if 1 |
| Xpath 1 " X: 1 |
| asdf " error |
| Xpath 2 " X: 0 |
| if P(1) " should not be called |
| Xpath 4 " X: 0 |
| elseif !P(2) " should not be called |
| Xpath 8 " X: 0 |
| else |
| Xpath 16 " X: 0 |
| endif |
| Xpath 32 " X: 0 |
| while P(4) " should not be called |
| Xpath 64 " X: 0 |
| endwhile |
| Xpath 128 " X: 0 |
| endif |
| |
| if calls % 2 |
| Xpath 256 " X: 0 |
| endif |
| if (calls/2) % 2 |
| Xpath 512 " X: 0 |
| endif |
| if (calls/4) % 2 |
| Xpath 1024 " X: 0 |
| endif |
| Xpath 2048 " X: 2048 |
| |
| unlet calls |
| delfunction P |
| |
| Xcheck 2049 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 12: Expressions in braces in skipped code {{{1 |
| " |
| " In code skipped over due to an error or inactive conditional, |
| " an expression in braces as part of a variable or function name |
| " should not be evaluated. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT 1 8 |
| |
| function! NULL() |
| Xloop 1 " X: 0 |
| return 0 |
| endfunction |
| |
| function! ZERO() |
| Xloop 2 " X: 0 |
| return 0 |
| endfunction |
| |
| function! F0() |
| Xloop 4 " X: 0 |
| endfunction |
| |
| function! F1(arg) |
| Xpath 4096 " X: 0 |
| endfunction |
| |
| let V0 = 1 |
| |
| Xpath 8192 " X: 8192 |
| echo 0 ? F{NULL() + V{ZERO()}}() : 1 |
| XloopNEXT |
| |
| Xpath 16384 " X: 16384 |
| if 0 |
| Xpath 32768 " X: 0 |
| call F{NULL() + V{ZERO()}}() |
| endif |
| XloopNEXT |
| |
| Xpath 65536 " X: 65536 |
| if 1 |
| asdf " error |
| Xpath 131072 " X: 0 |
| call F1(F{NULL() + V{ZERO()}}()) |
| endif |
| XloopNEXT |
| |
| Xpath 262144 " X: 262144 |
| if 1 |
| asdf " error |
| Xpath 524288 " X: 0 |
| call F{NULL() + V{ZERO()}}() |
| endif |
| |
| Xcheck 352256 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 13: Failure in argument evaluation for :while {{{1 |
| " |
| " A failure in the expression evaluation for the condition of a :while |
| " causes the whole :while loop until the matching :endwhile being |
| " ignored. Continuation is at the next following line. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| Xpath 1 " X: 1 |
| while asdf |
| Xpath 2 " X: 0 |
| while 1 |
| Xpath 4 " X: 0 |
| break |
| endwhile |
| Xpath 8 " X: 0 |
| break |
| endwhile |
| Xpath 16 " X: 16 |
| |
| while asdf | Xpath 32 | endwhile | Xpath 64 " X: 0 |
| Xpath 128 " X: 128 |
| |
| Xcheck 145 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 14: Failure in argument evaluation for :if {{{1 |
| " |
| " A failure in the expression evaluation for the condition of an :if |
| " does not cause the corresponding :else or :endif being matched to |
| " a previous :if/:elseif. Neither of both branches of the failed :if |
| " are executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| XloopINIT 1 256 |
| |
| function! F() |
| Xloop 1 " X: 1 + 256 * 1 |
| let x = 0 |
| if x " false |
| Xloop 2 " X: 0 + 256 * 0 |
| elseif !x " always true |
| Xloop 4 " X: 4 + 256 * 4 |
| let x = 1 |
| if g:boolvar " possibly undefined |
| Xloop 8 " X: 8 + 256 * 0 |
| else |
| Xloop 16 " X: 0 + 256 * 0 |
| endif |
| Xloop 32 " X: 32 + 256 * 32 |
| elseif x " never executed |
| Xloop 64 " X: 0 + 256 * 0 |
| endif |
| Xloop 128 " X: 128 + 256 * 128 |
| endfunction |
| |
| let boolvar = 1 |
| call F() |
| |
| XloopNEXT |
| unlet boolvar |
| call F() |
| |
| delfunction F |
| |
| Xcheck 42413 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 15: Failure in argument evaluation for :if (bar) {{{1 |
| " |
| " Like previous test, except that the failing :if ... | ... | :endif |
| " is in a single line. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| XloopINIT 1 256 |
| |
| function! F() |
| Xloop 1 " X: 1 + 256 * 1 |
| let x = 0 |
| if x " false |
| Xloop 2 " X: 0 + 256 * 0 |
| elseif !x " always true |
| Xloop 4 " X: 4 + 256 * 4 |
| let x = 1 |
| if g:boolvar | Xloop 8 | else | Xloop 16 | endif " X: 8 |
| Xloop 32 " X: 32 + 256 * 32 |
| elseif x " never executed |
| Xloop 64 " X: 0 + 256 * 0 |
| endif |
| Xloop 128 " X: 128 + 256 * 128 |
| endfunction |
| |
| let boolvar = 1 |
| call F() |
| |
| XloopNEXT |
| unlet boolvar |
| call F() |
| |
| delfunction F |
| |
| Xcheck 42413 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 16: Double :else or :elseif after :else {{{1 |
| " |
| " Multiple :elses or an :elseif after an :else are forbidden. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() abort |
| if 0 |
| Xpath 1 " X: 0 |
| else |
| Xpath 2 " X: 2 |
| else " aborts function |
| Xpath 4 " X: 0 |
| endif |
| endfunction |
| |
| function! G() abort |
| if 0 |
| Xpath 8 " X: 0 |
| else |
| Xpath 16 " X: 16 |
| elseif 1 " aborts function |
| Xpath 32 " X: 0 |
| else |
| Xpath 64 " X: 0 |
| endif |
| endfunction |
| |
| function! H() abort |
| if 0 |
| Xpath 128 " X: 0 |
| elseif 0 |
| Xpath 256 " X: 0 |
| else |
| Xpath 512 " X: 512 |
| else " aborts function |
| Xpath 1024 " X: 0 |
| endif |
| endfunction |
| |
| function! I() abort |
| if 0 |
| Xpath 2048 " X: 0 |
| elseif 0 |
| Xpath 4096 " X: 0 |
| else |
| Xpath 8192 " X: 8192 |
| elseif 1 " aborts function |
| Xpath 16384 " X: 0 |
| else |
| Xpath 32768 " X: 0 |
| endif |
| endfunction |
| |
| call F() |
| call G() |
| call H() |
| call I() |
| |
| delfunction F |
| delfunction G |
| delfunction H |
| delfunction I |
| |
| Xcheck 8722 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 |
| " |
| " The :while/:endwhile takes precedence in nesting over an unclosed |
| " :if or an unopened :endif. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| let messages = "" |
| |
| " While loops inside a function are continued on error. |
| function! F() |
| let v:errmsg = "" |
| XloopINIT 1 16 |
| let loops = 3 |
| while loops > 0 |
| let loops = loops - 1 " 2: 1: 0: |
| Xloop 1 " X: 1 + 1*16 + 1*16*16 |
| if (loops == 1) |
| Xloop 2 " X: 2*16 |
| XloopNEXT |
| continue |
| elseif (loops == 0) |
| Xloop 4 " X: 4*16*16 |
| break |
| elseif 1 |
| Xloop 8 " X: 8 |
| XloopNEXT |
| " endif missing! |
| endwhile " :endwhile after :if 1 |
| Xpath 4096 " X: 16*16*16 |
| if MSG('E171', "Missing :endif") |
| let g:messages = g:messages . "A" |
| endif |
| |
| let v:errmsg = "" |
| XloopINIT! 8192 4 |
| let loops = 2 |
| while loops > 0 " 2: 1: |
| XloopNEXT |
| let loops = loops - 1 |
| Xloop 1 " X: 8192 + 8192*4 |
| if 0 |
| Xloop 2 " X: 0 |
| " endif missing |
| endwhile " :endwhile after :if 0 |
| Xpath 131072 " X: 8192*4*4 |
| if MSG('E171', "Missing :endif") |
| let g:messages = g:messages . "B" |
| endif |
| |
| let v:errmsg = "" |
| XloopINIT 262144 4 |
| let loops = 2 |
| while loops > 0 " 2: 1: |
| let loops = loops - 1 |
| Xloop 1 " X: 262144 + 262144 * 4 |
| " if missing! |
| endif " :endif without :if in while |
| Xloop 2 " X: 524288 + 524288 * 4 |
| XloopNEXT |
| endwhile |
| Xpath 4194304 " X: 262144*4*4 |
| if MSG('E580', ":endif without :if") |
| let g:messages = g:messages . "C" |
| endif |
| endfunction |
| |
| call F() |
| |
| " Error continuation outside a function is at the outermost :endwhile or :endif. |
| let v:errmsg = "" |
| XloopINIT! 8388608 4 |
| let loops = 2 |
| while loops > 0 " 2: 1: |
| XloopNEXT |
| let loops = loops - 1 |
| Xloop 1 " X: 8388608 + 0 * 4 |
| if 0 |
| Xloop 2 " X: 0 |
| " endif missing! Following :endwhile fails. |
| endwhile | Xpath 134217728 " X: 0 |
| Xpath 268435456 " X: 2*8388608*4*4 |
| if MSG('E171', "Missing :endif") |
| let messages = g:messages . "D" |
| endif |
| |
| if messages != "ABCD" |
| Xpath 536870912 " X: 0 |
| Xout "messages is" messages "instead of ABCD" |
| endif |
| |
| unlet loops messages |
| delfunction F |
| delfunction MSG |
| |
| Xcheck 285127993 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 18: Interrupt (Ctrl-C pressed) {{{1 |
| " |
| " On an interrupt, the script processing is terminated immediately. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| if 1 |
| Xpath 1 " X: 1 |
| while 1 |
| Xpath 2 " X: 2 |
| if 1 |
| Xpath 4 " X: 4 |
| "INTERRUPT |
| Xpath 8 " X: 0 |
| break |
| finish |
| endif | Xpath 16 " X: 0 |
| Xpath 32 " X: 0 |
| endwhile | Xpath 64 " X: 0 |
| Xpath 128 " X: 0 |
| endif | Xpath 256 " X: 0 |
| Xpath 512 " X: 0 |
| endif |
| |
| if ExtraVim() |
| try |
| Xpath 1024 " X: 1024 |
| "INTERRUPT |
| Xpath 2048 " X: 0 |
| endtry | Xpath 4096 " X: 0 |
| Xpath 8192 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function! F() |
| if 1 |
| Xpath 16384 " X: 16384 |
| while 1 |
| Xpath 32768 " X: 32768 |
| if 1 |
| Xpath 65536 " X: 65536 |
| "INTERRUPT |
| Xpath 131072 " X: 0 |
| break |
| return |
| endif | Xpath 262144 " X: 0 |
| Xpath Xpath 524288 " X: 0 |
| endwhile | Xpath 1048576 " X: 0 |
| Xpath Xpath 2097152 " X: 0 |
| endif | Xpath Xpath 4194304 " X: 0 |
| Xpath Xpath 8388608 " X: 0 |
| endfunction |
| |
| call F() | Xpath 16777216 " X: 0 |
| Xpath 33554432 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function! G() |
| try |
| Xpath 67108864 " X: 67108864 |
| "INTERRUPT |
| Xpath 134217728 " X: 0 |
| endtry | Xpath 268435456 " X: 0 |
| Xpath 536870912 " X: 0 |
| endfunction |
| |
| call G() | Xpath 1073741824 " X: 0 |
| " The Xpath command does not accept 2^31 (negative); display explicitly: |
| exec "!echo 2147483648 >>" . g:ExtraVimResult |
| " X: 0 |
| endif |
| |
| Xcheck 67224583 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 19: Aborting on errors inside :try/:endtry {{{1 |
| " |
| " An error in a command dynamically enclosed in a :try/:endtry region |
| " aborts script processing immediately. It does not matter whether |
| " the failing command is outside or inside a function and whether a |
| " function has an "abort" attribute. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| function! F() abort |
| Xpath 1 " X: 1 |
| asdf |
| Xpath 2 " X: 0 |
| endfunction |
| |
| try |
| Xpath 4 " X: 4 |
| call F() |
| Xpath 8 " X: 0 |
| endtry | Xpath 16 " X: 0 |
| Xpath 32 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function! G() |
| Xpath 64 " X: 64 |
| asdf |
| Xpath 128 " X: 0 |
| endfunction |
| |
| try |
| Xpath 256 " X: 256 |
| call G() |
| Xpath 512 " X: 0 |
| endtry | Xpath 1024 " X: 0 |
| Xpath 2048 " X: 0 |
| endif |
| |
| if ExtraVim() |
| try |
| Xpath 4096 " X: 4096 |
| asdf |
| Xpath 8192 " X: 0 |
| endtry | Xpath 16384 " X: 0 |
| Xpath 32768 " X: 0 |
| endif |
| |
| if ExtraVim() |
| if 1 |
| try |
| Xpath 65536 " X: 65536 |
| asdf |
| Xpath 131072 " X: 0 |
| endtry | Xpath 262144 " X: 0 |
| endif | Xpath 524288 " X: 0 |
| Xpath 1048576 " X: 0 |
| endif |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| try |
| Xpath 2097152 " X: 2097152 |
| asdf |
| Xpath 4194304 " X: 0 |
| endtry | Xpath 8388608 " X: 0 |
| endwhile | Xpath 16777216 " X: 0 |
| Xpath 33554432 " X: 0 |
| endif |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| " try |
| Xpath 67108864 " X: 67108864 |
| endwhile | Xpath 134217728 " X: 0 |
| Xpath 268435456 " X: 0 |
| endif |
| |
| Xcheck 69275973 |
| "------------------------------------------------------------------------------- |
| " Test 20: Aborting on errors after :try/:endtry {{{1 |
| " |
| " When an error occurs after the last active :try/:endtry region has |
| " been left, termination behavior is as if no :try/:endtry has been |
| " seen. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| try |
| Xpath 1 " X: 1 |
| endtry |
| asdf |
| endwhile | Xpath 2 " X: 0 |
| Xpath 4 " X: 4 |
| endif |
| |
| if ExtraVim() |
| while 1 |
| try |
| Xpath 8 " X: 8 |
| break |
| Xpath 16 " X: 0 |
| endtry |
| endwhile |
| Xpath 32 " X: 32 |
| asdf |
| Xpath 64 " X: 64 |
| endif |
| |
| if ExtraVim() |
| while 1 |
| try |
| Xpath 128 " X: 128 |
| break |
| Xpath 256 " X: 0 |
| finally |
| Xpath 512 " X: 512 |
| endtry |
| endwhile |
| Xpath 1024 " X: 1024 |
| asdf |
| Xpath 2048 " X: 2048 |
| endif |
| |
| if ExtraVim() |
| while 1 |
| try |
| Xpath 4096 " X: 4096 |
| finally |
| Xpath 8192 " X: 8192 |
| break |
| Xpath 16384 " X: 0 |
| endtry |
| endwhile |
| Xpath 32768 " X: 32768 |
| asdf |
| Xpath 65536 " X: 65536 |
| endif |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| try |
| Xpath 131072 " X: 131072 |
| continue |
| Xpath 262144 " X: 0 |
| endtry |
| endwhile |
| Xpath 524288 " X: 524288 |
| asdf |
| Xpath 1048576 " X: 1048576 |
| endif |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| try |
| Xpath 2097152 " X: 2097152 |
| continue |
| Xpath 4194304 " X: 0 |
| finally |
| Xpath 8388608 " X: 8388608 |
| endtry |
| endwhile |
| Xpath 16777216 " X: 16777216 |
| asdf |
| Xpath 33554432 " X: 33554432 |
| endif |
| |
| if ExtraVim() |
| let p = 1 |
| while p |
| let p = 0 |
| try |
| Xpath 67108864 " X: 67108864 |
| finally |
| Xpath 134217728 " X: 134217728 |
| continue |
| Xpath 268435456 " X: 0 |
| endtry |
| endwhile |
| Xpath 536870912 " X: 536870912 |
| asdf |
| Xpath 1073741824 " X: 1073741824 |
| endif |
| |
| Xcheck 1874575085 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 |
| " |
| " If a :try conditional stays inactive due to a preceding :continue, |
| " :break, :return, or :finish, its :finally clause should not be |
| " executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| function F() |
| let loops = 2 |
| XloopINIT! 1 256 |
| while loops > 0 |
| XloopNEXT |
| let loops = loops - 1 |
| try |
| if loops == 1 |
| Xloop 1 " X: 1 |
| continue |
| Xloop 2 " X: 0 |
| elseif loops == 0 |
| Xloop 4 " X: 4*256 |
| break |
| Xloop 8 " X: 0 |
| endif |
| |
| try " inactive |
| Xloop 16 " X: 0 |
| finally |
| Xloop 32 " X: 0 |
| endtry |
| finally |
| Xloop 64 " X: 64 + 64*256 |
| endtry |
| Xloop 128 " X: 0 |
| endwhile |
| |
| try |
| Xpath 65536 " X: 65536 |
| return |
| Xpath 131072 " X: 0 |
| try " inactive |
| Xpath 262144 " X: 0 |
| finally |
| Xpath 524288 " X: 0 |
| endtry |
| finally |
| Xpath 1048576 " X: 1048576 |
| endtry |
| Xpath 2097152 " X: 0 |
| endfunction |
| |
| try |
| Xpath 4194304 " X: 4194304 |
| call F() |
| Xpath 8388608 " X: 8388608 |
| finish |
| Xpath 16777216 " X: 0 |
| try " inactive |
| Xpath 33554432 " X: 0 |
| finally |
| Xpath 67108864 " X: 0 |
| endtry |
| finally |
| Xpath 134217728 " X: 134217728 |
| endtry |
| Xpath 268435456 " X: 0 |
| endif |
| |
| Xcheck 147932225 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 22: :finally for a :try after an error/interrupt/:throw {{{1 |
| " |
| " If a :try conditional stays inactive due to a preceding error or |
| " interrupt or :throw, its :finally clause should not be executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| function! Error() |
| try |
| asdf " aborting error, triggering error exception |
| endtry |
| endfunction |
| |
| Xpath 1 " X: 1 |
| call Error() |
| Xpath 2 " X: 0 |
| |
| if 1 " not active due to error |
| try " not active since :if inactive |
| Xpath 4 " X: 0 |
| finally |
| Xpath 8 " X: 0 |
| endtry |
| endif |
| |
| try " not active due to error |
| Xpath 16 " X: 0 |
| finally |
| Xpath 32 " X: 0 |
| endtry |
| endif |
| |
| if ExtraVim() |
| function! Interrupt() |
| try |
| "INTERRUPT " triggering interrupt exception |
| endtry |
| endfunction |
| |
| Xpath 64 " X: 64 |
| call Interrupt() |
| Xpath 128 " X: 0 |
| |
| if 1 " not active due to interrupt |
| try " not active since :if inactive |
| Xpath 256 " X: 0 |
| finally |
| Xpath 512 " X: 0 |
| endtry |
| endif |
| |
| try " not active due to interrupt |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 0 |
| endtry |
| endif |
| |
| if ExtraVim() |
| function! Throw() |
| throw "xyz" |
| endfunction |
| |
| Xpath 4096 " X: 4096 |
| call Throw() |
| Xpath 8192 " X: 0 |
| |
| if 1 " not active due to :throw |
| try " not active since :if inactive |
| Xpath 16384 " X: 0 |
| finally |
| Xpath 32768 " X: 0 |
| endtry |
| endif |
| |
| try " not active due to :throw |
| Xpath 65536 " X: 0 |
| finally |
| Xpath 131072 " X: 0 |
| endtry |
| endif |
| |
| Xcheck 4161 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 23: :catch clauses for a :try after a :throw {{{1 |
| " |
| " If a :try conditional stays inactive due to a preceding :throw, |
| " none of its :catch clauses should be executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| try |
| Xpath 1 " X: 1 |
| throw "xyz" |
| Xpath 2 " X: 0 |
| |
| if 1 " not active due to :throw |
| try " not active since :if inactive |
| Xpath 4 " X: 0 |
| catch /xyz/ |
| Xpath 8 " X: 0 |
| endtry |
| endif |
| catch /xyz/ |
| Xpath 16 " X: 16 |
| endtry |
| |
| Xpath 32 " X: 32 |
| throw "abc" |
| Xpath 64 " X: 0 |
| |
| try " not active due to :throw |
| Xpath 128 " X: 0 |
| catch /abc/ |
| Xpath 256 " X: 0 |
| endtry |
| endif |
| |
| Xcheck 49 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 24: :endtry for a :try after a :throw {{{1 |
| " |
| " If a :try conditional stays inactive due to a preceding :throw, |
| " its :endtry should not rethrow the exception to the next surrounding |
| " active :try conditional. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| try " try 1 |
| try " try 2 |
| Xpath 1 " X: 1 |
| throw "xyz" " makes try 2 inactive |
| Xpath 2 " X: 0 |
| |
| try " try 3 |
| Xpath 4 " X: 0 |
| endtry " no rethrow to try 1 |
| catch /xyz/ " should catch although try 2 inactive |
| Xpath 8 " X: 8 |
| endtry |
| catch /xyz/ " try 1 active, but exception already caught |
| Xpath 16 " X: 0 |
| endtry |
| Xpath 32 " X: 32 |
| endif |
| |
| Xcheck 41 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 25: Executing :finally clauses on normal control flow {{{1 |
| " |
| " Control flow in a :try conditional should always fall through to its |
| " :finally clause. A :finally clause of a :try conditional inside an |
| " inactive conditional should never be executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| let loops = 3 |
| XloopINIT 1 256 |
| while loops > 0 " 3: 2: 1: |
| Xloop 1 " X: 1 + 1*256 + 1*256*256 |
| if loops >= 2 |
| try |
| Xloop 2 " X: 2 + 2*256 |
| if loops == 2 |
| try |
| Xloop 4 " X: 4*256 |
| finally |
| Xloop 8 " X: 8*256 |
| endtry |
| endif |
| finally |
| Xloop 16 " X: 16 + 16*256 |
| if loops == 2 |
| try |
| Xloop 32 " X: 32*256 |
| finally |
| Xloop 64 " X: 64*256 |
| endtry |
| endif |
| endtry |
| endif |
| Xloop 128 " X: 128 + 128*256 + 128*256*256 |
| let loops = loops - 1 |
| XloopNEXT |
| endwhile |
| Xpath 16777216 " X: 16777216 |
| endfunction |
| |
| if 1 |
| try |
| Xpath 33554432 " X: 33554432 |
| call F() |
| Xpath 67108864 " X: 67108864 |
| finally |
| Xpath 134217728 " X: 134217728 |
| endtry |
| else |
| try |
| Xpath 268435456 " X: 0 |
| finally |
| Xpath 536870912 " X: 0 |
| endtry |
| endif |
| |
| delfunction F |
| |
| Xcheck 260177811 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 26: Executing :finally clauses after :continue or :break {{{1 |
| " |
| " For a :continue or :break dynamically enclosed in a :try/:endtry |
| " region inside the next surrounding :while/:endwhile, if the |
| " :continue/:break is before the :finally, the :finally clause is |
| " executed first. If the :continue/:break is after the :finally, the |
| " :finally clause is broken (like an :if/:endif region). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| try |
| let loops = 3 |
| XloopINIT! 1 32 |
| while loops > 0 |
| XloopNEXT |
| try |
| try |
| if loops == 2 " 3: 2: 1: |
| Xloop 1 " X: 1*32 |
| let loops = loops - 1 |
| continue |
| elseif loops == 1 |
| Xloop 2 " X: 2*32*32 |
| break |
| finish |
| endif |
| Xloop 4 " X: 4 |
| endtry |
| finally |
| Xloop 8 " X: 8 + 8*32 + 8*32*32 |
| endtry |
| Xloop 16 " X: 16 |
| let loops = loops - 1 |
| endwhile |
| Xpath 32768 " X: 32768 |
| finally |
| Xpath 65536 " X: 65536 |
| let loops = 3 |
| XloopINIT 131072 16 |
| while loops > 0 |
| try |
| finally |
| try |
| if loops == 2 |
| Xloop 1 " X: 131072*16 |
| let loops = loops - 1 |
| XloopNEXT |
| continue |
| elseif loops == 1 |
| Xloop 2 " X: 131072*2*16*16 |
| break |
| finish |
| endif |
| endtry |
| Xloop 4 " X: 131072*4 |
| endtry |
| Xloop 8 " X: 131072*8 |
| let loops = loops - 1 |
| XloopNEXT |
| endwhile |
| Xpath 536870912 " X: 536870912 |
| endtry |
| Xpath 1073741824 " X: 1073741824 |
| |
| unlet loops |
| |
| Xcheck 1681500476 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 27: Executing :finally clauses after :return {{{1 |
| " |
| " For a :return command dynamically enclosed in a :try/:endtry region, |
| " :finally clauses are executed and the called function is ended. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| try |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| return |
| Xpath 4 " X: 0 |
| finally |
| Xpath 8 " X: 8 |
| endtry |
| Xpath 16 " X: 0 |
| finally |
| Xpath 32 " X: 32 |
| endtry |
| Xpath 64 " X: 0 |
| endfunction |
| |
| function! G() |
| try |
| Xpath 128 " X: 128 |
| return |
| Xpath 256 " X: 0 |
| finally |
| Xpath 512 " X: 512 |
| call F() |
| Xpath 1024 " X: 1024 |
| endtry |
| Xpath 2048 " X: 0 |
| endfunction |
| |
| function! H() |
| try |
| Xpath 4096 " X: 4096 |
| call G() |
| Xpath 8192 " X: 8192 |
| finally |
| Xpath 16384 " X: 16384 |
| return |
| Xpath 32768 " X: 0 |
| endtry |
| Xpath 65536 " X: 0 |
| endfunction |
| |
| try |
| Xpath 131072 " X: 131072 |
| call H() |
| Xpath 262144 " X: 262144 |
| finally |
| Xpath 524288 " X: 524288 |
| endtry |
| Xpath 1048576 " X: 1048576 |
| |
| Xcheck 1996459 |
| |
| " Leave F, G, and H for execution as scripts in the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 28: Executing :finally clauses after :finish {{{1 |
| " |
| " For a :finish command dynamically enclosed in a :try/:endtry region, |
| " :finally clauses are executed and the sourced file is finished. |
| " |
| " This test executes the bodies of the functions F, G, and H from the |
| " previous test as script files (:return replaced by :finish). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32 |
| let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024 |
| let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384 |
| |
| try |
| Xpath 131072 " X: 131072 |
| exec "source" scriptH |
| Xpath 262144 " X: 262144 |
| finally |
| Xpath 524288 " X: 524288 |
| endtry |
| Xpath 1048576 " X: 1048576 |
| |
| call delete(scriptF) |
| call delete(scriptG) |
| call delete(scriptH) |
| unlet scriptF scriptG scriptH |
| delfunction F |
| delfunction G |
| delfunction H |
| |
| Xcheck 1996459 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 29: Executing :finally clauses on errors {{{1 |
| " |
| " After an error in a command dynamically enclosed in a :try/:endtry |
| " region, :finally clauses are executed and the script processing is |
| " terminated. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| function! F() |
| while 1 |
| try |
| Xpath 1 " X: 1 |
| while 1 |
| try |
| Xpath 2 " X: 2 |
| asdf " error |
| Xpath 4 " X: 0 |
| finally |
| Xpath 8 " X: 8 |
| endtry | Xpath 16 " X: 0 |
| Xpath 32 " X: 0 |
| break |
| endwhile |
| Xpath 64 " X: 0 |
| finally |
| Xpath 128 " X: 128 |
| endtry | Xpath 256 " X: 0 |
| Xpath 512 " X: 0 |
| break |
| endwhile |
| Xpath 1024 " X: 0 |
| endfunction |
| |
| while 1 |
| try |
| Xpath 2048 " X: 2048 |
| while 1 |
| call F() |
| Xpath 4096 " X: 0 |
| break |
| endwhile | Xpath 8192 " X: 0 |
| Xpath 16384 " X: 0 |
| finally |
| Xpath 32768 " X: 32768 |
| endtry | Xpath 65536 " X: 0 |
| endwhile | Xpath 131072 " X: 0 |
| Xpath 262144 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function! G() abort |
| if 1 |
| try |
| Xpath 524288 " X: 524288 |
| asdf " error |
| Xpath 1048576 " X: 0 |
| finally |
| Xpath 2097152 " X: 2097152 |
| endtry | Xpath 4194304 " X: 0 |
| endif | Xpath 8388608 " X: 0 |
| Xpath 16777216 " X: 0 |
| endfunction |
| |
| if 1 |
| try |
| Xpath 33554432 " X: 33554432 |
| call G() |
| Xpath 67108864 " X: 0 |
| finally |
| Xpath 134217728 " X: 134217728 |
| endtry | Xpath 268435456 " X: 0 |
| endif | Xpath 536870912 " X: 0 |
| Xpath 1073741824 " X: 0 |
| endif |
| |
| Xcheck 170428555 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 30: Executing :finally clauses on interrupt {{{1 |
| " |
| " After an interrupt in a command dynamically enclosed in |
| " a :try/:endtry region, :finally clauses are executed and the |
| " script processing is terminated. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| XloopINIT 1 16 |
| |
| function! F() |
| try |
| Xloop 1 " X: 1 + 1*16 |
| "INTERRUPT |
| Xloop 2 " X: 0 |
| finally |
| Xloop 4 " X: 4 + 4*16 |
| endtry |
| Xloop 8 " X: 0 |
| endfunction |
| |
| try |
| Xpath 256 " X: 256 |
| try |
| Xpath 512 " X: 512 |
| "INTERRUPT |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| try |
| Xpath 4096 " X: 4096 |
| try |
| Xpath 8192 " X: 8192 |
| finally |
| Xpath 16384 " X: 16384 |
| try |
| Xpath 32768 " X: 32768 |
| "INTERRUPT |
| Xpath 65536 " X: 0 |
| endtry |
| Xpath 131072 " X: 0 |
| endtry |
| Xpath 262144 " X: 0 |
| endtry |
| Xpath 524288 " X: 0 |
| endtry |
| Xpath 1048576 " X: 0 |
| finally |
| Xpath 2097152 " X: 2097152 |
| try |
| Xpath 4194304 " X: 4194304 |
| call F() |
| Xpath 8388608 " X: 0 |
| finally |
| Xpath 16777216 " X: 16777216 |
| try |
| Xpath 33554432 " X: 33554432 |
| XloopNEXT |
| ExecAsScript F |
| Xpath 67108864 " X: 0 |
| finally |
| Xpath 134217728 " X: 134217728 |
| endtry |
| Xpath 268435456 " X: 0 |
| endtry |
| Xpath 536870912 " X: 0 |
| endtry |
| Xpath 1073741824 " X: 0 |
| endif |
| |
| Xcheck 190905173 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 31: Executing :finally clauses after :throw {{{1 |
| " |
| " After a :throw dynamically enclosed in a :try/:endtry region, |
| " :finally clauses are executed and the script processing is |
| " terminated. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| XloopINIT 1 16 |
| |
| function! F() |
| try |
| Xloop 1 " X: 1 + 1*16 |
| throw "exception" |
| Xloop 2 " X: 0 |
| finally |
| Xloop 4 " X: 4 + 4*16 |
| endtry |
| Xloop 8 " X: 0 |
| endfunction |
| |
| try |
| Xpath 256 " X: 256 |
| try |
| Xpath 512 " X: 512 |
| throw "exception" |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| try |
| Xpath 4096 " X: 4096 |
| try |
| Xpath 8192 " X: 8192 |
| finally |
| Xpath 16384 " X: 16384 |
| try |
| Xpath 32768 " X: 32768 |
| throw "exception" |
| Xpath 65536 " X: 0 |
| endtry |
| Xpath 131072 " X: 0 |
| endtry |
| Xpath 262144 " X: 0 |
| endtry |
| Xpath 524288 " X: 0 |
| endtry |
| Xpath 1048576 " X: 0 |
| finally |
| Xpath 2097152 " X: 2097152 |
| try |
| Xpath 4194304 " X: 4194304 |
| call F() |
| Xpath 8388608 " X: 0 |
| finally |
| Xpath 16777216 " X: 16777216 |
| try |
| Xpath 33554432 " X: 33554432 |
| XloopNEXT |
| ExecAsScript F |
| Xpath 67108864 " X: 0 |
| finally |
| Xpath 134217728 " X: 134217728 |
| endtry |
| Xpath 268435456 " X: 0 |
| endtry |
| Xpath 536870912 " X: 0 |
| endtry |
| Xpath 1073741824 " X: 0 |
| endif |
| |
| Xcheck 190905173 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 32: Remembering the :return value on :finally {{{1 |
| " |
| " If a :finally clause is executed due to a :return specifying |
| " a value, this is the value visible to the caller if not overwritten |
| " by a new :return in the :finally clause. A :return without a value |
| " in the :finally clause overwrites with value 0. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| try |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| return "ABCD" |
| Xpath 4 " X: 0 |
| finally |
| Xpath 8 " X: 8 |
| endtry |
| Xpath 16 " X: 0 |
| finally |
| Xpath 32 " X: 32 |
| endtry |
| Xpath 64 " X: 0 |
| endfunction |
| |
| function! G() |
| try |
| Xpath 128 " X: 128 |
| return 8 |
| Xpath 256 " X: 0 |
| finally |
| Xpath 512 " X: 512 |
| return 16 + strlen(F()) |
| Xpath 1024 " X: 0 |
| endtry |
| Xpath 2048 " X: 0 |
| endfunction |
| |
| function! H() |
| try |
| Xpath 4096 " X: 4096 |
| return 32 |
| Xpath 8192 " X: 0 |
| finally |
| Xpath 16384 " X: 16384 |
| return |
| Xpath 32768 " X: 0 |
| endtry |
| Xpath 65536 " X: 0 |
| endfunction |
| |
| function! I() |
| try |
| Xpath 131072 " X: 131072 |
| finally |
| Xpath 262144 " X: 262144 |
| return G() + H() + 64 |
| Xpath 524288 " X: 0 |
| endtry |
| Xpath 1048576 " X: 0 |
| endfunction |
| |
| let retcode = I() |
| Xpath 2097152 " X: 2097152 |
| |
| if retcode < 0 |
| Xpath 4194304 " X: 0 |
| endif |
| if retcode % 4 |
| Xpath 8388608 " X: 0 |
| endif |
| if (retcode/4) % 2 |
| Xpath 16777216 " X: 16777216 |
| endif |
| if (retcode/8) % 2 |
| Xpath 33554432 " X: 0 |
| endif |
| if (retcode/16) % 2 |
| Xpath 67108864 " X: 67108864 |
| endif |
| if (retcode/32) % 2 |
| Xpath 134217728 " X: 0 |
| endif |
| if (retcode/64) % 2 |
| Xpath 268435456 " X: 268435456 |
| endif |
| if retcode/128 |
| Xpath 536870912 " X: 0 |
| endif |
| |
| unlet retcode |
| delfunction F |
| delfunction G |
| delfunction H |
| delfunction I |
| |
| Xcheck 354833067 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 33: :return under :execute or user command and :finally {{{1 |
| " |
| " A :return command may be executed under an ":execute" or from |
| " a user command. Executing of :finally clauses and passing through |
| " the return code works also then. |
| "------------------------------------------------------------------------------- |
| XpathINIT |
| |
| command! -nargs=? RETURN |
| \ try | return <args> | finally | return <args> * 2 | endtry |
| |
| function! F() |
| try |
| RETURN 8 |
| Xpath 1 " X: 0 |
| finally |
| Xpath 2 " X: 2 |
| endtry |
| Xpath 4 " X: 0 |
| endfunction |
| |
| function! G() |
| try |
| RETURN 32 |
| Xpath 8 " X: 0 |
| finally |
| Xpath 16 " X: 16 |
| RETURN 128 |
| Xpath 32 " X: 0 |
| endtry |
| Xpath 64 " X: 0 |
| endfunction |
| |
| function! H() |
| try |
| execute "try | return 512 | finally | return 1024 | endtry" |
| Xpath 128 " X: 0 |
| finally |
| Xpath 256 " X: 256 |
| endtry |
| Xpath 512 " X: 0 |
| endfunction |
| |
| function! I() |
| try |
| execute "try | return 2048 | finally | return 4096 | endtry" |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| execute "try | return 8192 | finally | return 16384 | endtry" |
| Xpath 4096 " X: 0 |
| endtry |
| Xpath 8192 " X: 0 |
| endfunction |
| |
| function! J() |
| try |
| RETURN 32768 |
| Xpath 16384 " X: 0 |
| finally |
| Xpath 32768 " X: 32768 |
| return |
| Xpath 65536 " X: 0 |
| endtry |
| Xpath 131072 " X: 0 |
| endfunction |
| |
| function! K() |
| try |
| execute "try | return 131072 | finally | return 262144 | endtry" |
| Xpath 262144 " X: 0 |
| finally |
| Xpath 524288 " X: 524288 |
| execute "try | return 524288 | finally | return | endtry" |
| Xpath 1048576 " X: 0 |
| endtry |
| Xpath 2097152 " X: 0 |
| endfunction |
| |
| function! L() |
| try |
| return |
| Xpath 4194304 " X: 0 |
| finally |
| Xpath 8388608 " X: 8388608 |
| RETURN 1048576 |
| Xpath 16777216 " X: 0 |
| endtry |
| Xpath 33554432 " X: 0 |
| endfunction |
| |
| function! M() |
| try |
| return |
| Xpath 67108864 " X: 0 |
| finally |
| Xpath 134217728 " X: 134217728 |
| execute "try | return 4194304 | finally | return 8388608 | endtry" |
| Xpath 268435456 " X: 0 |
| endtry |
| Xpath 536870912 " X: 0 |
| endfunction |
| |
| function! N() |
| RETURN 16777216 |
| endfunction |
| |
| function! O() |
| execute "try | return 67108864 | finally | return 134217728 | endtry" |
| endfunction |
| |
| let sum = F() + G() + H() + I() + J() + K() + L() + M() |
| let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608 |
| let sum = sum + N() + O() |
| let expected = expected + 33554432 + 134217728 |
| |
| if sum == expected |
| Xout "sum = " . sum . " (ok)" |
| else |
| Xout "sum = " . sum . ", expected: " . expected |
| endif |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| if sum != expected |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| endif |
| |
| unlet sum expected |
| delfunction F |
| delfunction G |
| delfunction H |
| delfunction I |
| delfunction J |
| delfunction K |
| delfunction L |
| delfunction M |
| delfunction N |
| delfunction O |
| |
| Xcheck 1216907538 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 34: :finally reason discarded by :continue {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by a :continue in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 8 |
| |
| function! C(jump) |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" || a:jump == "finish" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| continue " discards jump that caused the :finally |
| Xloop 1 " X: 0 |
| endtry |
| Xloop 2 " X: 0 |
| elseif loop == 2 |
| Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) |
| endif |
| endwhile |
| endfunction |
| |
| call C("continue") |
| Xpath 2097152 " X: 2097152 |
| call C("break") |
| Xpath 4194304 " X: 4194304 |
| call C("return") |
| Xpath 8388608 " X: 8388608 |
| let g:jump = "finish" |
| ExecAsScript C |
| unlet g:jump |
| Xpath 16777216 " X: 16777216 |
| try |
| call C("error") |
| Xpath 33554432 " X: 33554432 |
| finally |
| Xpath 67108864 " X: 67108864 |
| try |
| call C("interrupt") |
| Xpath 134217728 " X: 134217728 |
| finally |
| Xpath 268435456 " X: 268435456 |
| call C("throw") |
| Xpath 536870912 " X: 536870912 |
| endtry |
| endtry |
| Xpath 1073741824 " X: 1073741824 |
| |
| delfunction C |
| |
| endif |
| |
| Xcheck 2146584868 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 35: :finally reason discarded by :break {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by a :break in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 8 |
| |
| function! B(jump) |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" || a:jump == "finish" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| break " discards jump that caused the :finally |
| Xloop 1 " X: 0 |
| endtry |
| elseif loop == 2 |
| Xloop 2 " X: 0 |
| endif |
| endwhile |
| Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) |
| endfunction |
| |
| call B("continue") |
| Xpath 2097152 " X: 2097152 |
| call B("break") |
| Xpath 4194304 " X: 4194304 |
| call B("return") |
| Xpath 8388608 " X: 8388608 |
| let g:jump = "finish" |
| ExecAsScript B |
| unlet g:jump |
| Xpath 16777216 " X: 16777216 |
| try |
| call B("error") |
| Xpath 33554432 " X: 33554432 |
| finally |
| Xpath 67108864 " X: 67108864 |
| try |
| call B("interrupt") |
| Xpath 134217728 " X: 134217728 |
| finally |
| Xpath 268435456 " X: 268435456 |
| call B("throw") |
| Xpath 536870912 " X: 536870912 |
| endtry |
| endtry |
| Xpath 1073741824 " X: 1073741824 |
| |
| delfunction B |
| |
| endif |
| |
| Xcheck 2146584868 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 36: :finally reason discarded by :return {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by a :return in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 8 |
| |
| function! R(jump, retval) abort |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| return a:retval " discards jump that caused the :finally |
| Xloop 1 " X: 0 |
| endtry |
| elseif loop == 2 |
| Xloop 2 " X: 0 |
| endif |
| endwhile |
| Xloop 4 " X: 0 |
| endfunction |
| |
| let sum = -R("continue", -8) |
| Xpath 2097152 " X: 2097152 |
| let sum = sum - R("break", -16) |
| Xpath 4194304 " X: 4194304 |
| let sum = sum - R("return", -32) |
| Xpath 8388608 " X: 8388608 |
| try |
| let sum = sum - R("error", -64) |
| Xpath 16777216 " X: 16777216 |
| finally |
| Xpath 33554432 " X: 33554432 |
| try |
| let sum = sum - R("interrupt", -128) |
| Xpath 67108864 " X: 67108864 |
| finally |
| Xpath 134217728 " X: 134217728 |
| let sum = sum - R("throw", -256) |
| Xpath 268435456 " X: 268435456 |
| endtry |
| endtry |
| Xpath 536870912 " X: 536870912 |
| |
| let expected = 8 + 16 + 32 + 64 + 128 + 256 |
| if sum != expected |
| Xpath 1073741824 " X: 0 |
| Xout "sum =" . sum . ", expected: " . expected |
| endif |
| |
| unlet sum expected |
| delfunction R |
| |
| endif |
| |
| Xcheck 1071644672 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 37: :finally reason discarded by :finish {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by a :finish in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 8 |
| |
| function! F(jump) " not executed as function, transformed to a script |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "finish" |
| finish |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| finish " discards jump that caused the :finally |
| Xloop 1 " X: 0 |
| endtry |
| elseif loop == 2 |
| Xloop 2 " X: 0 |
| endif |
| endwhile |
| Xloop 4 " X: 0 |
| endfunction |
| |
| let scriptF = MakeScript("F") |
| delfunction F |
| |
| let g:jump = "continue" |
| exec "source" scriptF |
| Xpath 2097152 " X: 2097152 |
| let g:jump = "break" |
| exec "source" scriptF |
| Xpath 4194304 " X: 4194304 |
| let g:jump = "finish" |
| exec "source" scriptF |
| Xpath 8388608 " X: 8388608 |
| try |
| let g:jump = "error" |
| exec "source" scriptF |
| Xpath 16777216 " X: 16777216 |
| finally |
| Xpath 33554432 " X: 33554432 |
| try |
| let g:jump = "interrupt" |
| exec "source" scriptF |
| Xpath 67108864 " X: 67108864 |
| finally |
| Xpath 134217728 " X: 134217728 |
| try |
| let g:jump = "throw" |
| exec "source" scriptF |
| Xpath 268435456 " X: 268435456 |
| finally |
| Xpath 536870912 " X: 536870912 |
| endtry |
| endtry |
| endtry |
| unlet g:jump |
| |
| call delete(scriptF) |
| unlet scriptF |
| |
| endif |
| |
| Xcheck 1071644672 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 38: :finally reason discarded by an error {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by an error in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 4 |
| |
| function! E(jump) |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" || a:jump == "finish" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| asdf " error; discards jump that caused the :finally |
| endtry |
| elseif loop == 2 |
| Xloop 1 " X: 0 |
| endif |
| endwhile |
| Xloop 2 " X: 0 |
| endfunction |
| |
| try |
| Xpath 16384 " X: 16384 |
| call E("continue") |
| Xpath 32768 " X: 0 |
| finally |
| try |
| Xpath 65536 " X: 65536 |
| call E("break") |
| Xpath 131072 " X: 0 |
| finally |
| try |
| Xpath 262144 " X: 262144 |
| call E("return") |
| Xpath 524288 " X: 0 |
| finally |
| try |
| Xpath 1048576 " X: 1048576 |
| let g:jump = "finish" |
| ExecAsScript E |
| Xpath 2097152 " X: 0 |
| finally |
| unlet g:jump |
| try |
| Xpath 4194304 " X: 4194304 |
| call E("error") |
| Xpath 8388608 " X: 0 |
| finally |
| try |
| Xpath 16777216 " X: 16777216 |
| call E("interrupt") |
| Xpath 33554432 " X: 0 |
| finally |
| try |
| Xpath 67108864 " X: 67108864 |
| call E("throw") |
| Xpath 134217728 " X: 0 |
| finally |
| Xpath 268435456 " X: 268435456 |
| delfunction E |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| Xpath 536870912 " X: 0 |
| |
| endif |
| |
| Xcheck 357908480 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 39: :finally reason discarded by an interrupt {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by an interrupt in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 4 |
| |
| function! I(jump) |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" || a:jump == "finish" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| "INTERRUPT - discards jump that caused the :finally |
| let dummy = 0 |
| endtry |
| elseif loop == 2 |
| Xloop 1 " X: 0 |
| endif |
| endwhile |
| Xloop 2 " X: 0 |
| endfunction |
| |
| try |
| Xpath 16384 " X: 16384 |
| call I("continue") |
| Xpath 32768 " X: 0 |
| finally |
| try |
| Xpath 65536 " X: 65536 |
| call I("break") |
| Xpath 131072 " X: 0 |
| finally |
| try |
| Xpath 262144 " X: 262144 |
| call I("return") |
| Xpath 524288 " X: 0 |
| finally |
| try |
| Xpath 1048576 " X: 1048576 |
| let g:jump = "finish" |
| ExecAsScript I |
| Xpath 2097152 " X: 0 |
| finally |
| unlet g:jump |
| try |
| Xpath 4194304 " X: 4194304 |
| call I("error") |
| Xpath 8388608 " X: 0 |
| finally |
| try |
| Xpath 16777216 " X: 16777216 |
| call I("interrupt") |
| Xpath 33554432 " X: 0 |
| finally |
| try |
| Xpath 67108864 " X: 67108864 |
| call I("throw") |
| Xpath 134217728 " X: 0 |
| finally |
| Xpath 268435456 " X: 268435456 |
| delfunction I |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| Xpath 536870912 " X: 0 |
| |
| endif |
| |
| Xcheck 357908480 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 40: :finally reason discarded by :throw {{{1 |
| " |
| " When a :finally clause is executed due to a :continue, :break, |
| " :return, :finish, error, interrupt or :throw, the jump reason is |
| " discarded by a :throw in the finally clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 4 |
| |
| function! T(jump) |
| XloopNEXT |
| let loop = 0 |
| while loop < 2 |
| let loop = loop + 1 |
| if loop == 1 |
| try |
| if a:jump == "continue" |
| continue |
| elseif a:jump == "break" |
| break |
| elseif a:jump == "return" || a:jump == "finish" |
| return |
| elseif a:jump == "error" |
| asdf |
| elseif a:jump == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:jump == "throw" |
| throw "abc" |
| endif |
| finally |
| throw "xyz" " discards jump that caused the :finally |
| endtry |
| elseif loop == 2 |
| Xloop 1 " X: 0 |
| endif |
| endwhile |
| Xloop 2 " X: 0 |
| endfunction |
| |
| try |
| Xpath 16384 " X: 16384 |
| call T("continue") |
| Xpath 32768 " X: 0 |
| finally |
| try |
| Xpath 65536 " X: 65536 |
| call T("break") |
| Xpath 131072 " X: 0 |
| finally |
| try |
| Xpath 262144 " X: 262144 |
| call T("return") |
| Xpath 524288 " X: 0 |
| finally |
| try |
| Xpath 1048576 " X: 1048576 |
| let g:jump = "finish" |
| ExecAsScript T |
| Xpath 2097152 " X: 0 |
| finally |
| unlet g:jump |
| try |
| Xpath 4194304 " X: 4194304 |
| call T("error") |
| Xpath 8388608 " X: 0 |
| finally |
| try |
| Xpath 16777216 " X: 16777216 |
| call T("interrupt") |
| Xpath 33554432 " X: 0 |
| finally |
| try |
| Xpath 67108864 " X: 67108864 |
| call T("throw") |
| Xpath 134217728 " X: 0 |
| finally |
| Xpath 268435456 " X: 268435456 |
| delfunction T |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| endtry |
| Xpath 536870912 " X: 0 |
| |
| endif |
| |
| Xcheck 357908480 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 41: Skipped :throw finding next command {{{1 |
| " |
| " A :throw in an inactive conditional must not hide a following |
| " command. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F() |
| Xpath 1 " X: 1 |
| if 0 | throw "never" | endif | Xpath 2 " X: 2 |
| Xpath 4 " X: 4 |
| endfunction |
| |
| function! G() |
| Xpath 8 " X: 8 |
| while 0 | throw "never" | endwhile | Xpath 16 " X: 16 |
| Xpath 32 " X: 32 |
| endfunction |
| |
| function H() |
| Xpath 64 " X: 64 |
| if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128 |
| Xpath 256 " X: 256 |
| endfunction |
| |
| Xpath 512 " X: 512 |
| |
| try |
| Xpath 1024 " X: 1024 |
| call F() |
| Xpath 2048 " X: 2048 |
| catch /.*/ |
| Xpath 4096 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 8192 " X: 8192 |
| |
| try |
| Xpath 16384 " X: 16384 |
| call G() |
| Xpath 32768 " X: 32768 |
| catch /.*/ |
| Xpath 65536 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 131072 " X: 131072 |
| |
| try |
| Xpath 262144 " X: 262144 |
| call H() |
| Xpath 524288 " X: 524288 |
| catch /.*/ |
| Xpath 1048576 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 2097152 " X: 2097152 |
| |
| delfunction F |
| delfunction G |
| delfunction H |
| |
| Xcheck 3076095 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 42: Catching number and string exceptions {{{1 |
| " |
| " When a number is thrown, it is converted to a string exception. |
| " Numbers and strings may be caught by specifying a regular exception |
| " as argument to the :catch command. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| try |
| |
| try |
| Xpath 1 " X: 1 |
| throw 4711 |
| Xpath 2 " X: 0 |
| catch /4711/ |
| Xpath 4 " X: 4 |
| endtry |
| |
| try |
| Xpath 8 " X: 8 |
| throw 4711 |
| Xpath 16 " X: 0 |
| catch /^4711$/ |
| Xpath 32 " X: 32 |
| endtry |
| |
| try |
| Xpath 64 " X: 64 |
| throw 4711 |
| Xpath 128 " X: 0 |
| catch /\d/ |
| Xpath 256 " X: 256 |
| endtry |
| |
| try |
| Xpath 512 " X: 512 |
| throw 4711 |
| Xpath 1024 " X: 0 |
| catch /^\d\+$/ |
| Xpath 2048 " X: 2048 |
| endtry |
| |
| try |
| Xpath 4096 " X: 4096 |
| throw "arrgh" |
| Xpath 8192 " X: 0 |
| catch /arrgh/ |
| Xpath 16384 " X: 16384 |
| endtry |
| |
| try |
| Xpath 32768 " X: 32768 |
| throw "arrgh" |
| Xpath 65536 " X: 0 |
| catch /^arrgh$/ |
| Xpath 131072 " X: 131072 |
| endtry |
| |
| try |
| Xpath 262144 " X: 262144 |
| throw "arrgh" |
| Xpath 524288 " X: 0 |
| catch /\l/ |
| Xpath 1048576 " X: 1048576 |
| endtry |
| |
| try |
| Xpath 2097152 " X: 2097152 |
| throw "arrgh" |
| Xpath 4194304 " X: 0 |
| catch /^\l\+$/ |
| Xpath 8388608 " X: 8388608 |
| endtry |
| |
| try |
| try |
| Xpath 16777216 " X: 16777216 |
| throw "ARRGH" |
| Xpath 33554432 " X: 0 |
| catch /^arrgh$/ |
| Xpath 67108864 " X: 0 |
| endtry |
| catch /^\carrgh$/ |
| Xpath 134217728 " X: 134217728 |
| endtry |
| |
| try |
| Xpath 268435456 " X: 268435456 |
| throw "" |
| Xpath 536870912 " X: 0 |
| catch /^$/ |
| Xpath 1073741824 " X: 1073741824 |
| endtry |
| |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xcheck 1505155949 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 43: Selecting the correct :catch clause {{{1 |
| " |
| " When an exception is thrown and there are multiple :catch clauses, |
| " the first matching one is taken. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT 1 1024 |
| let loops = 3 |
| while loops > 0 |
| try |
| if loops == 3 |
| Xloop 1 " X: 1 |
| throw "a" |
| Xloop 2 " X: 0 |
| elseif loops == 2 |
| Xloop 4 " X: 4*1024 |
| throw "ab" |
| Xloop 8 " X: 0 |
| elseif loops == 1 |
| Xloop 16 " X: 16*1024*1024 |
| throw "abc" |
| Xloop 32 " X: 0 |
| endif |
| catch /abc/ |
| Xloop 64 " X: 64*1024*1024 |
| catch /ab/ |
| Xloop 128 " X: 128*1024 |
| catch /.*/ |
| Xloop 256 " X: 256 |
| catch /a/ |
| Xloop 512 " X: 0 |
| endtry |
| |
| let loops = loops - 1 |
| XloopNEXT |
| endwhile |
| Xpath 1073741824 " X: 1073741824 |
| |
| unlet loops |
| |
| Xcheck 1157763329 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 44: Missing or empty :catch patterns {{{1 |
| " |
| " A missing or empty :catch pattern means the same as /.*/, that is, |
| " catches everything. To catch only empty exceptions, /^$/ must be |
| " used. A :catch with missing, empty, or /.*/ argument also works |
| " when followed by another command separated by a bar on the same |
| " line. :catch patterns cannot be specified between ||. But other |
| " pattern separators can be used instead of //. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| throw "" |
| catch /^$/ |
| Xpath 2 " X: 2 |
| endtry |
| |
| try |
| Xpath 4 " X: 4 |
| throw "" |
| catch /.*/ |
| Xpath 8 " X: 8 |
| endtry |
| |
| try |
| Xpath 16 " X: 16 |
| throw "" |
| catch // |
| Xpath 32 " X: 32 |
| endtry |
| |
| try |
| Xpath 64 " X: 64 |
| throw "" |
| catch |
| Xpath 128 " X: 128 |
| endtry |
| |
| try |
| Xpath 256 " X: 256 |
| throw "oops" |
| catch /^$/ |
| Xpath 512 " X: 0 |
| catch /.*/ |
| Xpath 1024 " X: 1024 |
| endtry |
| |
| try |
| Xpath 2048 " X: 2048 |
| throw "arrgh" |
| catch /^$/ |
| Xpath 4096 " X: 0 |
| catch // |
| Xpath 8192 " X: 8192 |
| endtry |
| |
| try |
| Xpath 16384 " X: 16384 |
| throw "brrr" |
| catch /^$/ |
| Xpath 32768 " X: 0 |
| catch |
| Xpath 65536 " X: 65536 |
| endtry |
| |
| try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry |
| " X: 131072 + 262144 |
| |
| try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry |
| " X: 524288 + 1048576 |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| " Extra try level: if ":catch" without arguments below raises |
| " a syntax error because it misinterprets the "Xpath" as a pattern, |
| " let it be caught by the ":catch /.*/" below. |
| try |
| try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | : |
| endtry " X: 2097152 + 4194304 |
| endtry |
| catch /.*/ |
| let caught = 1 |
| Xout v:exception "in" v:throwpoint |
| finally |
| if $VIMNOERRTHROW && v:errmsg != "" |
| Xout v:errmsg |
| endif |
| if caught || $VIMNOERRTHROW && v:errmsg != "" |
| Xpath 8388608 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| let cologne = 4711 |
| try |
| try |
| Xpath 16777216 " X: 16777216 |
| throw "throw cologne" |
| " Next lines catches all and throws 4711: |
| catch |throw cologne| |
| Xpath 33554432 " X: 0 |
| endtry |
| catch /4711/ |
| Xpath 67108864 " X: 67108864 |
| endtry |
| |
| try |
| Xpath 134217728 " X: 134217728 |
| throw "plus" |
| catch +plus+ |
| Xpath 268435456 " X: 268435456 |
| endtry |
| |
| Xpath 536870912 " X: 536870912 |
| catch /.*/ |
| Xpath 1073741824 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| unlet! caught cologne |
| |
| Xcheck 1031761407 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 45: Catching exceptions from nested :try blocks {{{1 |
| " |
| " When :try blocks are nested, an exception is caught by the innermost |
| " try conditional that has a matching :catch clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT 1 1024 |
| let loops = 3 |
| while loops > 0 |
| try |
| try |
| try |
| try |
| if loops == 3 |
| Xloop 1 " X: 1 |
| throw "a" |
| Xloop 2 " X: 0 |
| elseif loops == 2 |
| Xloop 4 " X: 4*1024 |
| throw "ab" |
| Xloop 8 " X: 0 |
| elseif loops == 1 |
| Xloop 16 " X: 16*1024*1024 |
| throw "abc" |
| Xloop 32 " X: 0 |
| endif |
| catch /abc/ |
| Xloop 64 " X: 64*1024*1024 |
| endtry |
| catch /ab/ |
| Xloop 128 " X: 128*1024 |
| endtry |
| catch /.*/ |
| Xloop 256 " X: 256 |
| endtry |
| catch /a/ |
| Xloop 512 " X: 0 |
| endtry |
| |
| let loops = loops - 1 |
| XloopNEXT |
| endwhile |
| Xpath 1073741824 " X: 1073741824 |
| |
| unlet loops |
| |
| Xcheck 1157763329 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 46: Executing :finally after a :throw in nested :try {{{1 |
| " |
| " When an exception is thrown from within nested :try blocks, the |
| " :finally clauses of the non-catching try conditionals should be |
| " executed before the matching :catch of the next surrounding :try |
| " gets the control. If this also has a :finally clause, it is |
| " executed afterwards. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let sum = 0 |
| |
| try |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| try |
| Xpath 4 " X: 4 |
| try |
| Xpath 8 " X: 8 |
| throw "ABC" |
| Xpath 16 " X: 0 |
| catch /xyz/ |
| Xpath 32 " X: 0 |
| finally |
| Xpath 64 " X: 64 |
| if sum != 0 |
| Xpath 128 " X: 0 |
| endif |
| let sum = sum + 1 |
| endtry |
| Xpath 256 " X: 0 |
| catch /123/ |
| Xpath 512 " X: 0 |
| catch /321/ |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| if sum != 1 |
| Xpath 4096 " X: 0 |
| endif |
| let sum = sum + 2 |
| endtry |
| Xpath 8192 " X: 0 |
| finally |
| Xpath 16384 " X: 16384 |
| if sum != 3 |
| Xpath 32768 " X: 0 |
| endif |
| let sum = sum + 4 |
| endtry |
| Xpath 65536 " X: 0 |
| catch /ABC/ |
| Xpath 131072 " X: 131072 |
| if sum != 7 |
| Xpath 262144 " X: 0 |
| endif |
| let sum = sum + 8 |
| finally |
| Xpath 524288 " X: 524288 |
| if sum != 15 |
| Xpath 1048576 " X: 0 |
| endif |
| let sum = sum + 16 |
| endtry |
| Xpath 65536 " X: 65536 |
| if sum != 31 |
| Xpath 131072 " X: 0 |
| endif |
| |
| unlet sum |
| |
| Xcheck 739407 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 47: Throwing exceptions from a :catch clause {{{1 |
| " |
| " When an exception is thrown from a :catch clause, it should not be |
| " caught by a :catch of the same :try conditional. After executing |
| " the :finally clause (if present), surrounding try conditionals |
| " should be checked for a matching :catch. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| try |
| Xpath 4 " X: 4 |
| try |
| Xpath 8 " X: 8 |
| throw "x1" |
| Xpath 16 " X: 0 |
| catch /x1/ |
| Xpath 32 " X: 32 |
| try |
| Xpath 64 " X: 64 |
| throw "x2" |
| Xpath 128 " X: 0 |
| catch /x1/ |
| Xpath 256 " X: 0 |
| catch /x2/ |
| Xpath 512 " X: 512 |
| try |
| Xpath 1024 " X: 1024 |
| throw "x3" |
| Xpath 2048 " X: 0 |
| catch /x1/ |
| Xpath 4096 " X: 0 |
| catch /x2/ |
| Xpath 8192 " X: 0 |
| finally |
| Xpath 16384 " X: 16384 |
| endtry |
| Xpath 32768 " X: 0 |
| catch /x3/ |
| Xpath 65536 " X: 0 |
| endtry |
| Xpath 131072 " X: 0 |
| catch /x1/ |
| Xpath 262144 " X: 0 |
| catch /x2/ |
| Xpath 524288 " X: 0 |
| catch /x3/ |
| Xpath 1048576 " X: 0 |
| finally |
| Xpath 2097152 " X: 2097152 |
| endtry |
| Xpath 4194304 " X: 0 |
| catch /x1/ |
| Xpath 8388608 " X: 0 |
| catch /x2/ |
| Xpath 16777216 " X: 0 |
| catch /x3/ |
| Xpath 33554432 " X: 33554432 |
| endtry |
| Xpath 67108864 " X: 67108864 |
| catch /.*/ |
| Xpath 134217728 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| Xpath 268435456 " X: 268435456 |
| |
| Xcheck 371213935 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 48: Throwing exceptions from a :finally clause {{{1 |
| " |
| " When an exception is thrown from a :finally clause, it should not be |
| " caught by a :catch of the same :try conditional. Surrounding try |
| " conditionals should be checked for a matching :catch. A previously |
| " thrown exception is discarded. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| try |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| catch /x1/ |
| Xpath 2 " X: 0 |
| finally |
| Xpath 4 " X: 4 |
| throw "x1" |
| Xpath 8 " X: 0 |
| endtry |
| Xpath 16 " X: 0 |
| catch /x1/ |
| Xpath 32 " X: 32 |
| endtry |
| Xpath 64 " X: 64 |
| |
| try |
| try |
| Xpath 128 " X: 128 |
| throw "x2" |
| Xpath 256 " X: 0 |
| catch /x2/ |
| Xpath 512 " X: 512 |
| catch /x3/ |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| throw "x3" |
| Xpath 4096 " X: 0 |
| endtry |
| Xpath 8192 " X: 0 |
| catch /x2/ |
| Xpath 16384 " X: 0 |
| catch /x3/ |
| Xpath 32768 " X: 32768 |
| endtry |
| Xpath 65536 " X: 65536 |
| |
| try |
| try |
| try |
| Xpath 131072 " X: 131072 |
| throw "x4" |
| Xpath 262144 " X: 0 |
| catch /x5/ |
| Xpath 524288 " X: 0 |
| finally |
| Xpath 1048576 " X: 1048576 |
| throw "x5" " discards "x4" |
| Xpath 2097152 " X: 0 |
| endtry |
| Xpath 4194304 " X: 0 |
| catch /x4/ |
| Xpath 8388608 " X: 0 |
| finally |
| Xpath 16777216 " X: 16777216 |
| endtry |
| Xpath 33554432 " X: 0 |
| catch /x5/ |
| Xpath 67108864 " X: 67108864 |
| endtry |
| Xpath 134217728 " X: 134217728 |
| |
| catch /.*/ |
| Xpath 268435456 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| Xpath 536870912 " X: 536870912 |
| |
| Xcheck 756255461 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 49: Throwing exceptions across functions {{{1 |
| " |
| " When an exception is thrown but not caught inside a function, the |
| " caller is checked for a matching :catch clause. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! C() |
| try |
| Xpath 1 " X: 1 |
| throw "arrgh" |
| Xpath 2 " X: 0 |
| catch /arrgh/ |
| Xpath 4 " X: 4 |
| endtry |
| Xpath 8 " X: 8 |
| endfunction |
| |
| XloopINIT! 16 16 |
| |
| function! T1() |
| XloopNEXT |
| try |
| Xloop 1 " X: 16 + 16*16 |
| throw "arrgh" |
| Xloop 2 " X: 0 |
| finally |
| Xloop 4 " X: 64 + 64*16 |
| endtry |
| Xloop 8 " X: 0 |
| endfunction |
| |
| function! T2() |
| try |
| Xpath 4096 " X: 4096 |
| call T1() |
| Xpath 8192 " X: 0 |
| finally |
| Xpath 16384 " X: 16384 |
| endtry |
| Xpath 32768 " X: 0 |
| endfunction |
| |
| try |
| Xpath 65536 " X: 65536 |
| call C() " throw and catch |
| Xpath 131072 " X: 131072 |
| catch /.*/ |
| Xpath 262144 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 524288 " X: 524288 |
| call T1() " throw, one level |
| Xpath 1048576 " X: 0 |
| catch /arrgh/ |
| Xpath 2097152 " X: 2097152 |
| catch /.*/ |
| Xpath 4194304 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 8388608 " X: 8388608 |
| call T2() " throw, two levels |
| Xpath 16777216 " X: 0 |
| catch /arrgh/ |
| Xpath 33554432 " X: 33554432 |
| catch /.*/ |
| Xpath 67108864 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| Xpath 134217728 " X: 134217728 |
| |
| Xcheck 179000669 |
| |
| " Leave C, T1, and T2 for execution as scripts in the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 50: Throwing exceptions across script files {{{1 |
| " |
| " When an exception is thrown but not caught inside a script file, |
| " the sourcing script or function is checked for a matching :catch |
| " clause. |
| " |
| " This test executes the bodies of the functions C, T1, and T2 from |
| " the previous test as script files (:return replaced by :finish). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let scriptC = MakeScript("C") " X: 1 + 4 + 8 |
| delfunction C |
| |
| XloopINIT! 16 16 |
| |
| let scriptT1 = MakeScript("T1") " X: 16 + 64 + 16*16 + 64*16 |
| delfunction T1 |
| |
| let scriptT2 = MakeScript("T2", scriptT1) " X: 4096 + 16384 |
| delfunction T2 |
| |
| function! F() |
| try |
| Xpath 65536 " X: 65536 |
| exec "source" g:scriptC |
| Xpath 131072 " X: 131072 |
| catch /.*/ |
| Xpath 262144 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 524288 " X: 524288 |
| exec "source" g:scriptT1 |
| Xpath 1048576 " X: 0 |
| catch /arrgh/ |
| Xpath 2097152 " X: 2097152 |
| catch /.*/ |
| Xpath 4194304 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| endfunction |
| |
| try |
| Xpath 8388608 " X: 8388608 |
| call F() |
| Xpath 16777216 " X: 16777216 |
| exec "source" scriptT2 |
| Xpath 33554432 " X: 0 |
| catch /arrgh/ |
| Xpath 67108864 " X: 67108864 |
| catch /.*/ |
| Xpath 134217728 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| Xpath 268435456 " X: 268435456 |
| |
| call delete(scriptC) |
| call delete(scriptT1) |
| call delete(scriptT2) |
| unlet scriptC scriptT1 scriptT2 |
| delfunction F |
| |
| Xcheck 363550045 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 51: Throwing exceptions across :execute and user commands {{{1 |
| " |
| " A :throw command may be executed under an ":execute" or from |
| " a user command. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| command! -nargs=? THROW1 throw <args> | throw 1 |
| command! -nargs=? THROW2 try | throw <args> | endtry | throw 2 |
| command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry |
| command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry |
| |
| try |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| THROW1 "A" |
| catch /A/ |
| Xpath 2 " X: 2 |
| endtry |
| catch /1/ |
| Xpath 4 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 8 " X: 8 |
| THROW2 "B" |
| catch /B/ |
| Xpath 16 " X: 16 |
| endtry |
| catch /2/ |
| Xpath 32 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 64 " X: 64 |
| THROW3 "C" |
| catch /C/ |
| Xpath 128 " X: 128 |
| endtry |
| catch /3/ |
| Xpath 256 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 512 " X: 512 |
| THROW4 "D" |
| catch /D/ |
| Xpath 1024 " X: 1024 |
| endtry |
| catch /4/ |
| Xpath 2048 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 4096 " X: 4096 |
| execute 'throw "E" | throw 5' |
| catch /E/ |
| Xpath 8192 " X: 8192 |
| endtry |
| catch /5/ |
| Xpath 16384 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 32768 " X: 32768 |
| execute 'try | throw "F" | endtry | throw 6' |
| catch /F/ |
| Xpath 65536 " X: 65536 |
| endtry |
| catch /6/ |
| Xpath 131072 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 262144 " X: 262144 |
| execute'try | throw 7 | catch /7/ | throw "G" | endtry' |
| catch /G/ |
| Xpath 524288 " X: 524288 |
| endtry |
| catch /7/ |
| Xpath 1048576 " X: 0 |
| endtry |
| |
| try |
| try |
| Xpath 2097152 " X: 2097152 |
| execute 'try | throw 8 | finally | throw "H" | endtry' |
| catch /H/ |
| Xpath 4194304 " X: 4194304 |
| endtry |
| catch /8/ |
| Xpath 8388608 " X: 0 |
| endtry |
| |
| catch /.*/ |
| Xpath 16777216 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 33554432 " X: 33554432 |
| |
| delcommand THROW1 |
| delcommand THROW2 |
| delcommand THROW3 |
| delcommand THROW4 |
| |
| Xcheck 40744667 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 52: Uncaught exceptions {{{1 |
| " |
| " When an exception is thrown but not caught, an error message is |
| " displayed when the script is terminated. In case of an interrupt |
| " or error exception, the normal interrupt or error message(s) are |
| " displayed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let msgfile = tempname() |
| |
| function! MESSAGES(...) |
| try |
| exec "edit" g:msgfile |
| catch /^Vim(edit):/ |
| return 0 |
| endtry |
| |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| let match = 1 |
| norm gg |
| |
| let num = a:0 / 2 |
| let cnt = 1 |
| while cnt <= num |
| let enr = a:{2*cnt - 1} |
| let emsg= a:{2*cnt} |
| let cnt = cnt + 1 |
| |
| if enr == "" |
| Xout "TODO: Add message number for:" emsg |
| elseif enr == "INT" |
| let enr = "" |
| endif |
| if enr == "" && !english |
| continue |
| endif |
| let pattern = (enr != "") ? enr . ':.*' : '' |
| if english |
| let pattern = pattern . emsg |
| endif |
| if !search(pattern, "W") |
| let match = 0 |
| Xout "No match for:" pattern |
| endif |
| norm $ |
| endwhile |
| |
| bwipeout! |
| return match |
| endfunction |
| |
| if ExtraVim(msgfile) |
| Xpath 1 " X: 1 |
| throw "arrgh" |
| endif |
| |
| Xpath 2 " X: 2 |
| if !MESSAGES('E605', "Exception not caught") |
| Xpath 4 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| try |
| Xpath 8 " X: 8 |
| throw "oops" |
| catch /arrgh/ |
| Xpath 16 " X: 0 |
| endtry |
| Xpath 32 " X: 0 |
| endif |
| |
| Xpath 64 " X: 64 |
| if !MESSAGES('E605', "Exception not caught") |
| Xpath 128 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| function! T() |
| throw "brrr" |
| endfunction |
| |
| try |
| Xpath 256 " X: 256 |
| throw "arrgh" |
| catch /.*/ |
| Xpath 512 " X: 512 |
| call T() |
| endtry |
| Xpath 1024 " X: 0 |
| endif |
| |
| Xpath 2048 " X: 2048 |
| if !MESSAGES('E605', "Exception not caught") |
| Xpath 4096 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| try |
| Xpath 8192 " X: 8192 |
| throw "arrgh" |
| finally |
| Xpath 16384 " X: 16384 |
| throw "brrr" |
| endtry |
| Xpath 32768 " X: 0 |
| endif |
| |
| Xpath 65536 " X: 65536 |
| if !MESSAGES('E605', "Exception not caught") |
| Xpath 131072 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| try |
| Xpath 262144 " X: 262144 |
| "INTERRUPT |
| endtry |
| Xpath 524288 " X: 0 |
| endif |
| |
| Xpath 1048576 " X: 1048576 |
| if !MESSAGES('INT', "Interrupted") |
| Xpath 2097152 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| try |
| Xpath 4194304 " X: 4194304 |
| let x = novar " error E121/E15; exception: E121 |
| catch /E15:/ " should not catch |
| Xpath 8388608 " X: 0 |
| endtry |
| Xpath 16777216 " X: 0 |
| endif |
| |
| Xpath 33554432 " X: 33554432 |
| if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression") |
| Xpath 67108864 " X: 0 |
| endif |
| |
| if ExtraVim(msgfile) |
| try |
| Xpath 134217728 " X: 134217728 |
| " unlet novar # " error E108/E488; exception: E488 |
| catch /E108:/ " should not catch |
| Xpath 268435456 " X: 0 |
| endtry |
| Xpath 536870912 " X: 0 |
| endif |
| |
| Xpath 1073741824 " X: 1073741824 |
| if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters") |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| endif |
| |
| call delete(msgfile) |
| unlet msgfile |
| |
| Xcheck 1247112011 |
| |
| " Leave MESSAGES() for the next tests. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 53: Nesting errors: :endif/:else/:elseif {{{1 |
| " |
| " For nesting errors of :if conditionals the correct error messages |
| " should be given. |
| " |
| " This test reuses the function MESSAGES() from the previous test. |
| " This functions checks the messages in g:msgfile. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let msgfile = tempname() |
| |
| if ExtraVim(msgfile) |
| " endif |
| endif |
| if MESSAGES('E580', ":endif without :if") |
| Xpath 1 " X: 1 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " endif |
| " endwhile |
| endif |
| if MESSAGES('E580', ":endif without :if") |
| Xpath 2 " X: 2 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " endif |
| " endtry |
| endif |
| if MESSAGES('E580', ":endif without :if") |
| Xpath 4 " X: 4 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " endif |
| " endtry |
| endif |
| if MESSAGES('E580', ":endif without :if") |
| Xpath 8 " X: 8 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " endif |
| " endtry |
| endif |
| if MESSAGES('E580', ":endif without :if") |
| Xpath 16 " X: 16 |
| endif |
| |
| if ExtraVim(msgfile) |
| " else |
| endif |
| if MESSAGES('E581', ":else without :if") |
| Xpath 32 " X: 32 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " else |
| " endwhile |
| endif |
| if MESSAGES('E581', ":else without :if") |
| Xpath 64 " X: 64 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " else |
| " endtry |
| endif |
| if MESSAGES('E581', ":else without :if") |
| Xpath 128 " X: 128 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " else |
| " endtry |
| endif |
| if MESSAGES('E581', ":else without :if") |
| Xpath 256 " X: 256 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " else |
| " endtry |
| endif |
| if MESSAGES('E581', ":else without :if") |
| Xpath 512 " X: 512 |
| endif |
| |
| if ExtraVim(msgfile) |
| " elseif |
| endif |
| if MESSAGES('E582', ":elseif without :if") |
| Xpath 1024 " X: 1024 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " elseif |
| " endwhile |
| endif |
| if MESSAGES('E582', ":elseif without :if") |
| Xpath 2048 " X: 2048 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " elseif |
| " endtry |
| endif |
| if MESSAGES('E582', ":elseif without :if") |
| Xpath 4096 " X: 4096 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " elseif |
| " endtry |
| endif |
| if MESSAGES('E582', ":elseif without :if") |
| Xpath 8192 " X: 8192 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " elseif |
| " endtry |
| endif |
| if MESSAGES('E582', ":elseif without :if") |
| Xpath 16384 " X: 16384 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " else |
| " else |
| " endif |
| endif |
| if MESSAGES('E583', "multiple :else") |
| Xpath 32768 " X: 32768 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " else |
| " elseif 1 |
| " endif |
| endif |
| if MESSAGES('E584', ":elseif after :else") |
| Xpath 65536 " X: 65536 |
| endif |
| |
| call delete(msgfile) |
| unlet msgfile |
| |
| Xcheck 131071 |
| |
| " Leave MESSAGES() for the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 54: Nesting errors: :while/:endwhile {{{1 |
| " |
| " For nesting errors of :while conditionals the correct error messages |
| " should be given. |
| " |
| " This test reuses the function MESSAGES() from the previous test. |
| " This functions checks the messages in g:msgfile. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let msgfile = tempname() |
| |
| if ExtraVim(msgfile) |
| " endwhile |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 1 " X: 1 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " endwhile |
| " endif |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 2 " X: 2 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " if 1 |
| " endwhile |
| endif |
| if MESSAGES('E171', "Missing :endif") |
| Xpath 4 " X: 4 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " endwhile |
| " endtry |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 8 " X: 8 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " try |
| " finally |
| " endwhile |
| endif |
| if MESSAGES('E600', "Missing :endtry") |
| Xpath 16 " X: 16 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " if 1 |
| " try |
| " finally |
| " endwhile |
| endif |
| if MESSAGES('E600', "Missing :endtry") |
| Xpath 32 " X: 32 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " try |
| " finally |
| " if 1 |
| " endwhile |
| endif |
| if MESSAGES('E171', "Missing :endif") |
| Xpath 64 " X: 64 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " endwhile |
| " endtry |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 128 " X: 128 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " try |
| " endwhile |
| " endtry |
| " endwhile |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 256 " X: 256 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " endwhile |
| " endtry |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 512 " X: 512 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " try |
| " throw "a" |
| " catch /a/ |
| " endwhile |
| " endtry |
| " endwhile |
| endif |
| if MESSAGES('E588', ":endwhile without :while") |
| Xpath 1024 " X: 1024 |
| endif |
| |
| |
| call delete(msgfile) |
| unlet msgfile |
| |
| Xcheck 2047 |
| |
| " Leave MESSAGES() for the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 55: Nesting errors: :continue/:break {{{1 |
| " |
| " For nesting errors of :continue and :break commands the correct |
| " error messages should be given. |
| " |
| " This test reuses the function MESSAGES() from the previous test. |
| " This functions checks the messages in g:msgfile. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let msgfile = tempname() |
| |
| if ExtraVim(msgfile) |
| " continue |
| endif |
| if MESSAGES('E586', ":continue without :while") |
| Xpath 1 " X: 1 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " continue |
| " endif |
| endif |
| if MESSAGES('E586', ":continue without :while") |
| Xpath 2 " X: 2 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " continue |
| " endtry |
| endif |
| if MESSAGES('E586', ":continue without :while") |
| Xpath 4 " X: 4 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " continue |
| " endtry |
| endif |
| if MESSAGES('E586', ":continue without :while") |
| Xpath 8 " X: 8 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " continue |
| " endtry |
| endif |
| if MESSAGES('E586', ":continue without :while") |
| Xpath 16 " X: 16 |
| endif |
| |
| if ExtraVim(msgfile) |
| " break |
| endif |
| if MESSAGES('E587', ":break without :while") |
| Xpath 32 " X: 32 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " break |
| " endif |
| endif |
| if MESSAGES('E587', ":break without :while") |
| Xpath 64 " X: 64 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " break |
| " endtry |
| endif |
| if MESSAGES('E587', ":break without :while") |
| Xpath 128 " X: 128 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " break |
| " endtry |
| endif |
| if MESSAGES('E587', ":break without :while") |
| Xpath 256 " X: 256 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " break |
| " endtry |
| endif |
| if MESSAGES('E587', ":break without :while") |
| Xpath 512 " X: 512 |
| endif |
| |
| call delete(msgfile) |
| unlet msgfile |
| |
| Xcheck 1023 |
| |
| " Leave MESSAGES() for the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 56: Nesting errors: :endtry {{{1 |
| " |
| " For nesting errors of :try conditionals the correct error messages |
| " should be given. |
| " |
| " This test reuses the function MESSAGES() from the previous test. |
| " This functions checks the messages in g:msgfile. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let msgfile = tempname() |
| |
| if ExtraVim(msgfile) |
| " endtry |
| endif |
| if MESSAGES('E602', ":endtry without :try") |
| Xpath 1 " X: 1 |
| endif |
| |
| if ExtraVim(msgfile) |
| " if 1 |
| " endtry |
| " endif |
| endif |
| if MESSAGES('E602', ":endtry without :try") |
| Xpath 2 " X: 2 |
| endif |
| |
| if ExtraVim(msgfile) |
| " while 1 |
| " endtry |
| " endwhile |
| endif |
| if MESSAGES('E602', ":endtry without :try") |
| Xpath 4 " X: 4 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " if 1 |
| " endtry |
| endif |
| if MESSAGES('E171', "Missing :endif") |
| Xpath 8 " X: 8 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " while 1 |
| " endtry |
| endif |
| if MESSAGES('E170', "Missing :endwhile") |
| Xpath 16 " X: 16 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " if 1 |
| " endtry |
| endif |
| if MESSAGES('E171', "Missing :endif") |
| Xpath 32 " X: 32 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " finally |
| " while 1 |
| " endtry |
| endif |
| if MESSAGES('E170', "Missing :endwhile") |
| Xpath 64 " X: 64 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " if 1 |
| " endtry |
| endif |
| if MESSAGES('E171', "Missing :endif") |
| Xpath 128 " X: 128 |
| endif |
| |
| if ExtraVim(msgfile) |
| " try |
| " throw "a" |
| " catch /a/ |
| " while 1 |
| " endtry |
| endif |
| if MESSAGES('E170', "Missing :endwhile") |
| Xpath 256 " X: 256 |
| endif |
| |
| call delete(msgfile) |
| unlet msgfile |
| |
| delfunction MESSAGES |
| |
| Xcheck 511 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 57: v:exception and v:throwpoint for user exceptions {{{1 |
| " |
| " v:exception evaluates to the value of the exception that was caught |
| " most recently and is not finished. (A caught exception is finished |
| " when the next ":catch", ":finally", or ":endtry" is reached.) |
| " v:throwpoint evaluates to the script/function name and line number |
| " where that exception has been thrown. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! FuncException() |
| let g:exception = v:exception |
| endfunction |
| |
| function! FuncThrowpoint() |
| let g:throwpoint = v:throwpoint |
| endfunction |
| |
| let scriptException = MakeScript("FuncException") |
| let scriptThrowPoint = MakeScript("FuncThrowpoint") |
| |
| command! CmdException let g:exception = v:exception |
| command! CmdThrowpoint let g:throwpoint = v:throwpoint |
| |
| XloopINIT! 1 2 |
| |
| function! CHECK(n, exception, throwname, throwline) |
| XloopNEXT |
| let error = 0 |
| if v:exception != a:exception |
| Xout a:n.": v:exception is" v:exception "instead of" a:exception |
| let error = 1 |
| endif |
| if v:throwpoint !~ a:throwname |
| let name = escape(a:throwname, '\') |
| Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name |
| let error = 1 |
| endif |
| if v:throwpoint !~ a:throwline |
| let line = escape(a:throwline, '\') |
| Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line |
| let error = 1 |
| endif |
| if error |
| Xloop 1 " X: 0 |
| endif |
| endfunction |
| |
| function! T(arg, line) |
| if a:line == 2 |
| throw a:arg " in line 2 |
| elseif a:line == 4 |
| throw a:arg " in line 4 |
| elseif a:line == 6 |
| throw a:arg " in line 6 |
| elseif a:line == 8 |
| throw a:arg " in line 8 |
| endif |
| endfunction |
| |
| function! G(arg, line) |
| call T(a:arg, a:line) |
| endfunction |
| |
| function! F(arg, line) |
| call G(a:arg, a:line) |
| endfunction |
| |
| let scriptT = MakeScript("T") |
| let scriptG = MakeScript("G", scriptT) |
| let scriptF = MakeScript("F", scriptG) |
| |
| try |
| Xpath 32768 " X: 32768 |
| call F("oops", 2) |
| catch /.*/ |
| Xpath 65536 " X: 65536 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| exec "let exception = v:exception" |
| exec "let throwpoint = v:throwpoint" |
| call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| CmdException |
| CmdThrowpoint |
| call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| call FuncException() |
| call FuncThrowpoint() |
| call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| exec "source" scriptException |
| exec "source" scriptThrowPoint |
| call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| try |
| Xpath 131072 " X: 131072 |
| call G("arrgh", 4) |
| catch /.*/ |
| Xpath 262144 " X: 262144 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>') |
| try |
| Xpath 524288 " X: 524288 |
| let g:arg = "autsch" |
| let g:line = 6 |
| exec "source" scriptF |
| catch /.*/ |
| Xpath 1048576 " X: 1048576 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| " Symbolic links in tempname()s are not resolved, whereas resolving |
| " is done for v:throwpoint. Resolve the temporary file name for |
| " scriptT, so that it can be matched against v:throwpoint. |
| call CHECK(7, "autsch", resolve(scriptT), '\<6\>') |
| finally |
| Xpath 2097152 " X: 2097152 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>') |
| try |
| Xpath 4194304 " X: 4194304 |
| let g:arg = "brrrr" |
| let g:line = 8 |
| exec "source" scriptG |
| catch /.*/ |
| Xpath 8388608 " X: 8388608 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| " Resolve scriptT for matching it against v:throwpoint. |
| call CHECK(9, "brrrr", resolve(scriptT), '\<8\>') |
| finally |
| Xpath 16777216 " X: 16777216 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>') |
| endtry |
| Xpath 33554432 " X: 33554432 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>') |
| endtry |
| Xpath 67108864 " X: 67108864 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>') |
| finally |
| Xpath 134217728 " X: 134217728 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| endtry |
| Xpath 268435456 " X: 268435456 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>') |
| finally |
| Xpath 536870912 " X: 536870912 |
| let exception = v:exception |
| let throwpoint = v:throwpoint |
| call CHECK(15, "", '^$', '^$') |
| endtry |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| unlet exception throwpoint |
| delfunction FuncException |
| delfunction FuncThrowpoint |
| call delete(scriptException) |
| call delete(scriptThrowPoint) |
| unlet scriptException scriptThrowPoint |
| delcommand CmdException |
| delcommand CmdThrowpoint |
| delfunction T |
| delfunction G |
| delfunction F |
| call delete(scriptT) |
| call delete(scriptG) |
| call delete(scriptF) |
| unlet scriptT scriptG scriptF |
| |
| Xcheck 2147450880 |
| |
| |
| "------------------------------------------------------------------------------- |
| " |
| " Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1 |
| " |
| " v:exception and v:throwpoint work also for error and interrupt |
| " exceptions. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| function! T(line) |
| if a:line == 2 |
| delfunction T " error (function in use) in line 2 |
| elseif a:line == 4 |
| let dummy = 0 " INTERRUPT1 - interrupt in line 4 |
| endif |
| endfunction |
| |
| while 1 |
| try |
| Xpath 1 " X: 1 |
| let caught = 0 |
| call T(2) |
| catch /.*/ |
| let caught = 1 |
| if v:exception !~ 'Vim(delfunction):' |
| Xpath 2 " X: 0 |
| endif |
| if v:throwpoint !~ '\<T\>' |
| Xpath 4 " X: 0 |
| endif |
| if v:throwpoint !~ '\<2\>' |
| Xpath 8 " X: 0 |
| endif |
| finally |
| Xpath 16 " X: 16 |
| if caught || $VIMNOERRTHROW |
| Xpath 32 " X: 32 |
| endif |
| if v:exception != "" |
| Xpath 64 " X: 0 |
| endif |
| if v:throwpoint != "" |
| Xpath 128 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| Xpath 256 " X: 256 |
| if v:exception != "" |
| Xpath 512 " X: 0 |
| endif |
| if v:throwpoint != "" |
| Xpath 1024 " X: 0 |
| endif |
| |
| while 1 |
| try |
| Xpath 2048 " X: 2048 |
| let caught = 0 |
| call T(4) |
| catch /.*/ |
| let caught = 1 |
| if v:exception != 'Vim:Interrupt' |
| Xpath 4096 " X: 0 |
| endif |
| if v:throwpoint !~ '\<T\>' |
| Xpath 8192 " X: 0 |
| endif |
| if v:throwpoint !~ '\<4\>' |
| Xpath 16384 " X: 0 |
| endif |
| finally |
| Xpath 32768 " X: 32768 |
| if caught || $VIMNOINTTHROW |
| Xpath 65536 " X: 65536 |
| endif |
| if v:exception != "" |
| Xpath 131072 " X: 0 |
| endif |
| if v:throwpoint != "" |
| Xpath 262144 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| Xpath 524288 " X: 524288 |
| if v:exception != "" |
| Xpath 1048576 " X: 0 |
| endif |
| if v:throwpoint != "" |
| Xpath 2097152 " X: 0 |
| endif |
| |
| endif |
| |
| Xcheck 624945 |
| |
| |
| "------------------------------------------------------------------------------- |
| " |
| " Test 59: v:exception and v:throwpoint when discarding exceptions {{{1 |
| " |
| " When a :catch clause is left by a ":break" etc or an error or |
| " interrupt exception, v:exception and v:throwpoint are reset. They |
| " are not affected by an exception that is discarded before being |
| " caught. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| XloopINIT! 1 2 |
| |
| let sfile = expand("<sfile>") |
| |
| function! LineNumber() |
| return substitute(substitute(v:throwpoint, g:sfile, '', ""), |
| \ '\D*\(\d*\).*', '\1', "") |
| endfunction |
| |
| command! -nargs=1 SetLineNumber |
| \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry |
| |
| " Check v:exception/v:throwpoint against second/fourth parameter if |
| " specified, check for being empty else. |
| function! CHECK(n, ...) |
| XloopNEXT |
| let exception = a:0 != 0 ? a:1 : "" " second parameter (optional) |
| let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional) |
| let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional) |
| let error = 0 |
| if emsg != "" |
| " exception is the error number, emsg the English error message text |
| if exception !~ '^E\d\+$' |
| Xout "TODO: Add message number for:" emsg |
| elseif v:lang == "C" || v:lang =~ '^[Ee]n' |
| if exception == "E492" && emsg == "Not an editor command" |
| let exception = '^Vim:' . exception . ': ' . emsg |
| else |
| let exception = '^Vim(\a\+):' . exception . ': ' . emsg |
| endif |
| else |
| if exception == "E492" |
| let exception = '^Vim:' . exception |
| else |
| let exception = '^Vim(\a\+):' . exception |
| endif |
| endif |
| endif |
| if exception == "" && v:exception != "" |
| Xout a:n.": v:exception is set:" v:exception |
| let error = 1 |
| elseif exception != "" && v:exception !~ exception |
| Xout a:n.": v:exception (".v:exception.") does not match" exception |
| let error = 1 |
| endif |
| if line == 0 && v:throwpoint != "" |
| Xout a:n.": v:throwpoint is set:" v:throwpoint |
| let error = 1 |
| elseif line != 0 && v:throwpoint !~ '\<' . line . '\>' |
| Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line |
| let error = 1 |
| endif |
| if !error |
| Xloop 1 " X: 2097151 |
| endif |
| endfunction |
| |
| while 1 |
| try |
| throw "x1" |
| catch /.*/ |
| break |
| endtry |
| endwhile |
| call CHECK(1) |
| |
| while 1 |
| try |
| throw "x2" |
| catch /.*/ |
| break |
| finally |
| call CHECK(2) |
| endtry |
| break |
| endwhile |
| call CHECK(3) |
| |
| while 1 |
| try |
| let errcaught = 0 |
| try |
| try |
| throw "x3" |
| catch /.*/ |
| SetLineNumber line_before_error |
| asdf |
| endtry |
| catch /.*/ |
| let errcaught = 1 |
| call CHECK(4, 'E492', "Not an editor command", |
| \ line_before_error + 1) |
| endtry |
| finally |
| if !errcaught && $VIMNOERRTHROW |
| call CHECK(4) |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| call CHECK(5) |
| |
| Xpath 2097152 " X: 2097152 |
| |
| while 1 |
| try |
| let intcaught = 0 |
| try |
| try |
| throw "x4" |
| catch /.*/ |
| SetLineNumber two_lines_before_interrupt |
| "INTERRUPT |
| let dummy = 0 |
| endtry |
| catch /.*/ |
| let intcaught = 1 |
| call CHECK(6, "Vim:Interrupt", '', |
| \ two_lines_before_interrupt + 2) |
| endtry |
| finally |
| if !intcaught && $VIMNOINTTHROW |
| call CHECK(6) |
| endif |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| call CHECK(7) |
| |
| Xpath 4194304 " X: 4194304 |
| |
| while 1 |
| try |
| let errcaught = 0 |
| try |
| try |
| " if 1 |
| SetLineNumber line_before_throw |
| throw "x5" |
| " missing endif |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| endtry |
| catch /.*/ |
| let errcaught = 1 |
| call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3) |
| endtry |
| finally |
| if !errcaught && $VIMNOERRTHROW |
| call CHECK(8) |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| call CHECK(9) |
| |
| Xpath 16777216 " X: 16777216 |
| |
| try |
| while 1 |
| try |
| throw "x6" |
| finally |
| break |
| endtry |
| break |
| endwhile |
| catch /.*/ |
| Xpath 33554432 " X: 0 |
| endtry |
| call CHECK(10) |
| |
| try |
| while 1 |
| try |
| throw "x7" |
| finally |
| break |
| endtry |
| break |
| endwhile |
| catch /.*/ |
| Xpath 67108864 " X: 0 |
| finally |
| call CHECK(11) |
| endtry |
| call CHECK(12) |
| |
| while 1 |
| try |
| let errcaught = 0 |
| try |
| try |
| throw "x8" |
| finally |
| SetLineNumber line_before_error |
| asdf |
| endtry |
| catch /.*/ |
| let errcaught = 1 |
| call CHECK(13, 'E492', "Not an editor command", |
| \ line_before_error + 1) |
| endtry |
| finally |
| if !errcaught && $VIMNOERRTHROW |
| call CHECK(13) |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| call CHECK(14) |
| |
| Xpath 134217728 " X: 134217728 |
| |
| while 1 |
| try |
| let intcaught = 0 |
| try |
| try |
| throw "x9" |
| finally |
| SetLineNumber two_lines_before_interrupt |
| "INTERRUPT |
| endtry |
| catch /.*/ |
| let intcaught = 1 |
| call CHECK(15, "Vim:Interrupt", '', |
| \ two_lines_before_interrupt + 2) |
| endtry |
| finally |
| if !intcaught && $VIMNOINTTHROW |
| call CHECK(15) |
| endif |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| call CHECK(16) |
| |
| Xpath 268435456 " X: 268435456 |
| |
| while 1 |
| try |
| let errcaught = 0 |
| try |
| try |
| " if 1 |
| SetLineNumber line_before_throw |
| throw "x10" |
| " missing endif |
| finally |
| call CHECK(17) |
| endtry |
| catch /.*/ |
| let errcaught = 1 |
| call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3) |
| endtry |
| finally |
| if !errcaught && $VIMNOERRTHROW |
| call CHECK(18) |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| call CHECK(19) |
| |
| Xpath 536870912 " X: 536870912 |
| |
| while 1 |
| try |
| let errcaught = 0 |
| try |
| try |
| " if 1 |
| SetLineNumber line_before_throw |
| throw "x11" |
| " missing endif |
| endtry |
| catch /.*/ |
| let errcaught = 1 |
| call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3) |
| endtry |
| finally |
| if !errcaught && $VIMNOERRTHROW |
| call CHECK(20) |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| call CHECK(21) |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| endif |
| |
| Xcheck 2038431743 |
| |
| |
| "------------------------------------------------------------------------------- |
| " |
| " Test 60: (Re)throwing v:exception; :echoerr. {{{1 |
| " |
| " A user exception can be rethrown after catching by throwing |
| " v:exception. An error or interrupt exception cannot be rethrown |
| " because Vim exceptions cannot be faked. A Vim exception using the |
| " value of v:exception can, however, be triggered by the :echoerr |
| " command. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| throw "oops" |
| catch /oops/ |
| Xpath 2 " X: 2 |
| throw v:exception " rethrow user exception |
| catch /.*/ |
| Xpath 4 " X: 0 |
| endtry |
| catch /^oops$/ " catches rethrown user exception |
| Xpath 8 " X: 8 |
| catch /.*/ |
| Xpath 16 " X: 0 |
| endtry |
| |
| function! F() |
| try |
| let caught = 0 |
| try |
| Xpath 32 " X: 32 |
| write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e |
| Xpath 64 " X: 0 |
| Xout "did_emsg was reset before executing " . |
| \ "BufWritePost autocommands." |
| catch /^Vim(write):/ |
| let caught = 1 |
| throw v:exception " throw error: cannot fake Vim exception |
| catch /.*/ |
| Xpath 128 " X: 0 |
| finally |
| Xpath 256 " X: 256 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 512 " X: 0 |
| endif |
| endtry |
| catch /^Vim(throw):/ " catches throw error |
| let caught = caught + 1 |
| catch /.*/ |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| if caught != 2 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 4096 " X: 0 |
| elseif caught |
| Xpath 8192 " X: 0 |
| endif |
| return | " discard error for $VIMNOERRTHROW |
| endif |
| endtry |
| endfunction |
| |
| call F() |
| delfunction F |
| |
| function! G() |
| try |
| let caught = 0 |
| try |
| Xpath 16384 " X: 16384 |
| asdf |
| catch /^Vim/ " catch error exception |
| let caught = 1 |
| " Trigger Vim error exception with value specified after :echoerr |
| let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "") |
| echoerr value |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| finally |
| Xpath 65536 " X: 65536 |
| if !caught |
| if !$VIMNOERRTHROW |
| Xpath 131072 " X: 0 |
| else |
| let value = "Error" |
| echoerr value |
| endif |
| endif |
| endtry |
| catch /^Vim(echoerr):/ |
| let caught = caught + 1 |
| if v:exception !~ value |
| Xpath 262144 " X: 0 |
| endif |
| catch /.*/ |
| Xpath 524288 " X: 0 |
| finally |
| Xpath 1048576 " X: 1048576 |
| if caught != 2 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2097152 " X: 0 |
| elseif caught |
| Xpath 4194304 " X: 0 |
| endif |
| return | " discard error for $VIMNOERRTHROW |
| endif |
| endtry |
| endfunction |
| |
| call G() |
| delfunction G |
| |
| unlet! value caught |
| |
| if ExtraVim() |
| try |
| let errcaught = 0 |
| try |
| Xpath 8388608 " X: 8388608 |
| let intcaught = 0 |
| "INTERRUPT |
| catch /^Vim:/ " catch interrupt exception |
| let intcaught = 1 |
| " Trigger Vim error exception with value specified after :echoerr |
| echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "") |
| catch /.*/ |
| Xpath 16777216 " X: 0 |
| finally |
| Xpath 33554432 " X: 33554432 |
| if !intcaught |
| if !$VIMNOINTTHROW |
| Xpath 67108864 " X: 0 |
| else |
| echoerr "Interrupt" |
| endif |
| endif |
| endtry |
| catch /^Vim(echoerr):/ |
| let errcaught = 1 |
| if v:exception !~ "Interrupt" |
| Xpath 134217728 " X: 0 |
| endif |
| finally |
| Xpath 268435456 " X: 268435456 |
| if !errcaught && !$VIMNOERRTHROW |
| Xpath 536870912 " X: 0 |
| endif |
| endtry |
| endif |
| |
| Xcheck 311511339 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 61: Catching interrupt exceptions {{{1 |
| " |
| " When an interrupt occurs inside a :try/:endtry region, an |
| " interrupt exception is thrown and can be caught. Its value is |
| " "Vim:Interrupt". If the interrupt occurs after an error or a :throw |
| " but before a matching :catch is reached, all following :catches of |
| " that try block are ignored, but the interrupt exception can be |
| " caught by the next surrounding try conditional. An interrupt is |
| " ignored when there is a previous interrupt that has not been caught |
| " or causes a :finally clause to be executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| while 1 |
| try |
| try |
| Xpath 1 " X: 1 |
| let caught = 0 |
| "INTERRUPT |
| Xpath 2 " X: 0 |
| catch /^Vim:Interrupt$/ |
| let caught = 1 |
| finally |
| Xpath 4 " X: 4 |
| if caught || $VIMNOINTTHROW |
| Xpath 8 " X: 8 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 16 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| try |
| Xpath 32 " X: 32 |
| asdf |
| Xpath 64 " X: 0 |
| catch /do_not_catch/ |
| Xpath 128 " X: 0 |
| catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW |
| Xpath 256 " X: 0 |
| catch /.*/ |
| Xpath 512 " X: 0 |
| finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW |
| Xpath 1024 " X: 1024 |
| endtry |
| catch /^Vim:Interrupt$/ |
| let caught = 1 |
| finally |
| Xpath 2048 " X: 2048 |
| if caught || $VIMNOINTTHROW |
| Xpath 4096 " X: 4096 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8192 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| try |
| Xpath 16384 " X: 16384 |
| throw "x" |
| Xpath 32768 " X: 0 |
| catch /do_not_catch/ |
| Xpath 65536 " X: 0 |
| catch /x/ "INTERRUPT |
| Xpath 131072 " X: 0 |
| catch /.*/ |
| Xpath 262144 " X: 0 |
| endtry |
| catch /^Vim:Interrupt$/ |
| let caught = 1 |
| finally |
| Xpath 524288 " X: 524288 |
| if caught || $VIMNOINTTHROW |
| Xpath 1048576 " X: 1048576 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 2097152 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| let caught = 0 |
| try |
| Xpath 4194304 " X: 4194304 |
| "INTERRUPT |
| Xpath 8388608 " X: 0 |
| catch /do_not_catch/ "INTERRUPT |
| Xpath 16777216 " X: 0 |
| catch /^Vim:Interrupt$/ |
| let caught = 1 |
| finally |
| Xpath 33554432 " X: 33554432 |
| if caught || $VIMNOINTTHROW |
| Xpath 67108864 " X: 67108864 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 134217728 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard interrupt for $VIMNOINTTHROW |
| endtry |
| endwhile |
| |
| Xpath 268435456 " X: 268435456 |
| |
| endif |
| |
| Xcheck 374889517 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 62: Catching error exceptions {{{1 |
| " |
| " An error inside a :try/:endtry region is converted to an exception |
| " and can be caught. The error exception has a "Vim(cmdname):" prefix |
| " where cmdname is the name of the failing command, or a "Vim:" prefix |
| " if no command name is known. The "Vim" prefixes cannot be faked. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| unlet novar |
| catch /^Vim(unlet):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "") |
| finally |
| Xpath 1 " X: 1 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2 " X: 0 |
| endif |
| if !MSG('E108', "No such variable") |
| Xpath 4 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| throw novar " error in :throw |
| catch /^Vim(throw):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") |
| finally |
| Xpath 16 " X: 16 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 32 " X: 0 |
| endif |
| if caught ? !MSG('E121', "Undefined variable") |
| \ : !MSG('E15', "Invalid expression") |
| Xpath 64 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 128 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| throw "Vim:faked" " error: cannot fake Vim exception |
| catch /^Vim(throw):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") |
| finally |
| Xpath 256 " X: 256 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 512 " X: 0 |
| endif |
| if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix") |
| Xpath 1024 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 2048 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| function! F() |
| while 1 |
| " Missing :endwhile |
| endfunction |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| call F() |
| catch /^Vim(endfunction):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "") |
| finally |
| Xpath 4096 " X: 4096 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 8192 " X: 0 |
| endif |
| if !MSG('E170', "Missing :endwhile") |
| Xpath 16384 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| ExecAsScript F |
| catch /^Vim:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim:', '', "") |
| finally |
| Xpath 65536 " X: 65536 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 131072 " X: 0 |
| endif |
| if !MSG('E170', "Missing :endwhile") |
| Xpath 262144 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 524288 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| function! G() |
| call G() |
| endfunction |
| |
| while 1 |
| try |
| let mfd_save = &mfd |
| set mfd=3 |
| try |
| let caught = 0 |
| call G() |
| catch /^Vim(call):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(call):', '', "") |
| finally |
| Xpath 1048576 " X: 1048576 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2097152 " X: 0 |
| endif |
| if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") |
| Xpath 4194304 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| let &mfd = mfd_save |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| function! H() |
| return H() |
| endfunction |
| |
| while 1 |
| try |
| let mfd_save = &mfd |
| set mfd=3 |
| try |
| let caught = 0 |
| call H() |
| catch /^Vim(return):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(return):', '', "") |
| finally |
| Xpath 16777216 " X: 16777216 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 33554432 " X: 0 |
| endif |
| if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") |
| Xpath 67108864 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 134217728 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| let &mfd = mfd_save |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| unlet! caught mfd_save |
| delfunction F |
| delfunction G |
| delfunction H |
| Xpath 268435456 " X: 268435456 |
| |
| Xcheck 286331153 |
| |
| " Leave MSG() for the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 63: Suppressing error exceptions by :silent!. {{{1 |
| " |
| " A :silent! command inside a :try/:endtry region suppresses the |
| " conversion of errors to an exception and the immediate abortion on |
| " error. When the commands executed by the :silent! themselves open |
| " a new :try/:endtry region, conversion of errors to exception and |
| " immediate abortion is switched on again - until the next :silent! |
| " etc. The :silent! has the effect of setting v:errmsg to the error |
| " message text (without displaying it) and continuing with the next |
| " script line. |
| " |
| " When a command triggering autocommands is executed by :silent! |
| " inside a :try/:endtry, the autocommand execution is not suppressed |
| " on error. |
| " |
| " This test reuses the function MSG() from the previous test. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT! 1 4 |
| |
| let taken = "" |
| |
| function! S(n) abort |
| XloopNEXT |
| let g:taken = g:taken . "E" . a:n |
| let v:errmsg = "" |
| exec "asdf" . a:n |
| |
| " Check that ":silent!" continues: |
| Xloop 1 |
| |
| " Check that ":silent!" sets "v:errmsg": |
| if MSG('E492', "Not an editor command") |
| Xloop 2 |
| endif |
| endfunction |
| |
| function! Foo() |
| while 1 |
| try |
| try |
| let caught = 0 |
| " This is not silent: |
| call S(3) " X: 0 * 16 |
| catch /^Vim:/ |
| let caught = 1 |
| let errmsg3 = substitute(v:exception, '^Vim:', '', "") |
| silent! call S(4) " X: 3 * 64 |
| finally |
| if !caught |
| let errmsg3 = v:errmsg |
| " Do call S(4) here if not executed in :catch. |
| silent! call S(4) |
| endif |
| Xpath 1048576 " X: 1048576 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2097152 " X: 0 |
| endif |
| let v:errmsg = errmsg3 |
| if !MSG('E492', "Not an editor command") |
| Xpath 4194304 " X: 0 |
| endif |
| silent! call S(5) " X: 3 * 256 |
| " Break out of try conditionals that cover ":silent!". This also |
| " discards the aborting error when $VIMNOERRTHROW is non-zero. |
| break |
| endtry |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| endwhile |
| " This is a double ":silent!" (see caller). |
| silent! call S(6) " X: 3 * 1024 |
| endfunction |
| |
| function! Bar() |
| try |
| silent! call S(2) " X: 3 * 4 |
| " X: 3 * 4096 |
| silent! execute "call Foo() | call S(7)" |
| silent! call S(8) " X: 3 * 16384 |
| endtry " normal end of try cond that covers ":silent!" |
| " This has a ":silent!" from the caller: |
| call S(9) " X: 3 * 65536 |
| endfunction |
| |
| silent! call S(1) " X: 3 * 1 |
| silent! call Bar() |
| silent! call S(10) " X: 3 * 262144 |
| |
| let expected = "E1E2E3E4E5E6E7E8E9E10" |
| if taken != expected |
| Xpath 16777216 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| endif |
| |
| augroup TMP |
| autocmd BufWritePost * Xpath 33554432 " X: 33554432 |
| augroup END |
| |
| Xpath 67108864 " X: 67108864 |
| write /i/m/p/o/s/s/i/b/l/e |
| Xpath 134217728 " X: 134217728 |
| |
| autocmd! TMP |
| unlet! caught errmsg3 taken expected |
| delfunction S |
| delfunction Foo |
| delfunction Bar |
| delfunction MSG |
| |
| Xcheck 236978127 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 64: Error exceptions after error, interrupt or :throw {{{1 |
| " |
| " When an error occurs after an interrupt or a :throw but before |
| " a matching :catch is reached, all following :catches of that try |
| " block are ignored, but the error exception can be caught by the next |
| " surrounding try conditional. Any previous error exception is |
| " discarded. An error is ignored when there is a previous error that |
| " has not been caught. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| while 1 |
| try |
| try |
| Xpath 1 " X: 1 |
| let caught = 0 |
| while 1 |
| " if 1 |
| " Missing :endif |
| endwhile " throw error exception |
| catch /^Vim(/ |
| let caught = 1 |
| finally |
| Xpath 2 " X: 2 |
| if caught || $VIMNOERRTHROW |
| Xpath 4 " X: 4 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| Xpath 16 " X: 16 |
| let caught = 0 |
| try |
| " if 1 |
| " Missing :endif |
| catch /.*/ " throw error exception |
| Xpath 32 " X: 0 |
| catch /.*/ |
| Xpath 64 " X: 0 |
| endtry |
| catch /^Vim(/ |
| let caught = 1 |
| finally |
| Xpath 128 " X: 128 |
| if caught || $VIMNOERRTHROW |
| Xpath 256 " X: 256 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 512 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| try |
| Xpath 1024 " X: 1024 |
| "INTERRUPT |
| catch /do_not_catch/ |
| Xpath 2048 " X: 0 |
| " if 1 |
| " Missing :endif |
| catch /.*/ " throw error exception |
| Xpath 4096 " X: 0 |
| catch /.*/ |
| Xpath 8192 " X: 0 |
| endtry |
| catch /^Vim(/ |
| let caught = 1 |
| finally |
| Xpath 16384 " X: 16384 |
| if caught || $VIMNOERRTHROW |
| Xpath 32768 " X: 32768 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 65536 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| try |
| Xpath 131072 " X: 131072 |
| throw "x" |
| catch /do_not_catch/ |
| Xpath 262144 " X: 0 |
| " if 1 |
| " Missing :endif |
| catch /x/ " throw error exception |
| Xpath 524288 " X: 0 |
| catch /.*/ |
| Xpath 1048576 " X: 0 |
| endtry |
| catch /^Vim(/ |
| let caught = 1 |
| finally |
| Xpath 2097152 " X: 2097152 |
| if caught || $VIMNOERRTHROW |
| Xpath 4194304 " X: 4194304 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let caught = 0 |
| Xpath 16777216 " X: 16777216 |
| " endif " :endif without :if; throw error exception |
| " if 1 |
| " Missing :endif |
| catch /do_not_catch/ " ignore new error |
| Xpath 33554432 " X: 0 |
| catch /^Vim(endif):/ |
| let caught = 1 |
| catch /^Vim(/ |
| Xpath 67108864 " X: 0 |
| finally |
| Xpath 134217728 " X: 134217728 |
| if caught || $VIMNOERRTHROW |
| Xpath 268435456 " X: 268435456 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 536870912 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| endif |
| |
| Xcheck 1499645335 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 65: Errors in the /pattern/ argument of a :catch {{{1 |
| " |
| " On an error in the /pattern/ argument of a :catch, the :catch does |
| " not match. Any following :catches of the same :try/:endtry don't |
| " match either. Finally clauses are executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| throw "oops" |
| catch /^oops$/ |
| Xpath 2 " X: 2 |
| catch /\)/ " not checked; exception has already been caught |
| Xpath 4 " X: 0 |
| endtry |
| Xpath 8 " X: 8 |
| catch /.*/ |
| Xpath 16 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| function! F() |
| try |
| let caught = 0 |
| try |
| try |
| Xpath 32 " X: 32 |
| throw "ab" |
| catch /abc/ " does not catch |
| Xpath 64 " X: 0 |
| catch /\)/ " error; discards exception |
| Xpath 128 " X: 0 |
| catch /.*/ " not checked |
| Xpath 256 " X: 0 |
| finally |
| Xpath 512 " X: 512 |
| endtry |
| Xpath 1024 " X: 0 |
| catch /^ab$/ " checked, but original exception is discarded |
| Xpath 2048 " X: 0 |
| catch /^Vim(catch):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "") |
| finally |
| Xpath 4096 " X: 4096 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 8192 " X: 0 |
| endif |
| if caught ? !MSG('E55', 'Unmatched \\)') |
| \ : !MSG('E475', "Invalid argument") |
| Xpath 16384 " X: 0 |
| endif |
| if !caught |
| return | " discard error |
| endif |
| endtry |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| endfunction |
| |
| call F() |
| Xpath 65536 " X: 65536 |
| |
| delfunction MSG |
| delfunction F |
| unlet! caught |
| |
| Xcheck 70187 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 66: Stop range :call on error, interrupt, or :throw {{{1 |
| " |
| " When a function which is multiply called for a range since it |
| " doesn't handle the range itself has an error in a command |
| " dynamically enclosed by :try/:endtry or gets an interrupt or |
| " executes a :throw, no more calls for the remaining lines in the |
| " range are made. On an error in a command not dynamically enclosed |
| " by :try/:endtry, the function is executed again for the remaining |
| " lines in the range. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| let file = tempname() |
| exec "edit" file |
| |
| insert |
| line 1 |
| line 2 |
| line 3 |
| . |
| |
| XloopINIT! 1 2 |
| |
| let taken = "" |
| let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)" |
| |
| function! F(reason, n) abort |
| let g:taken = g:taken . "F" . a:n . |
| \ substitute(a:reason, '\(\l\).*', '\u\1', "") . |
| \ "(" . line(".") . ")" |
| |
| if a:reason == "error" |
| asdf |
| elseif a:reason == "interrupt" |
| "INTERRUPT |
| let dummy = 0 |
| elseif a:reason == "throw" |
| throw "xyz" |
| elseif a:reason == "aborting error" |
| XloopNEXT |
| if g:taken != g:expected |
| Xloop 1 " X: 0 |
| Xout "'taken' is" g:taken "instead of" g:expected |
| endif |
| try |
| bwipeout! |
| call delete(file) |
| asdf |
| endtry |
| endif |
| endfunction |
| |
| function! G(reason, n) |
| let g:taken = g:taken . "G" . a:n . |
| \ substitute(a:reason, '\(\l\).*', '\u\1', "") |
| 1,3call F(a:reason, a:n) |
| endfunction |
| |
| Xpath 8 " X: 8 |
| call G("error", 1) |
| try |
| Xpath 16 " X: 16 |
| try |
| call G("error", 2) |
| Xpath 32 " X: 0 |
| finally |
| Xpath 64 " X: 64 |
| try |
| call G("interrupt", 3) |
| Xpath 128 " X: 0 |
| finally |
| Xpath 256 " X: 256 |
| try |
| call G("throw", 4) |
| Xpath 512 " X: 0 |
| endtry |
| endtry |
| endtry |
| catch /xyz/ |
| Xpath 1024 " X: 1024 |
| catch /.*/ |
| Xpath 2048 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| Xpath 4096 " X: 4096 |
| call G("aborting error", 5) |
| Xpath 8192 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| |
| endif |
| |
| Xcheck 5464 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 67: :throw across :call command {{{1 |
| " |
| " On a call command, an exception might be thrown when evaluating the |
| " function name, during evaluation of the arguments, or when the |
| " function is being executed. The exception can be caught by the |
| " caller. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! THROW(x, n) |
| if a:n == 1 |
| Xpath 1 " X: 1 |
| elseif a:n == 2 |
| Xpath 2 " X: 2 |
| elseif a:n == 3 |
| Xpath 4 " X: 4 |
| endif |
| throw a:x |
| endfunction |
| |
| function! NAME(x, n) |
| if a:n == 1 |
| Xpath 8 " X: 0 |
| elseif a:n == 2 |
| Xpath 16 " X: 16 |
| elseif a:n == 3 |
| Xpath 32 " X: 32 |
| elseif a:n == 4 |
| Xpath 64 " X: 64 |
| endif |
| return a:x |
| endfunction |
| |
| function! ARG(x, n) |
| if a:n == 1 |
| Xpath 128 " X: 0 |
| elseif a:n == 2 |
| Xpath 256 " X: 0 |
| elseif a:n == 3 |
| Xpath 512 " X: 512 |
| elseif a:n == 4 |
| Xpath 1024 " X: 1024 |
| endif |
| return a:x |
| endfunction |
| |
| function! F(x, n) |
| if a:n == 2 |
| Xpath 2048 " X: 0 |
| elseif a:n == 4 |
| Xpath 4096 " X: 4096 |
| endif |
| endfunction |
| |
| while 1 |
| try |
| let error = 0 |
| let v:errmsg = "" |
| |
| while 1 |
| try |
| Xpath 8192 " X: 8192 |
| call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) |
| Xpath 16384 " X: 0 |
| catch /^name$/ |
| Xpath 32768 " X: 32768 |
| catch /.*/ |
| let error = 1 |
| Xout "1:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "1:" v:errmsg |
| endif |
| if error |
| Xpath 65536 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 131072 " X: 131072 |
| call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) |
| Xpath 262144 " X: 0 |
| catch /^arg$/ |
| Xpath 524288 " X: 524288 |
| catch /.*/ |
| let error = 1 |
| Xout "2:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "2:" v:errmsg |
| endif |
| if error |
| Xpath 1048576 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 2097152 " X: 2097152 |
| call {NAME("THROW", 3)}(ARG("call", 3), 3) |
| Xpath 4194304 " X: 0 |
| catch /^call$/ |
| Xpath 8388608 " X: 8388608 |
| catch /^0$/ " default return value |
| Xpath 16777216 " X: 0 |
| Xout "3:" v:throwpoint |
| catch /.*/ |
| let error = 1 |
| Xout "3:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "3:" v:errmsg |
| endif |
| if error |
| Xpath 33554432 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 67108864 " X: 67108864 |
| call {NAME("F", 4)}(ARG(4711, 4), 4) |
| Xpath 134217728 " X: 134217728 |
| catch /.*/ |
| let error = 1 |
| Xout "4:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "4:" v:errmsg |
| endif |
| if error |
| Xpath 268435456 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| catch /^0$/ " default return value |
| Xpath 536870912 " X: 0 |
| Xout v:throwpoint |
| catch /.*/ |
| let error = 1 |
| Xout v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout v:errmsg |
| endif |
| if error |
| Xpath 1073741824 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| unlet error |
| delfunction F |
| |
| Xcheck 212514423 |
| |
| " Leave THROW(), NAME(), and ARG() for the next test. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 68: :throw across function calls in expressions {{{1 |
| " |
| " On a function call within an expression, an exception might be |
| " thrown when evaluating the function name, during evaluation of the |
| " arguments, or when the function is being executed. The exception |
| " can be caught by the caller. |
| " |
| " This test reuses the functions THROW(), NAME(), and ARG() from the |
| " previous test. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F(x, n) |
| if a:n == 2 |
| Xpath 2048 " X: 0 |
| elseif a:n == 4 |
| Xpath 4096 " X: 4096 |
| endif |
| return a:x |
| endfunction |
| |
| unlet! var1 var2 var3 var4 |
| |
| while 1 |
| try |
| let error = 0 |
| let v:errmsg = "" |
| |
| while 1 |
| try |
| Xpath 8192 " X: 8192 |
| let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) |
| Xpath 16384 " X: 0 |
| catch /^name$/ |
| Xpath 32768 " X: 32768 |
| catch /.*/ |
| let error = 1 |
| Xout "1:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "1:" v:errmsg |
| endif |
| if error |
| Xpath 65536 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 131072 " X: 131072 |
| let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) |
| Xpath 262144 " X: 0 |
| catch /^arg$/ |
| Xpath 524288 " X: 524288 |
| catch /.*/ |
| let error = 1 |
| Xout "2:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "2:" v:errmsg |
| endif |
| if error |
| Xpath 1048576 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 2097152 " X: 2097152 |
| let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3) |
| Xpath 4194304 " X: 0 |
| catch /^call$/ |
| Xpath 8388608 " X: 8388608 |
| catch /^0$/ " default return value |
| Xpath 16777216 " X: 0 |
| Xout "3:" v:throwpoint |
| catch /.*/ |
| let error = 1 |
| Xout "3:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "3:" v:errmsg |
| endif |
| if error |
| Xpath 33554432 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 67108864 " X: 67108864 |
| let var4 = {NAME("F", 4)}(ARG(4711, 4), 4) |
| Xpath 134217728 " X: 134217728 |
| catch /.*/ |
| let error = 1 |
| Xout "4:" v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout "4:" v:errmsg |
| endif |
| if error |
| Xpath 268435456 " X: 0 |
| endif |
| let error = 0 |
| let v:errmsg = "" |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| catch /^0$/ " default return value |
| Xpath 536870912 " X: 0 |
| Xout v:throwpoint |
| catch /.*/ |
| let error = 1 |
| Xout v:exception "in" v:throwpoint |
| finally |
| if !error && $VIMNOERRTHROW && v:errmsg != "" |
| let error = 1 |
| Xout v:errmsg |
| endif |
| if error |
| Xpath 1073741824 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| if exists("var1") || exists("var2") || exists("var3") || |
| \ !exists("var4") || var4 != 4711 |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| if exists("var1") |
| Xout "var1 =" var1 |
| endif |
| if exists("var2") |
| Xout "var2 =" var2 |
| endif |
| if exists("var3") |
| Xout "var3 =" var3 |
| endif |
| if !exists("var4") |
| Xout "var4 unset" |
| elseif var4 != 4711 |
| Xout "var4 =" var4 |
| endif |
| endif |
| |
| unlet! error var1 var2 var3 var4 |
| delfunction THROW |
| delfunction NAME |
| delfunction ARG |
| delfunction F |
| |
| Xcheck 212514423 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 69: :throw across :if, :elseif, :while {{{1 |
| " |
| " On an :if, :elseif, or :while command, an exception might be thrown |
| " during evaluation of the expression to test. The exception can be |
| " caught by the script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT! 1 2 |
| |
| function! THROW(x) |
| XloopNEXT |
| Xloop 1 " X: 1 + 2 + 4 |
| throw a:x |
| endfunction |
| |
| try |
| |
| try |
| Xpath 8 " X: 8 |
| if 4711 == THROW("if") + 111 |
| Xpath 16 " X: 0 |
| else |
| Xpath 32 " X: 0 |
| endif |
| Xpath 64 " X: 0 |
| catch /^if$/ |
| Xpath 128 " X: 128 |
| catch /.*/ |
| Xpath 256 " X: 0 |
| Xout "if:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 512 " X: 512 |
| if 4711 == 4 + 7 + 1 + 1 |
| Xpath 1024 " X: 0 |
| elseif 4711 == THROW("elseif") + 222 |
| Xpath 2048 " X: 0 |
| else |
| Xpath 4096 " X: 0 |
| endif |
| Xpath 8192 " X: 0 |
| catch /^elseif$/ |
| Xpath 16384 " X: 16384 |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| Xout "elseif:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 65536 " X: 65536 |
| while 4711 == THROW("while") + 4711 |
| Xpath 131072 " X: 0 |
| break |
| endwhile |
| Xpath 262144 " X: 0 |
| catch /^while$/ |
| Xpath 524288 " X: 524288 |
| catch /.*/ |
| Xpath 1048576 " X: 0 |
| Xout "while:" v:exception "in" v:throwpoint |
| endtry |
| |
| catch /^0$/ " default return value |
| Xpath 2097152 " X: 0 |
| Xout v:throwpoint |
| catch /.*/ |
| Xout v:exception "in" v:throwpoint |
| Xpath 4194304 " X: 0 |
| endtry |
| |
| Xpath 8388608 " X: 8388608 |
| |
| delfunction THROW |
| |
| Xcheck 8995471 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 70: :throw across :return or :throw {{{1 |
| " |
| " On a :return or :throw command, an exception might be thrown during |
| " evaluation of the expression to return or throw, respectively. The |
| " exception can be caught by the script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let taken = "" |
| |
| function! THROW(x, n) |
| let g:taken = g:taken . "T" . a:n |
| throw a:x |
| endfunction |
| |
| function! F(x, y, n) |
| let g:taken = g:taken . "F" . a:n |
| return a:x + THROW(a:y, a:n) |
| endfunction |
| |
| function! G(x, y, n) |
| let g:taken = g:taken . "G" . a:n |
| throw a:x . THROW(a:y, a:n) |
| return a:x |
| endfunction |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| call F(4711, "return", 1) |
| Xpath 2 " X: 0 |
| catch /^return$/ |
| Xpath 4 " X: 4 |
| catch /.*/ |
| Xpath 8 " X: 0 |
| Xout "return:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 16 " X: 16 |
| let var = F(4712, "return-var", 2) |
| Xpath 32 " X: 0 |
| catch /^return-var$/ |
| Xpath 64 " X: 64 |
| catch /.*/ |
| Xpath 128 " X: 0 |
| Xout "return-var:" v:exception "in" v:throwpoint |
| finally |
| unlet! var |
| endtry |
| |
| try |
| Xpath 256 " X: 256 |
| throw "except1" . THROW("throw1", 3) |
| Xpath 512 " X: 0 |
| catch /^except1/ |
| Xpath 1024 " X: 0 |
| catch /^throw1$/ |
| Xpath 2048 " X: 2048 |
| catch /.*/ |
| Xpath 4096 " X: 0 |
| Xout "throw1:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 8192 " X: 8192 |
| call G("except2", "throw2", 4) |
| Xpath 16384 " X: 0 |
| catch /^except2/ |
| Xpath 32768 " X: 0 |
| catch /^throw2$/ |
| Xpath 65536 " X: 65536 |
| catch /.*/ |
| Xpath 131072 " X: 0 |
| Xout "throw2:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 262144 " X: 262144 |
| let var = G("except3", "throw3", 5) |
| Xpath 524288 " X: 0 |
| catch /^except3/ |
| Xpath 1048576 " X: 0 |
| catch /^throw3$/ |
| Xpath 2097152 " X: 2097152 |
| catch /.*/ |
| Xpath 4194304 " X: 0 |
| Xout "throw3:" v:exception "in" v:throwpoint |
| finally |
| unlet! var |
| endtry |
| |
| let expected = "F1T1F2T2T3G4T4G5T5" |
| if taken != expected |
| Xpath 8388608 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| endif |
| |
| catch /^0$/ " default return value |
| Xpath 16777216 " X: 0 |
| Xout v:throwpoint |
| catch /.*/ |
| Xpath 33554432 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 67108864 " X: 67108864 |
| |
| unlet taken expected |
| delfunction THROW |
| delfunction F |
| delfunction G |
| |
| Xcheck 69544277 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 71: :throw across :echo variants and :execute {{{1 |
| " |
| " On an :echo, :echon, :echomsg, :echoerr, or :execute command, an |
| " exception might be thrown during evaluation of the arguments to |
| " be displayed or executed as a command, respectively. Any following |
| " arguments are not evaluated, then. The exception can be caught by |
| " the script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let taken = "" |
| |
| function! THROW(x, n) |
| let g:taken = g:taken . "T" . a:n |
| throw a:x |
| endfunction |
| |
| function! F(n) |
| let g:taken = g:taken . "F" . a:n |
| return "F" . a:n |
| endfunction |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| echo "echo" . THROW("echo-except", 1) F(1) |
| Xpath 2 " X: 0 |
| catch /^echo-except$/ |
| Xpath 4 " X: 4 |
| catch /.*/ |
| Xpath 8 " X: 0 |
| Xout "echo:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 16 " X: 16 |
| echon "echon" . THROW("echon-except", 2) F(2) |
| Xpath 32 " X: 0 |
| catch /^echon-except$/ |
| Xpath 64 " X: 64 |
| catch /.*/ |
| Xpath 128 " X: 0 |
| Xout "echon:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 256 " X: 256 |
| echomsg "echomsg" . THROW("echomsg-except", 3) F(3) |
| Xpath 512 " X: 0 |
| catch /^echomsg-except$/ |
| Xpath 1024 " X: 1024 |
| catch /.*/ |
| Xpath 2048 " X: 0 |
| Xout "echomsg:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 4096 " X: 4096 |
| echoerr "echoerr" . THROW("echoerr-except", 4) F(4) |
| Xpath 8192 " X: 0 |
| catch /^echoerr-except$/ |
| Xpath 16384 " X: 16384 |
| catch /Vim/ |
| Xpath 32768 " X: 0 |
| catch /echoerr/ |
| Xpath 65536 " X: 0 |
| catch /.*/ |
| Xpath 131072 " X: 0 |
| Xout "echoerr:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 262144 " X: 262144 |
| execute "echo 'execute" . THROW("execute-except", 5) F(5) "'" |
| Xpath 524288 " X: 0 |
| catch /^execute-except$/ |
| Xpath 1048576 " X: 1048576 |
| catch /.*/ |
| Xpath 2097152 " X: 0 |
| Xout "execute:" v:exception "in" v:throwpoint |
| endtry |
| |
| let expected = "T1T2T3T4T5" |
| if taken != expected |
| Xpath 4194304 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| endif |
| |
| catch /^0$/ " default return value |
| Xpath 8388608 " X: 0 |
| Xout v:throwpoint |
| catch /.*/ |
| Xpath 16777216 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 33554432 " X: 33554432 |
| |
| unlet taken expected |
| delfunction THROW |
| delfunction F |
| |
| Xcheck 34886997 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 72: :throw across :let or :unlet {{{1 |
| " |
| " On a :let command, an exception might be thrown during evaluation |
| " of the expression to assign. On an :let or :unlet command, the |
| " evaluation of the name of the variable to be assigned or list or |
| " deleted, respectively, may throw an exception. Any following |
| " arguments are not evaluated, then. The exception can be caught by |
| " the script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let throwcount = 0 |
| |
| function! THROW(x) |
| let g:throwcount = g:throwcount + 1 |
| throw a:x |
| endfunction |
| |
| try |
| try |
| let $VAR = "old_value" |
| Xpath 1 " X: 1 |
| let $VAR = "let(" . THROW("var") . ")" |
| Xpath 2 " X: 0 |
| catch /^var$/ |
| Xpath 4 " X: 4 |
| finally |
| if $VAR != "old_value" |
| Xpath 8 " X: 0 |
| endif |
| endtry |
| |
| try |
| let @a = "old_value" |
| Xpath 16 " X: 16 |
| let @a = "let(" . THROW("reg") . ")" |
| Xpath 32 " X: 0 |
| catch /^reg$/ |
| try |
| Xpath 64 " X: 64 |
| let @A = "let(" . THROW("REG") . ")" |
| Xpath 128 " X: 0 |
| catch /^REG$/ |
| Xpath 256 " X: 256 |
| endtry |
| finally |
| if @a != "old_value" |
| Xpath 512 " X: 0 |
| endif |
| if @A != "old_value" |
| Xpath 1024 " X: 0 |
| endif |
| endtry |
| |
| try |
| let saved_gpath = &g:path |
| let saved_lpath = &l:path |
| Xpath 2048 " X: 2048 |
| let &path = "let(" . THROW("opt") . ")" |
| Xpath 4096 " X: 0 |
| catch /^opt$/ |
| try |
| Xpath 8192 " X: 8192 |
| let &g:path = "let(" . THROW("gopt") . ")" |
| Xpath 16384 " X: 0 |
| catch /^gopt$/ |
| try |
| Xpath 32768 " X: 32768 |
| let &l:path = "let(" . THROW("lopt") . ")" |
| Xpath 65536 " X: 0 |
| catch /^lopt$/ |
| Xpath 131072 " X: 131072 |
| endtry |
| endtry |
| finally |
| if &g:path != saved_gpath || &l:path != saved_lpath |
| Xpath 262144 " X: 0 |
| endif |
| let &g:path = saved_gpath |
| let &l:path = saved_lpath |
| endtry |
| |
| unlet! var1 var2 var3 |
| |
| try |
| Xpath 524288 " X: 524288 |
| let var1 = "let(" . THROW("var1") . ")" |
| Xpath 1048576 " X: 0 |
| catch /^var1$/ |
| Xpath 2097152 " X: 2097152 |
| finally |
| if exists("var1") |
| Xpath 4194304 " X: 0 |
| endif |
| endtry |
| |
| try |
| let var2 = "old_value" |
| Xpath 8388608 " X: 8388608 |
| let var2 = "let(" . THROW("var2"). ")" |
| Xpath 16777216 " X: 0 |
| catch /^var2$/ |
| Xpath 33554432 " X: 33554432 |
| finally |
| if var2 != "old_value" |
| Xpath 67108864 " X: 0 |
| endif |
| endtry |
| |
| try |
| Xpath 134217728 " X: 134217728 |
| let var{THROW("var3")} = 4711 |
| Xpath 268435456 " X: 0 |
| catch /^var3$/ |
| Xpath 536870912 " X: 536870912 |
| endtry |
| |
| let addpath = "" |
| |
| function ADDPATH(p) |
| let g:addpath = g:addpath . a:p |
| endfunction |
| |
| try |
| call ADDPATH("T1") |
| let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3") |
| call ADDPATH("T4") |
| catch /^var4$/ |
| call ADDPATH("T5") |
| endtry |
| |
| try |
| call ADDPATH("T6") |
| unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8") |
| call ADDPATH("T9") |
| catch /^var5$/ |
| call ADDPATH("T10") |
| endtry |
| |
| if addpath != "T1T5T6T10" || throwcount != 11 |
| throw "addpath: " . addpath . ", throwcount: " . throwcount |
| endif |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| unlet! var1 var2 var3 addpath throwcount |
| delfunction THROW |
| |
| Xcheck 1789569365 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 73: :throw across :function, :delfunction {{{1 |
| " |
| " The :function and :delfunction commands may cause an expression |
| " specified in braces to be evaluated. During evaluation, an |
| " exception might be thrown. The exception can be caught by the |
| " script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let taken = "" |
| |
| function! THROW(x, n) |
| let g:taken = g:taken . "T" . a:n |
| throw a:x |
| endfunction |
| |
| function! EXPR(x, n) |
| let g:taken = g:taken . "E" . a:n |
| if a:n % 2 == 0 |
| call THROW(a:x, a:n) |
| endif |
| return 2 - a:n % 2 |
| endfunction |
| |
| try |
| try |
| " Define function. |
| Xpath 1 " X: 1 |
| function! F0() |
| endfunction |
| Xpath 2 " X: 2 |
| function! F{EXPR("function-def-ok", 1)}() |
| endfunction |
| Xpath 4 " X: 4 |
| function! F{EXPR("function-def", 2)}() |
| endfunction |
| Xpath 8 " X: 0 |
| catch /^function-def-ok$/ |
| Xpath 16 " X: 0 |
| catch /^function-def$/ |
| Xpath 32 " X: 32 |
| catch /.*/ |
| Xpath 64 " X: 0 |
| Xout "def:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| " List function. |
| Xpath 128 " X: 128 |
| function F0 |
| Xpath 256 " X: 256 |
| function F{EXPR("function-lst-ok", 3)} |
| Xpath 512 " X: 512 |
| function F{EXPR("function-lst", 4)} |
| Xpath 1024 " X: 0 |
| catch /^function-lst-ok$/ |
| Xpath 2048 " X: 0 |
| catch /^function-lst$/ |
| Xpath 4096 " X: 4096 |
| catch /.*/ |
| Xpath 8192 " X: 0 |
| Xout "lst:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| " Delete function |
| Xpath 16384 " X: 16384 |
| delfunction F0 |
| Xpath 32768 " X: 32768 |
| delfunction F{EXPR("function-del-ok", 5)} |
| Xpath 65536 " X: 65536 |
| delfunction F{EXPR("function-del", 6)} |
| Xpath 131072 " X: 0 |
| catch /^function-del-ok$/ |
| Xpath 262144 " X: 0 |
| catch /^function-del$/ |
| Xpath 524288 " X: 524288 |
| catch /.*/ |
| Xpath 1048576 " X: 0 |
| Xout "del:" v:exception "in" v:throwpoint |
| endtry |
| |
| let expected = "E1E2T2E3E4T4E5E6T6" |
| if taken != expected |
| Xpath 2097152 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| endif |
| |
| catch /.*/ |
| Xpath 4194304 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xpath 8388608 " X: 8388608 |
| |
| unlet taken expected |
| delfunction THROW |
| delfunction EXPR |
| |
| Xcheck 9032615 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 74: :throw across builtin functions and commands {{{1 |
| " |
| " Some functions like exists(), searchpair() take expression |
| " arguments, other functions or commands like substitute() or |
| " :substitute cause an expression (specified in the regular |
| " expression) to be evaluated. During evaluation an exception |
| " might be thrown. The exception can be caught by the script. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| let taken = "" |
| |
| function! THROW(x, n) |
| let g:taken = g:taken . "T" . a:n |
| throw a:x |
| endfunction |
| |
| function! EXPR(x, n) |
| let g:taken = g:taken . "E" . a:n |
| call THROW(a:x . a:n, a:n) |
| return "EXPR" |
| endfunction |
| |
| function! SKIP(x, n) |
| let g:taken = g:taken . "S" . a:n . "(" . line(".") |
| let theline = getline(".") |
| if theline =~ "skip" |
| let g:taken = g:taken . "s)" |
| return 1 |
| elseif theline =~ "throw" |
| let g:taken = g:taken . "t)" |
| call THROW(a:x . a:n, a:n) |
| else |
| let g:taken = g:taken . ")" |
| return 0 |
| endif |
| endfunction |
| |
| function! SUBST(x, n) |
| let g:taken = g:taken . "U" . a:n . "(" . line(".") |
| let theline = getline(".") |
| if theline =~ "not" " SUBST() should not be called for this line |
| let g:taken = g:taken . "n)" |
| call THROW(a:x . a:n, a:n) |
| elseif theline =~ "throw" |
| let g:taken = g:taken . "t)" |
| call THROW(a:x . a:n, a:n) |
| else |
| let g:taken = g:taken . ")" |
| return "replaced" |
| endif |
| endfunction |
| |
| try |
| try |
| Xpath 1 " X: 1 |
| let result = exists('*{EXPR("exists", 1)}') |
| Xpath 2 " X: 0 |
| catch /^exists1$/ |
| Xpath 4 " X: 4 |
| try |
| let result = exists('{EXPR("exists", 2)}') |
| Xpath 8 " X: 0 |
| catch /^exists2$/ |
| Xpath 16 " X: 16 |
| catch /.*/ |
| Xpath 32 " X: 0 |
| Xout "exists2:" v:exception "in" v:throwpoint |
| endtry |
| catch /.*/ |
| Xpath 64 " X: 0 |
| Xout "exists1:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| let file = tempname() |
| exec "edit" file |
| insert |
| begin |
| xx |
| middle 3 |
| xx |
| middle 5 skip |
| xx |
| middle 7 throw |
| xx |
| end |
| . |
| normal! gg |
| Xpath 128 " X: 128 |
| let result = |
| \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)') |
| Xpath 256 " X: 256 |
| let result = |
| \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)') |
| Xpath 512 " X: 0 |
| let result = |
| \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)') |
| Xpath 1024 " X: 0 |
| catch /^searchpair[35]$/ |
| Xpath 2048 " X: 0 |
| catch /^searchpair4$/ |
| Xpath 4096 " X: 4096 |
| catch /.*/ |
| Xpath 8192 " X: 0 |
| Xout "searchpair:" v:exception "in" v:throwpoint |
| finally |
| bwipeout! |
| call delete(file) |
| endtry |
| |
| try |
| let file = tempname() |
| exec "edit" file |
| insert |
| subst 1 |
| subst 2 |
| not |
| subst 4 |
| subst throw |
| subst 6 |
| . |
| normal! gg |
| Xpath 16384 " X: 16384 |
| 1,2substitute/subst/\=SUBST("substitute", 6)/ |
| try |
| Xpath 32768 " X: 32768 |
| try |
| let v:errmsg = "" |
| 3substitute/subst/\=SUBST("substitute", 7)/ |
| finally |
| if v:errmsg != "" |
| " If exceptions are not thrown on errors, fake the error |
| " exception in order to get the same execution path. |
| throw "faked Vim(substitute)" |
| endif |
| endtry |
| catch /Vim(substitute)/ " Pattern not found ('e' flag missing) |
| Xpath 65536 " X: 65536 |
| 3substitute/subst/\=SUBST("substitute", 8)/e |
| Xpath 131072 " X: 131072 |
| endtry |
| Xpath 262144 " X: 262144 |
| 4,6substitute/subst/\=SUBST("substitute", 9)/ |
| Xpath 524288 " X: 0 |
| catch /^substitute[678]/ |
| Xpath 1048576 " X: 0 |
| catch /^substitute9/ |
| Xpath 2097152 " X: 2097152 |
| finally |
| bwipeout! |
| call delete(file) |
| endtry |
| |
| try |
| Xpath 4194304 " X: 4194304 |
| let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '') |
| Xpath 8388608 " X: 0 |
| catch /substitute()y/ |
| Xpath 16777216 " X: 16777216 |
| catch /.*/ |
| Xpath 33554432 " X: 0 |
| Xout "substitute()y:" v:exception "in" v:throwpoint |
| endtry |
| |
| try |
| Xpath 67108864 " X: 67108864 |
| let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '') |
| Xpath 134217728 " X: 134217728 |
| catch /substitute()n/ |
| Xpath 268435456 " X: 0 |
| catch /.*/ |
| Xpath 536870912 " X: 0 |
| Xout "substitute()n:" v:exception "in" v:throwpoint |
| endtry |
| |
| let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10" |
| if taken != expected |
| Xpath 1073741824 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| endif |
| |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| unlet result var taken expected |
| delfunction THROW |
| delfunction EXPR |
| delfunction SKIP |
| delfunction SUBST |
| |
| Xcheck 224907669 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 75: Errors in builtin functions. {{{1 |
| " |
| " On an error in a builtin function called inside a :try/:endtry |
| " region, the evaluation of the expression calling that function and |
| " the command containing that expression are abandoned. The error can |
| " be caught as an exception. |
| " |
| " A simple :call of the builtin function is a trivial case. If the |
| " builtin function is called in the argument list of another function, |
| " no further arguments are evaluated, and the other function is not |
| " executed. If the builtin function is called from the argument of |
| " a :return command, the :return command is not executed. If the |
| " builtin function is called from the argument of a :throw command, |
| " the :throw command is not executed. The evaluation of the |
| " expression calling the builtin function is abandoned. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! F1(arg1) |
| Xpath 1 " X: 0 |
| endfunction |
| |
| function! F2(arg1, arg2) |
| Xpath 2 " X: 0 |
| endfunction |
| |
| function! G() |
| Xpath 4 " X: 0 |
| endfunction |
| |
| function! H() |
| Xpath 8 " X: 0 |
| endfunction |
| |
| function! R() |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 16 " X: 16 |
| return append(1, "s") |
| catch /E21/ |
| let caught = 1 |
| catch /.*/ |
| Xpath 32 " X: 0 |
| finally |
| Xpath 64 " X: 64 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 128 " X: 128 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| Xpath 256 " X: 256 |
| endfunction |
| |
| try |
| set noma " let append() fail with "E21" |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 512 " X: 512 |
| call append(1, "s") |
| catch /E21/ |
| let caught = 1 |
| catch /.*/ |
| Xpath 1024 " X: 0 |
| finally |
| Xpath 2048 " X: 2048 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 4096 " X: 4096 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 8192 " X: 8192 |
| call F1('x' . append(1, "s")) |
| catch /E21/ |
| let caught = 1 |
| catch /.*/ |
| Xpath 16384 " X: 0 |
| finally |
| Xpath 32768 " X: 32768 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 65536 " X: 65536 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 131072 " X: 131072 |
| call F2('x' . append(1, "s"), G()) |
| catch /E21/ |
| let caught = 1 |
| catch /.*/ |
| Xpath 262144 " X: 0 |
| finally |
| Xpath 524288 " X: 524288 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 1048576 " X: 1048576 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| call R() |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 2097152 " X: 2097152 |
| throw "T" . append(1, "s") |
| catch /E21/ |
| let caught = 1 |
| catch /^T.*/ |
| Xpath 4194304 " X: 0 |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| finally |
| Xpath 16777216 " X: 16777216 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 33554432 " X: 33554432 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| let caught = 0 |
| let v:errmsg = "" |
| Xpath 67108864 " X: 67108864 |
| let x = "a" |
| let x = x . "b" . append(1, "s") . H() |
| catch /E21/ |
| let caught = 1 |
| catch /.*/ |
| Xpath 134217728 " X: 0 |
| finally |
| Xpath 268435456 " X: 268435456 |
| if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21' |
| Xpath 536870912 " X: 536870912 |
| endif |
| if x == "a" |
| Xpath 1073741824 " X: 1073741824 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| set ma& |
| endtry |
| |
| unlet! caught x |
| delfunction F1 |
| delfunction F2 |
| delfunction G |
| delfunction H |
| delfunction R |
| |
| Xcheck 2000403408 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 76: Errors, interrupts, :throw during expression evaluation {{{1 |
| " |
| " When a function call made during expression evaluation is aborted |
| " due to an error inside a :try/:endtry region or due to an interrupt |
| " or a :throw, the expression evaluation is aborted as well. No |
| " message is displayed for the cancelled expression evaluation. On an |
| " error not inside :try/:endtry, the expression evaluation continues. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| let taken = "" |
| |
| function! ERR(n) |
| let g:taken = g:taken . "E" . a:n |
| asdf |
| endfunction |
| |
| function! ERRabort(n) abort |
| let g:taken = g:taken . "A" . a:n |
| asdf |
| endfunction " returns -1; may cause follow-up msg for illegal var/func name |
| |
| function! WRAP(n, arg) |
| let g:taken = g:taken . "W" . a:n |
| let g:saved_errmsg = v:errmsg |
| return arg |
| endfunction |
| |
| function! INT(n) |
| let g:taken = g:taken . "I" . a:n |
| "INTERRUPT9 |
| let dummy = 0 |
| endfunction |
| |
| function! THR(n) |
| let g:taken = g:taken . "T" . a:n |
| throw "should not be caught" |
| endfunction |
| |
| function! CONT(n) |
| let g:taken = g:taken . "C" . a:n |
| endfunction |
| |
| function! MSG(n) |
| let g:taken = g:taken . "M" . a:n |
| let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg |
| let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf" |
| if errmsg !~ msgptn |
| let g:taken = g:taken . "x" |
| Xout "Expr" a:n.": Unexpected message:" v:errmsg |
| endif |
| let v:errmsg = "" |
| let g:saved_errmsg = "" |
| endfunction |
| |
| let v:errmsg = "" |
| |
| try |
| let t = 1 |
| XloopINIT 1 2 |
| while t <= 9 |
| Xloop 1 " X: 511 |
| try |
| if t == 1 |
| let v{ERR(t) + CONT(t)} = 0 |
| elseif t == 2 |
| let v{ERR(t) + CONT(t)} |
| elseif t == 3 |
| let var = exists('v{ERR(t) + CONT(t)}') |
| elseif t == 4 |
| unlet v{ERR(t) + CONT(t)} |
| elseif t == 5 |
| function F{ERR(t) + CONT(t)}() |
| endfunction |
| elseif t == 6 |
| function F{ERR(t) + CONT(t)} |
| elseif t == 7 |
| let var = exists('*F{ERR(t) + CONT(t)}') |
| elseif t == 8 |
| delfunction F{ERR(t) + CONT(t)} |
| elseif t == 9 |
| let var = ERR(t) + CONT(t) |
| endif |
| catch /asdf/ |
| " v:errmsg is not set when the error message is converted to an |
| " exception. Set it to the original error message. |
| let v:errmsg = substitute(v:exception, '^Vim:', '', "") |
| catch /^Vim\((\a\+)\)\=:/ |
| " An error exception has been thrown after the original error. |
| let v:errmsg = "" |
| finally |
| call MSG(t) |
| let t = t + 1 |
| XloopNEXT |
| continue " discard an aborting error |
| endtry |
| endwhile |
| catch /.*/ |
| Xpath 512 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| |
| try |
| let t = 10 |
| XloopINIT 1024 2 |
| while t <= 18 |
| Xloop 1 " X: 1024 * 511 |
| try |
| if t == 10 |
| let v{INT(t) + CONT(t)} = 0 |
| elseif t == 11 |
| let v{INT(t) + CONT(t)} |
| elseif t == 12 |
| let var = exists('v{INT(t) + CONT(t)}') |
| elseif t == 13 |
| unlet v{INT(t) + CONT(t)} |
| elseif t == 14 |
| function F{INT(t) + CONT(t)}() |
| endfunction |
| elseif t == 15 |
| function F{INT(t) + CONT(t)} |
| elseif t == 16 |
| let var = exists('*F{INT(t) + CONT(t)}') |
| elseif t == 17 |
| delfunction F{INT(t) + CONT(t)} |
| elseif t == 18 |
| let var = INT(t) + CONT(t) |
| endif |
| catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/ |
| " An error exception has been triggered after the interrupt. |
| let v:errmsg = substitute(v:exception, |
| \ '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| call MSG(t) |
| let t = t + 1 |
| XloopNEXT |
| continue " discard interrupt |
| endtry |
| endwhile |
| catch /.*/ |
| Xpath 524288 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| |
| try |
| let t = 19 |
| XloopINIT 1048576 2 |
| while t <= 27 |
| Xloop 1 " X: 1048576 * 511 |
| try |
| if t == 19 |
| let v{THR(t) + CONT(t)} = 0 |
| elseif t == 20 |
| let v{THR(t) + CONT(t)} |
| elseif t == 21 |
| let var = exists('v{THR(t) + CONT(t)}') |
| elseif t == 22 |
| unlet v{THR(t) + CONT(t)} |
| elseif t == 23 |
| function F{THR(t) + CONT(t)}() |
| endfunction |
| elseif t == 24 |
| function F{THR(t) + CONT(t)} |
| elseif t == 25 |
| let var = exists('*F{THR(t) + CONT(t)}') |
| elseif t == 26 |
| delfunction F{THR(t) + CONT(t)} |
| elseif t == 27 |
| let var = THR(t) + CONT(t) |
| endif |
| catch /^Vim\((\a\+)\)\=:/ |
| " An error exception has been triggered after the :throw. |
| let v:errmsg = substitute(v:exception, |
| \ '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| call MSG(t) |
| let t = t + 1 |
| XloopNEXT |
| continue " discard exception |
| endtry |
| endwhile |
| catch /.*/ |
| Xpath 536870912 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| |
| let v{ERR(28) + CONT(28)} = 0 |
| call MSG(28) |
| let v{ERR(29) + CONT(29)} |
| call MSG(29) |
| let var = exists('v{ERR(30) + CONT(30)}') |
| call MSG(30) |
| unlet v{ERR(31) + CONT(31)} |
| call MSG(31) |
| function F{ERR(32) + CONT(32)}() |
| endfunction |
| call MSG(32) |
| function F{ERR(33) + CONT(33)} |
| call MSG(33) |
| let var = exists('*F{ERR(34) + CONT(34)}') |
| call MSG(34) |
| delfunction F{ERR(35) + CONT(35)} |
| call MSG(35) |
| let var = ERR(36) + CONT(36) |
| call MSG(36) |
| |
| let saved_errmsg = "" |
| |
| let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0 |
| call MSG(37) |
| let v{WRAP(38, ERRabort(38)) + CONT(38)} |
| call MSG(38) |
| let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}') |
| call MSG(39) |
| unlet v{WRAP(40, ERRabort(40)) + CONT(40)} |
| call MSG(40) |
| function F{WRAP(41, ERRabort(41)) + CONT(41)}() |
| endfunction |
| call MSG(41) |
| function F{WRAP(42, ERRabort(42)) + CONT(42)} |
| call MSG(42) |
| let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}') |
| call MSG(43) |
| delfunction F{WRAP(44, ERRabort(44)) + CONT(44)} |
| call MSG(44) |
| let var = ERRabort(45) + CONT(45) |
| call MSG(45) |
| |
| Xpath 1073741824 " X: 1073741824 |
| |
| let expected = "" |
| \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9" |
| \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18" |
| \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27" |
| \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33" |
| \ . "E34C34M34E35C35M35E36C36M36" |
| \ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41" |
| \ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45" |
| |
| if taken != expected |
| " The Xpath command does not accept 2^31 (negative); display explicitly: |
| exec "!echo 2147483648 >>" . g:ExtraVimResult |
| " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| if substitute(taken, |
| \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)', |
| \ '\1E3M3\2E30C30M30\3A39C39M39\4', |
| \ "") == expected |
| Xout "Is ++emsg_skip for var with expr_start non-NULL" |
| \ "in f_exists ok?" |
| endif |
| endif |
| |
| unlet! v var saved_errmsg taken expected |
| call delete(WA_t5) |
| call delete(WA_t14) |
| call delete(WA_t23) |
| unlet! WA_t5 WA_t14 WA_t23 |
| delfunction WA_t5 |
| delfunction WA_t14 |
| delfunction WA_t23 |
| |
| endif |
| |
| Xcheck 1610087935 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1 |
| " |
| " When a function call made during evaluation of an expression in |
| " braces as part of a function name after ":function" is aborted due |
| " to an error inside a :try/:endtry region or due to an interrupt or |
| " a :throw, the expression evaluation is aborted as well, and the |
| " function definition is ignored, skipping all commands to the |
| " ":endfunction". On an error not inside :try/:endtry, the expression |
| " evaluation continues and the function gets defined, and can be |
| " called and deleted. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT 1 4 |
| |
| function! ERR() abort |
| Xloop 1 " X: 1 + 4 + 16 + 64 |
| asdf |
| endfunction " returns -1 |
| |
| function! OK() |
| Xloop 2 " X: 2 * (1 + 4 + 16) |
| let v:errmsg = "" |
| return 0 |
| endfunction |
| |
| let v:errmsg = "" |
| |
| Xpath 4096 " X: 4096 |
| function! F{1 + ERR() + OK()}(arg) |
| " F0 should be defined. |
| if exists("a:arg") && a:arg == "calling" |
| Xpath 8192 " X: 8192 |
| else |
| Xpath 16384 " X: 0 |
| endif |
| endfunction |
| if v:errmsg != "" |
| Xpath 32768 " X: 0 |
| endif |
| XloopNEXT |
| |
| Xpath 65536 " X: 65536 |
| call F{1 + ERR() + OK()}("calling") |
| if v:errmsg != "" |
| Xpath 131072 " X: 0 |
| endif |
| XloopNEXT |
| |
| Xpath 262144 " X: 262144 |
| delfunction F{1 + ERR() + OK()} |
| if v:errmsg != "" |
| Xpath 524288 " X: 0 |
| endif |
| XloopNEXT |
| |
| try |
| while 1 |
| let caught = 0 |
| try |
| Xpath 1048576 " X: 1048576 |
| function! G{1 + ERR() + OK()}(arg) |
| " G0 should not be defined, and the function body should be |
| " skipped. |
| if exists("a:arg") && a:arg == "calling" |
| Xpath 2097152 " X: 0 |
| else |
| Xpath 4194304 " X: 0 |
| endif |
| " Use an unmatched ":finally" to check whether the body is |
| " skipped when an error occurs in ERR(). This works whether or |
| " not the exception is converted to an exception. |
| finally |
| Xpath 8388608 " X: 0 |
| Xout "Body of G{1 + ERR() + OK()}() not skipped" |
| " Discard the aborting error or exception, and break the |
| " while loop. |
| break |
| " End the try conditional and start a new one to avoid |
| " ":catch after :finally" errors. |
| endtry |
| try |
| Xpath 16777216 " X: 0 |
| endfunction |
| |
| " When the function was not defined, this won't be reached - whether |
| " the body was skipped or not. When the function was defined, it |
| " can be called and deleted here. |
| Xpath 33554432 " X: 0 |
| Xout "G0() has been defined" |
| XloopNEXT |
| try |
| call G{1 + ERR() + OK()}("calling") |
| catch /.*/ |
| Xpath 67108864 " X: 0 |
| endtry |
| Xpath 134217728 " X: 0 |
| XloopNEXT |
| try |
| delfunction G{1 + ERR() + OK()} |
| catch /.*/ |
| Xpath 268435456 " X: 0 |
| endtry |
| catch /asdf/ |
| " Jumped to when the function is not defined and the body is |
| " skipped. |
| let caught = 1 |
| catch /.*/ |
| Xpath 536870912 " X: 0 |
| finally |
| if !caught && !$VIMNOERRTHROW |
| Xpath 1073741824 " X: 0 |
| endif |
| break " discard error for $VIMNOERRTHROW |
| endtry " jumped to when the body is not skipped |
| endwhile |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught" |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| Xcheck 1388671 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 78: Messages on parsing errors in expression evaluation {{{1 |
| " |
| " When an expression evaluation detects a parsing error, an error |
| " message is given and converted to an exception, and the expression |
| " evaluation is aborted. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| let taken = "" |
| |
| function! F(n) |
| let g:taken = g:taken . "F" . a:n |
| endfunction |
| |
| function! MSG(n, enr, emsg) |
| let g:taken = g:taken . "M" . a:n |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| if v:errmsg == "" |
| Xout "Expr" a:n.": Message missing." |
| let g:taken = g:taken . "x" |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Expr" a:n.": Unexpected message:" v:errmsg |
| Xout "Expected: " . a:enr . ': ' . a:emsg |
| let g:taken = g:taken . "X" |
| endif |
| endif |
| endfunction |
| |
| function! CONT(n) |
| let g:taken = g:taken . "C" . a:n |
| endfunction |
| |
| let v:errmsg = "" |
| XloopINIT 1 2 |
| |
| try |
| let t = 1 |
| while t <= 14 |
| let g:taken = g:taken . "T" . t |
| let v:errmsg = "" |
| try |
| let caught = 0 |
| if t == 1 |
| let v{novar + CONT(t)} = 0 |
| elseif t == 2 |
| let v{novar + CONT(t)} |
| elseif t == 3 |
| let var = exists('v{novar + CONT(t)}') |
| elseif t == 4 |
| unlet v{novar + CONT(t)} |
| elseif t == 5 |
| function F{novar + CONT(t)}() |
| endfunction |
| elseif t == 6 |
| function F{novar + CONT(t)} |
| elseif t == 7 |
| let var = exists('*F{novar + CONT(t)}') |
| elseif t == 8 |
| delfunction F{novar + CONT(t)} |
| elseif t == 9 |
| echo novar + CONT(t) |
| elseif t == 10 |
| echo v{novar + CONT(t)} |
| elseif t == 11 |
| echo F{novar + CONT(t)} |
| elseif t == 12 |
| let var = novar + CONT(t) |
| elseif t == 13 |
| let var = v{novar + CONT(t)} |
| elseif t == 14 |
| let var = F{novar + CONT(t)}() |
| endif |
| catch /^Vim\((\a\+)\)\=:/ |
| " v:errmsg is not set when the error message is converted to an |
| " exception. Set it to the original error message. |
| let v:errmsg = substitute(v:exception, |
| \ '^Vim\((\a\+)\)\=:', '', "") |
| let caught = 1 |
| finally |
| if t <= 8 && t != 3 && t != 7 |
| call MSG(t, 'E475', 'Invalid argument\>') |
| else |
| if !caught " no error exceptions ($VIMNOERRTHROW set) |
| call MSG(t, 'E15', "Invalid expression") |
| else |
| call MSG(t, 'E121', "Undefined variable") |
| endif |
| endif |
| let t = t + 1 |
| XloopNEXT |
| continue " discard an aborting error |
| endtry |
| endwhile |
| catch /.*/ |
| Xloop 1 " X: 0 |
| Xout t.":" v:exception "in" ExtraVimThrowpoint() |
| endtry |
| |
| function! T(n, expr, enr, emsg) |
| try |
| let g:taken = g:taken . "T" . a:n |
| let v:errmsg = "" |
| try |
| let caught = 0 |
| execute "let var = " . a:expr |
| catch /^Vim\((\a\+)\)\=:/ |
| " v:errmsg is not set when the error message is converted to an |
| " exception. Set it to the original error message. |
| let v:errmsg = substitute(v:exception, |
| \ '^Vim\((\a\+)\)\=:', '', "") |
| let caught = 1 |
| finally |
| if !caught " no error exceptions ($VIMNOERRTHROW set) |
| call MSG(a:n, 'E15', "Invalid expression") |
| else |
| call MSG(a:n, a:enr, a:emsg) |
| endif |
| XloopNEXT |
| " Discard an aborting error: |
| return |
| endtry |
| catch /.*/ |
| Xloop 1 " X: 0 |
| Xout a:n.":" v:exception "in" ExtraVimThrowpoint() |
| endtry |
| endfunction |
| |
| call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function") |
| call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments") |
| call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments") |
| call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments") |
| call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") |
| call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") |
| call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") |
| call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression") |
| call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") |
| call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") |
| call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") |
| call T(26, '& + CONT(26)', 'E112', "Option name missing") |
| call T(27, '&asdf + CONT(27)', 'E113', "Unknown option") |
| |
| Xpath 134217728 " X: 134217728 |
| |
| let expected = "" |
| \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14" |
| \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25" |
| \ . "T26M26T27M27" |
| |
| if taken != expected |
| Xpath 268435456 " X: 0 |
| Xout "'taken' is" taken "instead of" expected |
| if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected |
| Xout "Is ++emsg_skip for var with expr_start non-NULL" |
| \ "in f_exists ok?" |
| endif |
| endif |
| |
| unlet! var caught taken expected |
| call delete(WA_t5) |
| unlet! WA_t5 |
| delfunction WA_t5 |
| |
| endif |
| |
| Xcheck 134217728 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 79: Throwing one of several errors for the same command {{{1 |
| " |
| " When several errors appear in a row (for instance during expression |
| " evaluation), the first as the most specific one is used when |
| " throwing an error exception. If, however, a syntax error is |
| " detected afterwards, this one is used for the error exception. |
| " On a syntax error, the next command is not executed, on a normal |
| " error, however, it is (relevant only in a function without the |
| " "abort" flag). v:errmsg is not set. |
| " |
| " If throwing error exceptions is configured off, v:errmsg is always |
| " set to the latest error message, that is, to the more general |
| " message or the syntax error, respectively. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| XloopINIT 1 2 |
| |
| function! NEXT(cmd) |
| exec a:cmd . " | Xloop 1" |
| endfunction |
| |
| call NEXT('echo novar') " X: 1 * 1 (checks nextcmd) |
| XloopNEXT |
| call NEXT('let novar #') " X: 0 * 2 (skips nextcmd) |
| XloopNEXT |
| call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd) |
| XloopNEXT |
| call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd) |
| XloopNEXT |
| call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd) |
| |
| function! EXEC(cmd) |
| exec a:cmd |
| endfunction |
| |
| function! MATCH(expected, msg, enr, emsg) |
| let msg = a:msg |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let msg = ":" . msg |
| endif |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg) |
| let match = 0 |
| if a:expected " no match although expected |
| if a:msg == "" |
| Xout "Message missing." |
| else |
| let msg = escape(msg, '"') |
| Xout "Unexpected message:" msg |
| Xout "Expected:" a:enr . ": " . a:emsg |
| endif |
| endif |
| else |
| let match = 1 |
| if !a:expected " match although not expected |
| let msg = escape(msg, '"') |
| Xout "Unexpected message:" msg |
| Xout "Expected none." |
| endif |
| endif |
| return match |
| endfunction |
| |
| try |
| |
| while 1 " dummy loop |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| let thrmsg = "" |
| call EXEC('echo novar') " normal error |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xpath 32 " X: 32 |
| if !caught |
| if !$VIMNOERRTHROW |
| Xpath 64 " X: 0 |
| endif |
| elseif !MATCH(1, thrmsg, 'E121', "Undefined variable") |
| \ || v:errmsg != "" |
| Xpath 128 " X: 0 |
| endif |
| if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression") |
| Xpath 256 " X: 0 |
| endif |
| break " discard error if $VIMNOERRTHROW == 1 |
| endtry |
| endwhile |
| |
| Xpath 512 " X: 512 |
| let cmd = "let" |
| XloopINIT 1024 32 |
| while cmd != "" |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| let thrmsg = "" |
| call EXEC(cmd . ' novar #') " normal plus syntax error |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xloop 1 " X: 1024 * (1 + 32) |
| if !caught |
| if !$VIMNOERRTHROW |
| Xloop 2 " X: 0 |
| endif |
| else |
| if cmd == "let" |
| let match = MATCH(0, thrmsg, 'E106', "Unknown variable") |
| elseif cmd == "unlet" |
| let match = MATCH(0, thrmsg, 'E108', "No such variable") |
| endif |
| if match " normal error |
| Xloop 4 " X: 0 |
| endif |
| if !MATCH(1, thrmsg, 'E488', "Trailing characters") |
| \|| v:errmsg != "" |
| " syntax error |
| Xloop 8 " X: 0 |
| endif |
| endif |
| if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters") |
| " last error |
| Xloop 16 " X: 0 |
| endif |
| if cmd == "let" |
| let cmd = "unlet" |
| else |
| let cmd = "" |
| endif |
| XloopNEXT |
| continue " discard error if $VIMNOERRTHROW == 1 |
| endtry |
| endwhile |
| |
| Xpath 1048576 " X: 1048576 |
| let cmd = "let" |
| XloopINIT 2097152 32 |
| while cmd != "" |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| let thrmsg = "" |
| call EXEC(cmd . ' {novar}') " normal plus syntax error |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xloop 1 " X: 2097152 * (1 + 32) |
| if !caught |
| if !$VIMNOERRTHROW |
| Xloop 2 " X: 0 |
| endif |
| else |
| if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error |
| Xloop 4 " X: 0 |
| endif |
| if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>') |
| \ || v:errmsg != "" " syntax error |
| Xloop 8 " X: 0 |
| endif |
| endif |
| if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>') |
| " last error |
| Xloop 16 " X: 0 |
| endif |
| if cmd == "let" |
| let cmd = "unlet" |
| else |
| let cmd = "" |
| endif |
| XloopNEXT |
| continue " discard error if $VIMNOERRTHROW == 1 |
| endtry |
| endwhile |
| |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); add explicitly: |
| let Xpath = Xpath + 2147483648 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| endtry |
| |
| unlet! next_command thrmsg match |
| delfunction NEXT |
| delfunction EXEC |
| delfunction MATCH |
| |
| Xcheck 70288929 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 80: Syntax error in expression for illegal :elseif {{{1 |
| " |
| " If there is a syntax error in the expression after an illegal |
| " :elseif, an error message is given (or an error exception thrown) |
| " for the illegal :elseif rather than the expression error. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| let v:errmsg = "" |
| if 0 |
| else |
| elseif 1 ||| 2 |
| endif |
| Xpath 1 " X: 1 |
| if !MSG('E584', ":elseif after :else") |
| Xpath 2 " X: 0 |
| endif |
| |
| let v:errmsg = "" |
| if 1 |
| else |
| elseif 1 ||| 2 |
| endif |
| Xpath 4 " X: 4 |
| if !MSG('E584', ":elseif after :else") |
| Xpath 8 " X: 0 |
| endif |
| |
| let v:errmsg = "" |
| elseif 1 ||| 2 |
| Xpath 16 " X: 16 |
| if !MSG('E582', ":elseif without :if") |
| Xpath 32 " X: 0 |
| endif |
| |
| let v:errmsg = "" |
| while 1 |
| elseif 1 ||| 2 |
| endwhile |
| Xpath 64 " X: 64 |
| if !MSG('E582', ":elseif without :if") |
| Xpath 128 " X: 0 |
| endif |
| |
| while 1 |
| try |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| if 0 |
| else |
| elseif 1 ||| 2 |
| endif |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xpath 256 " X: 256 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 512 " X: 0 |
| endif |
| if !MSG('E584', ":elseif after :else") |
| Xpath 1024 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 2048 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| if 1 |
| else |
| elseif 1 ||| 2 |
| endif |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xpath 4096 " X: 4096 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 8192 " X: 0 |
| endif |
| if !MSG('E584', ":elseif after :else") |
| Xpath 16384 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| elseif 1 ||| 2 |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xpath 65536 " X: 65536 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 131072 " X: 0 |
| endif |
| if !MSG('E582', ":elseif without :if") |
| Xpath 262144 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 524288 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let v:errmsg = "" |
| let caught = 0 |
| while 1 |
| elseif 1 ||| 2 |
| endwhile |
| catch /^Vim\((\a\+)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") |
| finally |
| Xpath 1048576 " X: 1048576 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2097152 " X: 0 |
| endif |
| if !MSG('E582', ":elseif without :if") |
| Xpath 4194304 " X: 0 |
| endif |
| endtry |
| catch /.*/ |
| Xpath 8388608 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| Xpath 16777216 " X: 16777216 |
| |
| unlet! caught |
| delfunction MSG |
| |
| Xcheck 17895765 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 81: Discarding exceptions after an error or interrupt {{{1 |
| " |
| " When an exception is thrown from inside a :try conditional without |
| " :catch and :finally clauses and an error or interrupt occurs before |
| " the :endtry is reached, the exception is discarded. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| try |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| throw "arrgh" |
| Xpath 4 " X: 0 |
| " if 1 |
| Xpath 8 " X: 0 |
| " error after :throw: missing :endif |
| endtry |
| Xpath 16 " X: 0 |
| catch /arrgh/ |
| Xpath 32 " X: 0 |
| endtry |
| Xpath 64 " X: 0 |
| endif |
| |
| if ExtraVim() |
| try |
| Xpath 128 " X: 128 |
| try |
| Xpath 256 " X: 256 |
| throw "arrgh" |
| Xpath 512 " X: 0 |
| endtry " INTERRUPT |
| Xpath 1024 " X: 0 |
| catch /arrgh/ |
| Xpath 2048 " X: 0 |
| endtry |
| Xpath 4096 " X: 0 |
| endif |
| |
| Xcheck 387 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 82: Ignoring :catch clauses after an error or interrupt {{{1 |
| " |
| " When an exception is thrown and an error or interrupt occurs before |
| " the matching :catch clause is reached, the exception is discarded |
| " and the :catch clause is ignored (also for the error or interrupt |
| " exception being thrown then). |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| try |
| try |
| Xpath 1 " X: 1 |
| throw "arrgh" |
| Xpath 2 " X: 0 |
| " if 1 |
| Xpath 4 " X: 0 |
| " error after :throw: missing :endif |
| catch /.*/ |
| Xpath 8 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| catch /.*/ |
| Xpath 16 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| Xpath 32 " X: 0 |
| catch /arrgh/ |
| Xpath 64 " X: 0 |
| endtry |
| Xpath 128 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function! E() |
| try |
| try |
| Xpath 256 " X: 256 |
| throw "arrgh" |
| Xpath 512 " X: 0 |
| " if 1 |
| Xpath 1024 " X: 0 |
| " error after :throw: missing :endif |
| catch /.*/ |
| Xpath 2048 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| catch /.*/ |
| Xpath 4096 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| Xpath 8192 " X: 0 |
| catch /arrgh/ |
| Xpath 16384 " X: 0 |
| endtry |
| endfunction |
| |
| call E() |
| Xpath 32768 " X: 0 |
| endif |
| |
| if ExtraVim() |
| try |
| try |
| Xpath 65536 " X: 65536 |
| throw "arrgh" |
| Xpath 131072 " X: 0 |
| catch /.*/ "INTERRUPT |
| Xpath 262144 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| catch /.*/ |
| Xpath 524288 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| Xpath 1048576 " X: 0 |
| catch /arrgh/ |
| Xpath 2097152 " X: 0 |
| endtry |
| Xpath 4194304 " X: 0 |
| endif |
| |
| if ExtraVim() |
| function I() |
| try |
| try |
| Xpath 8388608 " X: 8388608 |
| throw "arrgh" |
| Xpath 16777216 " X: 0 |
| catch /.*/ "INTERRUPT |
| Xpath 33554432 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| catch /.*/ |
| Xpath 67108864 " X: 0 |
| Xout v:exception "in" ExtraVimThrowpoint() |
| endtry |
| Xpath 134217728 " X: 0 |
| catch /arrgh/ |
| Xpath 268435456 " X: 0 |
| endtry |
| endfunction |
| |
| call I() |
| Xpath 536870912 " X: 0 |
| endif |
| |
| Xcheck 8454401 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 83: Executing :finally clauses after an error or interrupt {{{1 |
| " |
| " When an exception is thrown and an error or interrupt occurs before |
| " the :finally of the innermost :try is reached, the exception is |
| " discarded and the :finally clause is executed. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| try |
| Xpath 1 " X: 1 |
| try |
| Xpath 2 " X: 2 |
| throw "arrgh" |
| Xpath 4 " X: 0 |
| " if 1 |
| Xpath 8 " X: 0 |
| " error after :throw: missing :endif |
| finally |
| Xpath 16 " X: 16 |
| endtry |
| Xpath 32 " X: 0 |
| catch /arrgh/ |
| Xpath 64 " X: 0 |
| endtry |
| Xpath 128 " X: 0 |
| endif |
| |
| if ExtraVim() |
| try |
| Xpath 256 " X: 256 |
| try |
| Xpath 512 " X: 512 |
| throw "arrgh" |
| Xpath 1024 " X: 0 |
| finally "INTERRUPT |
| Xpath 2048 " X: 2048 |
| endtry |
| Xpath 4096 " X: 0 |
| catch /arrgh/ |
| Xpath 8192 " X: 0 |
| endtry |
| Xpath 16384 " X: 0 |
| endif |
| |
| Xcheck 2835 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 84: Exceptions in autocommand sequences. {{{1 |
| " |
| " When an exception occurs in a sequence of autocommands for |
| " a specific event, the rest of the sequence is not executed. The |
| " command that triggered the autocommand execution aborts, and the |
| " exception is propagated to the caller. |
| " |
| " For the FuncUndefined event under a function call expression or |
| " :call command, the function is not executed, even when it has |
| " been defined by the autocommands before the exception occurred. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| function! INT() |
| "INTERRUPT |
| let dummy = 0 |
| endfunction |
| |
| aug TMP |
| autocmd! |
| |
| autocmd User x1 Xpath 1 " X: 1 |
| autocmd User x1 throw "x1" |
| autocmd User x1 Xpath 2 " X: 0 |
| |
| autocmd User x2 Xpath 4 " X: 4 |
| autocmd User x2 asdf |
| autocmd User x2 Xpath 8 " X: 0 |
| |
| autocmd User x3 Xpath 16 " X: 16 |
| autocmd User x3 call INT() |
| autocmd User x3 Xpath 32 " X: 0 |
| |
| autocmd FuncUndefined U1 function! U1() |
| autocmd FuncUndefined U1 Xpath 64 " X: 0 |
| autocmd FuncUndefined U1 endfunction |
| autocmd FuncUndefined U1 Xpath 128 " X: 128 |
| autocmd FuncUndefined U1 throw "U1" |
| autocmd FuncUndefined U1 Xpath 256 " X: 0 |
| |
| autocmd FuncUndefined U2 function! U2() |
| autocmd FuncUndefined U2 Xpath 512 " X: 0 |
| autocmd FuncUndefined U2 endfunction |
| autocmd FuncUndefined U2 Xpath 1024 " X: 1024 |
| autocmd FuncUndefined U2 ASDF |
| autocmd FuncUndefined U2 Xpath 2048 " X: 0 |
| |
| autocmd FuncUndefined U3 function! U3() |
| autocmd FuncUndefined U3 Xpath 4096 " X: 0 |
| autocmd FuncUndefined U3 endfunction |
| autocmd FuncUndefined U3 Xpath 8192 " X: 8192 |
| autocmd FuncUndefined U3 call INT() |
| autocmd FuncUndefined U3 Xpath 16384 " X: 0 |
| aug END |
| |
| try |
| try |
| Xpath 32768 " X: 32768 |
| doautocmd User x1 |
| catch /x1/ |
| Xpath 65536 " X: 65536 |
| endtry |
| |
| while 1 |
| try |
| Xpath 131072 " X: 131072 |
| let caught = 0 |
| doautocmd User x2 |
| catch /asdf/ |
| let caught = 1 |
| finally |
| Xpath 262144 " X: 262144 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 524288 " X: 0 |
| " Propagate uncaught error exception, |
| else |
| " ... but break loop for caught error exception, |
| " or discard error and break loop if $VIMNOERRTHROW |
| break |
| endif |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 1048576 " X: 1048576 |
| let caught = 0 |
| doautocmd User x3 |
| catch /Vim:Interrupt/ |
| let caught = 1 |
| finally |
| Xpath 2097152 " X: 2097152 |
| if !caught && !$VIMNOINTTHROW |
| Xpath 4194304 " X: 0 |
| " Propagate uncaught interrupt exception, |
| else |
| " ... but break loop for caught interrupt exception, |
| " or discard interrupt and break loop if $VIMNOINTTHROW |
| break |
| endif |
| endtry |
| endwhile |
| |
| if exists("*U1") | delfunction U1 | endif |
| if exists("*U2") | delfunction U2 | endif |
| if exists("*U3") | delfunction U3 | endif |
| |
| try |
| Xpath 8388608 " X: 8388608 |
| call U1() |
| catch /U1/ |
| Xpath 16777216 " X: 16777216 |
| endtry |
| |
| while 1 |
| try |
| Xpath 33554432 " X: 33554432 |
| let caught = 0 |
| call U2() |
| catch /ASDF/ |
| let caught = 1 |
| finally |
| Xpath 67108864 " X: 67108864 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 134217728 " X: 0 |
| " Propagate uncaught error exception, |
| else |
| " ... but break loop for caught error exception, |
| " or discard error and break loop if $VIMNOERRTHROW |
| break |
| endif |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| Xpath 268435456 " X: 268435456 |
| let caught = 0 |
| call U3() |
| catch /Vim:Interrupt/ |
| let caught = 1 |
| finally |
| Xpath 536870912 " X: 536870912 |
| if !caught && !$VIMNOINTTHROW |
| Xpath 1073741824 " X: 0 |
| " Propagate uncaught interrupt exception, |
| else |
| " ... but break loop for caught interrupt exception, |
| " or discard interrupt and break loop if $VIMNOINTTHROW |
| break |
| endif |
| endtry |
| endwhile |
| catch /.*/ |
| " The Xpath command does not accept 2^31 (negative); display explicitly: |
| exec "!echo 2147483648 >>" . g:ExtraVimResult |
| Xout "Caught" v:exception "in" v:throwpoint |
| endtry |
| |
| unlet caught |
| delfunction INT |
| delfunction U1 |
| delfunction U2 |
| delfunction U3 |
| au! TMP |
| aug! TMP |
| endif |
| |
| Xcheck 934782101 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 85: Error exceptions in autocommands for I/O command events {{{1 |
| " |
| " When an I/O command is inside :try/:endtry, autocommands to be |
| " executed after it should be skipped on an error (exception) in the |
| " command itself or in autocommands to be executed before the command. |
| " In the latter case, the I/O command should not be executed either. |
| " Example 1: BufWritePre, :write, BufWritePost |
| " Example 2: FileReadPre, :read, FileReadPost. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| function! MSG(enr, emsg) |
| let english = v:lang == "C" || v:lang =~ '^[Ee]n' |
| if a:enr == "" |
| Xout "TODO: Add message number for:" a:emsg |
| let v:errmsg = ":" . v:errmsg |
| endif |
| let match = 1 |
| if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) |
| let match = 0 |
| if v:errmsg == "" |
| Xout "Message missing." |
| else |
| let v:errmsg = escape(v:errmsg, '"') |
| Xout "Unexpected message:" v:errmsg |
| endif |
| endif |
| return match |
| endfunction |
| |
| " Remove the autocommands for the events specified as arguments in all used |
| " autogroups. |
| function! Delete_autocommands(...) |
| let augfile = tempname() |
| while 1 |
| try |
| exec "redir >" . augfile |
| aug |
| redir END |
| exec "edit" augfile |
| g/^$/d |
| norm G$ |
| let wrap = "w" |
| while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0 |
| let wrap = "W" |
| exec "norm y/ \n" |
| let argno = 1 |
| while argno <= a:0 |
| exec "au!" escape(@", " ") a:{argno} |
| let argno = argno + 1 |
| endwhile |
| endwhile |
| catch /.*/ |
| finally |
| bwipeout! |
| call delete(augfile) |
| break " discard errors for $VIMNOERRTHROW |
| endtry |
| endwhile |
| endfunction |
| |
| call Delete_autocommands("BufWritePre", "BufWritePost") |
| |
| while 1 |
| try |
| try |
| let post = 0 |
| aug TMP |
| au! BufWritePost * let post = 1 |
| aug END |
| let caught = 0 |
| write /n/o/n/e/x/i/s/t/e/n/t |
| catch /^Vim(write):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(write):', '', "") |
| finally |
| Xpath 1 " X: 1 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 2 " X: 0 |
| endif |
| let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ', |
| \ '', "") |
| if !MSG('E212', "Can't open file for writing") |
| Xpath 4 " X: 0 |
| endif |
| if post |
| Xpath 8 " X: 0 |
| Xout "BufWritePost commands executed after write error" |
| endif |
| au! TMP |
| aug! TMP |
| endtry |
| catch /.*/ |
| Xpath 16 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| try |
| let post = 0 |
| aug TMP |
| au! BufWritePre * asdf |
| au! BufWritePost * let post = 1 |
| aug END |
| let tmpfile = tempname() |
| let caught = 0 |
| exec "write" tmpfile |
| catch /^Vim\((write)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "") |
| finally |
| Xpath 32 " X: 32 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 64 " X: 0 |
| endif |
| let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "") |
| if !MSG('E492', "Not an editor command") |
| Xpath 128 " X: 0 |
| endif |
| if filereadable(tmpfile) |
| Xpath 256 " X: 0 |
| Xout ":write command not suppressed after BufWritePre error" |
| endif |
| if post |
| Xpath 512 " X: 0 |
| Xout "BufWritePost commands executed after BufWritePre error" |
| endif |
| au! TMP |
| aug! TMP |
| endtry |
| catch /.*/ |
| Xpath 1024 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| call delete(tmpfile) |
| |
| call Delete_autocommands("BufWritePre", "BufWritePost", |
| \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost") |
| |
| while 1 |
| try |
| try |
| let post = 0 |
| aug TMP |
| au! FileReadPost * let post = 1 |
| aug END |
| let caught = 0 |
| read /n/o/n/e/x/i/s/t/e/n/t |
| catch /^Vim(read):/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim(read):', '', "") |
| finally |
| Xpath 2048 " X: 2048 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 4096 " X: 0 |
| endif |
| let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$', |
| \ '', "") |
| if !MSG('E484', "Can't open file") |
| Xpath 8192 " X: 0 |
| endif |
| if post |
| Xpath 16384 " X: 0 |
| Xout "FileReadPost commands executed after write error" |
| endif |
| au! TMP |
| aug! TMP |
| endtry |
| catch /.*/ |
| Xpath 32768 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| while 1 |
| try |
| let infile = tempname() |
| let tmpfile = tempname() |
| exec "!echo XYZ >" . infile |
| exec "edit" tmpfile |
| try |
| Xpath 65536 " X: 65536 |
| try |
| let post = 0 |
| aug TMP |
| au! FileReadPre * asdf |
| au! FileReadPost * let post = 1 |
| aug END |
| let caught = 0 |
| exec "0read" infile |
| catch /^Vim\((read)\)\=:/ |
| let caught = 1 |
| let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '', |
| \ "") |
| finally |
| Xpath 131072 " X: 131072 |
| if !caught && !$VIMNOERRTHROW |
| Xpath 262144 " X: 0 |
| endif |
| let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "") |
| if !MSG('E492', "Not an editor command") |
| Xpath 524288 " X: 0 |
| endif |
| if getline("1") == "XYZ" |
| Xpath 1048576 " X: 0 |
| Xout ":read command not suppressed after FileReadPre error" |
| endif |
| if post |
| Xpath 2097152 " X: 0 |
| Xout "FileReadPost commands executed after " . |
| \ "FileReadPre error" |
| endif |
| au! TMP |
| aug! TMP |
| endtry |
| finally |
| bwipeout! |
| endtry |
| catch /.*/ |
| Xpath 4194304 " X: 0 |
| Xout v:exception "in" v:throwpoint |
| finally |
| break " discard error for $VIMNOERRTHROW |
| endtry |
| endwhile |
| |
| call delete(infile) |
| call delete(tmpfile) |
| unlet! caught post infile tmpfile |
| delfunction MSG |
| delfunction Delete_autocommands |
| |
| Xcheck 198689 |
| |
| |
| "------------------------------------------------------------------------------- |
| " Test 86: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1 |
| " |
| " It is possible to configure Vim for throwing exceptions on error |
| " or interrupt, controlled by variables $VIMNOERRTHROW and |
| " $VIMNOINTTHROW. This is just for increasing the number of tests. |
| " All tests here should run for all four combinations of setting |
| " these variables to 0 or 1. The variables are intended for the |
| " development phase only. In the final release, Vim should be |
| " configured to always use error and interrupt exceptions. |
| " |
| " The test result is "OK", |
| " |
| " - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not |
| " configured and exceptions are thrown on error and on |
| " interrupt. |
| " |
| " - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is |
| " configured and works as intended. |
| " |
| " What actually happens, is shown in the test output. |
| " |
| " Otherwise, the test result is "FAIL", and the test output describes |
| " the problem. |
| " |
| " IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and |
| " $VIMNOINTTHROW. |
| "------------------------------------------------------------------------------- |
| |
| XpathINIT |
| |
| if ExtraVim() |
| |
| function! ThrowOnError() |
| XloopNEXT |
| let caught = 0 |
| try |
| Xloop 1 " X: 1 + 8 + 64 |
| asdf |
| catch /.*/ |
| let caught = 1 " error exception caught |
| finally |
| Xloop 2 " X: 2 + 16 + 128 |
| return caught " discard aborting error |
| endtry |
| Xloop 4 " X: 0 |
| endfunction |
| |
| let quits_skipped = 0 |
| |
| function! ThrowOnInterrupt() |
| XloopNEXT |
| let caught = 0 |
| try |
| Xloop 1 " X: (1 + 8 + 64) * 512 |
| "INTERRUPT3 |
| let dummy = 0 |
| let g:quits_skipped = g:quits_skipped + 1 |
| catch /.*/ |
| let caught = 1 " interrupt exception caught |
| finally |
| Xloop 2 " X: (2 + 16 + 128) * 512 |
| return caught " discard interrupt |
| endtry |
| Xloop 4 " X: 0 |
| endfunction |
| |
| function! CheckThrow(Type) |
| execute 'return ThrowOn' . a:Type . '()' |
| endfunction |
| |
| function! CheckConfiguration(type) " type is "error" or "interrupt" |
| |
| let type = a:type |
| let Type = substitute(type, '.*', '\u&', "") |
| let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW' |
| |
| if type == "error" |
| XloopINIT! 1 8 |
| elseif type == "interrupt" |
| XloopINIT! 512 8 |
| endif |
| |
| exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0' |
| exec 'let suppressed_for_tests = ' . VAR . ' != 0' |
| let used_in_tests = CheckThrow(Type) |
| |
| exec 'let ' . VAR . ' = 0' |
| let request_works = CheckThrow(Type) |
| |
| exec 'let ' . VAR . ' = 1' |
| let suppress_works = !CheckThrow(Type) |
| |
| if type == "error" |
| XloopINIT! 262144 8 |
| elseif type == "interrupt" |
| XloopINIT! 2097152 8 |
| |
| if g:quits_skipped != 0 |
| Xloop 1 " X: 0*2097152 |
| Xout "Test environment error. Interrupt breakpoints skipped: " |
| \ . g:quits_skipped . ".\n" |
| \ . "Cannot check whether interrupt exceptions are thrown." |
| return |
| endif |
| endif |
| |
| let failure = |
| \ !suppressed_for_tests && !used_in_tests |
| \ || !request_works |
| |
| let contradiction = |
| \ used_in_tests |
| \ ? suppressed_for_tests && !request_works |
| \ : !suppressed_for_tests |
| |
| if failure |
| " Failure in configuration. |
| Xloop 2 " X: 0 * 2* (262144 + 2097152) |
| elseif contradiction |
| " Failure in test logic. Should not happen. |
| Xloop 4 " X: 0 * 4 * (262144 + 2097152) |
| endif |
| |
| let var_control_configured = |
| \ request_works != used_in_tests |
| \ || suppress_works == used_in_tests |
| |
| let var_control_not_configured = |
| \ requested_for_tests || suppressed_for_tests |
| \ ? request_works && !suppress_works |
| \ : request_works == used_in_tests |
| \ && suppress_works != used_in_tests |
| |
| let with = used_in_tests ? "with" : "without" |
| |
| let set = suppressed_for_tests ? "non-zero" : |
| \ requested_for_tests ? "0" : "unset" |
| |
| let although = contradiction && !var_control_not_configured |
| \ ? ",\nalthough " |
| \ : ".\n" |
| |
| let output = "All tests were run " . with . " throwing exceptions on " |
| \ . type . although |
| |
| if !var_control_not_configured |
| let output = output . VAR . " was " . set . "." |
| |
| if !request_works && !requested_for_tests |
| let output = output . |
| \ "\n" . Type . " exceptions are not thrown when " . VAR . |
| \ " is\nset to 0." |
| endif |
| |
| if !suppress_works && (!used_in_tests || |
| \ !request_works && |
| \ !requested_for_tests && !suppressed_for_tests) |
| let output = output . |
| \ "\n" . Type . " exceptions are thrown when " . VAR . |
| \ " is set to 1." |
| endif |
| |
| if !failure && var_control_configured |
| let output = output . |
| \ "\nRun tests also with " . substitute(VAR, '^\$', '', "") |
| \ . "=" . used_in_tests . "." |
| \ . "\nThis is for testing in the development phase only." |
| \ . " Remove the \n" |
| \ . VAR . " control in the final release." |
| endif |
| else |
| let output = output . |
| \ "The " . VAR . " control is not configured." |
| endif |
| |
| Xout output |
| endfunction |
| |
| call CheckConfiguration("error") |
| Xpath 16777216 " X: 16777216 |
| call CheckConfiguration("interrupt") |
| Xpath 33554432 " X: 33554432 |
| endif |
| |
| Xcheck 50443995 |
| |
| " IMPORTANT: No test should be added after this test because it changes |
| " $VIMNOERRTHROW and $VIMNOINTTHROW. |
| |
| |
| "------------------------------------------------------------------------------- |
| " Modelines {{{1 |
| " vim: ts=8 sw=4 tw=80 fdm=marker |
| " vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") |
| "------------------------------------------------------------------------------- |