neovim/test/old/testdir/test_trycatch.vim

2390 lines
52 KiB
VimL
Raw Normal View History

" Test try-catch-finally exception handling
" Most of this was formerly in test49.
source check.vim
source shared.vim
source vim9.vim
"-------------------------------------------------------------------------------
" Test environment {{{1
"-------------------------------------------------------------------------------
com! XpathINIT let g:Xpath = ''
com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args>
" 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.
"-------------------------------------------------------------------------------
func T25_F()
let loops = 3
while loops > 0
Xpath 'a' . loops
if loops >= 2
try
Xpath 'b' . loops
if loops == 2
try
Xpath 'c' . loops
finally
Xpath 'd' . loops
endtry
endif
finally
Xpath 'e' . loops
if loops == 2
try
Xpath 'f' . loops
final
Xpath 'g' . loops
endtry
endif
endtry
endif
Xpath 'h' . loops
let loops = loops - 1
endwhile
Xpath 'i'
endfunc
" Also try using "fina" and "final" and "finall" as abbraviations.
func T25_G()
if 1
try
Xpath 'A'
call T25_F()
Xpath 'B'
fina
Xpath 'C'
endtry
else
try
Xpath 'D'
finall
Xpath 'E'
endtry
endif
endfunc
func Test_finally()
XpathINIT
call T25_G()
call assert_equal('Aa3b3e3h3a2b2c2d2e2f2g2h2a1h1iBC', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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).
"-------------------------------------------------------------------------------
func T26_F()
try
let loops = 3
while loops > 0
try
try
if loops == 2
Xpath 'a' . loops
let loops = loops - 1
continue
elseif loops == 1
Xpath 'b' . loops
break
finish
endif
Xpath 'c' . loops
endtry
finally
Xpath 'd' . loops
endtry
Xpath 'e' . loops
let loops = loops - 1
endwhile
Xpath 'f'
finally
Xpath 'g'
let loops = 3
while loops > 0
try
finally
try
if loops == 2
Xpath 'h' . loops
let loops = loops - 1
continue
elseif loops == 1
Xpath 'i' . loops
break
finish
endif
endtry
Xpath 'j' . loops
endtry
Xpath 'k' . loops
let loops = loops - 1
endwhile
Xpath 'l'
endtry
Xpath 'm'
endfunc
func Test_finally_after_continue()
XpathINIT
call T26_F()
call assert_equal('c3d3e3a2d1b1d1fgj3k3h2i1lm', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T32_F()
try
Xpath 'a'
try
Xpath 'b'
return "ABCD"
Xpath 'c'
finally
Xpath 'd'
endtry
Xpath 'e'
finally
Xpath 'f'
endtry
Xpath 'g'
endfunc
func T32_G()
try
Xpath 'h'
return 8
Xpath 'i'
finally
Xpath 'j'
return 16 + strlen(T32_F())
Xpath 'k'
endtry
Xpath 'l'
endfunc
func T32_H()
try
Xpath 'm'
return 32
Xpath 'n'
finally
Xpath 'o'
return
Xpath 'p'
endtry
Xpath 'q'
endfunc
func T32_I()
try
Xpath 'r'
finally
Xpath 's'
return T32_G() + T32_H() + 64
Xpath 't'
endtry
Xpath 'u'
endfunc
func Test_finally_return()
XpathINIT
call assert_equal(84, T32_I())
call assert_equal('rshjabdfmo', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T33_F()
try
RETURN 10
Xpath 'a'
finally
Xpath 'b'
endtry
Xpath 'c'
endfunc
func T33_G()
try
RETURN 20
Xpath 'd'
finally
Xpath 'e'
RETURN 30
Xpath 'f'
endtry
Xpath 'g'
endfunc
func T33_H()
try
execute "try | return 40 | finally | return 50 | endtry"
Xpath 'h'
finally
Xpath 'i'
endtry
Xpath 'j'
endfunc
func T33_I()
try
execute "try | return 60 | finally | return 70 | endtry"
Xpath 'k'
finally
Xpath 'l'
execute "try | return 80 | finally | return 90 | endtry"
Xpath 'm'
endtry
Xpath 'n'
endfunc
func T33_J()
try
RETURN 100
Xpath 'o'
finally
Xpath 'p'
return
Xpath 'q'
endtry
Xpath 'r'
endfunc
func T33_K()
try
execute "try | return 110 | finally | return 120 | endtry"
Xpath 's'
finally
Xpath 't'
execute "try | return 130 | finally | return | endtry"
Xpath 'u'
endtry
Xpath 'v'
endfunc
func T33_L()
try
return
Xpath 'w'
finally
Xpath 'x'
RETURN 140
Xpath 'y'
endtry
Xpath 'z'
endfunc
func T33_M()
try
return
Xpath 'A'
finally
Xpath 'B'
execute "try | return 150 | finally | return 160 | endtry"
Xpath 'C'
endtry
Xpath 'D'
endfunc
func T33_N()
RETURN 170
endfunc
func T33_O()
execute "try | return 180 | finally | return 190 | endtry"
endfunc
func Test_finally_cmd_return()
command! -nargs=? RETURN
\ try | return <args> | finally | return <args> * 2 | endtry
XpathINIT
call assert_equal(20, T33_F())
call assert_equal(60, T33_G())
call assert_equal(50, T33_H())
call assert_equal(90, T33_I())
call assert_equal(0, T33_J())
call assert_equal(0, T33_K())
call assert_equal(280, T33_L())
call assert_equal(160, T33_M())
call assert_equal(340, T33_N())
call assert_equal(190, T33_O())
call assert_equal('beilptxB', g:Xpath)
delcommand RETURN
endfunc
"-------------------------------------------------------------------------------
" Test 41: Skipped :throw finding next command {{{1
"
" A :throw in an inactive conditional must not hide a following
" command.
"-------------------------------------------------------------------------------
func T41_F()
Xpath 'a'
if 0 | throw 'never' | endif | Xpath 'b'
Xpath 'c'
endfunc
func T41_G()
Xpath 'd'
while 0 | throw 'never' | endwhile | Xpath 'e'
Xpath 'f'
endfunc
func T41_H()
Xpath 'g'
if 0 | try | throw 'never' | endtry | endif | Xpath 'h'
Xpath 'i'
endfunc
func Test_throw_inactive_cond()
XpathINIT
try
Xpath 'j'
call T41_F()
Xpath 'k'
catch /.*/
Xpath 'l'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
try
Xpath 'm'
call T41_G()
Xpath 'n'
catch /.*/
Xpath 'o'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
try
Xpath 'p'
call T41_H()
Xpath 'q'
catch /.*/
Xpath 'r'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('jabckmdefnpghiq', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T42_F()
try
try
Xpath 'a'
throw 4711
Xpath 'b'
catch /4711/
Xpath 'c'
endtry
try
Xpath 'd'
throw 4711
Xpath 'e'
catch /^4711$/
Xpath 'f'
endtry
try
Xpath 'g'
throw 4711
Xpath 'h'
catch /\d/
Xpath 'i'
endtry
try
Xpath 'j'
throw 4711
Xpath 'k'
catch /^\d\+$/
Xpath 'l'
endtry
try
Xpath 'm'
throw "arrgh"
Xpath 'n'
catch /arrgh/
Xpath 'o'
endtry
try
Xpath 'p'
throw "arrgh"
Xpath 'q'
catch /^arrgh$/
Xpath 'r'
endtry
try
Xpath 's'
throw "arrgh"
Xpath 't'
catch /\l/
Xpath 'u'
endtry
try
Xpath 'v'
throw "arrgh"
Xpath 'w'
catch /^\l\+$/
Xpath 'x'
endtry
try
try
Xpath 'y'
throw "ARRGH"
Xpath 'z'
catch /^arrgh$/
Xpath 'A'
endtry
catch /^\carrgh$/
Xpath 'B'
endtry
try
Xpath 'C'
throw ""
Xpath 'D'
catch /^$/
Xpath 'E'
endtry
catch /.*/
Xpath 'F'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
endfunc
func Test_catch_number_string()
XpathINIT
call T42_F()
call assert_equal('acdfgijlmoprsuvxyBCE', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T43_F()
let loops = 3
while loops > 0
try
if loops == 3
Xpath 'a' . loops
throw "a"
Xpath 'b' . loops
elseif loops == 2
Xpath 'c' . loops
throw "ab"
Xpath 'd' . loops
elseif loops == 1
Xpath 'e' . loops
throw "abc"
Xpath 'f' . loops
endif
catch /abc/
Xpath 'g' . loops
catch /ab/
Xpath 'h' . loops
catch /.*/
Xpath 'i' . loops
catch /a/
Xpath 'j' . loops
endtry
let loops = loops - 1
endwhile
Xpath 'k'
endfunc
func Test_multi_catch()
XpathINIT
call T43_F()
call assert_equal('a3i3c2h2e1g1k', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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 //.
"-------------------------------------------------------------------------------
func T44_F()
try
try
Xpath 'a'
throw ""
catch /^$/
Xpath 'b'
endtry
try
Xpath 'c'
throw ""
catch /.*/
Xpath 'd'
endtry
try
Xpath 'e'
throw ""
catch //
Xpath 'f'
endtry
try
Xpath 'g'
throw ""
catch
Xpath 'h'
endtry
try
Xpath 'i'
throw "oops"
catch /^$/
Xpath 'j'
catch /.*/
Xpath 'k'
endtry
try
Xpath 'l'
throw "arrgh"
catch /^$/
Xpath 'm'
catch //
Xpath 'n'
endtry
try
Xpath 'o'
throw "brrr"
catch /^$/
Xpath 'p'
catch
Xpath 'q'
endtry
try | Xpath 'r' | throw "x" | catch /.*/ | Xpath 's' | endtry
try | Xpath 't' | throw "y" | catch // | Xpath 'u' | endtry
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 'v' | throw "z" | catch | Xpath 'w' | :
endtry
endtry
catch /.*/
let caught = 1
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
finally
if $VIMNOERRTHROW && v:errmsg != ""
call assert_report(v:errmsg)
endif
if caught || $VIMNOERRTHROW && v:errmsg != ""
Xpath 'x'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
let cologne = 4711
try
try
Xpath 'y'
throw "throw cologne"
" Next lines catches all and throws 4711:
catch |throw cologne|
Xpath 'z'
endtry
catch /4711/
Xpath 'A'
endtry
try
Xpath 'B'
throw "plus"
catch +plus+
Xpath 'C'
endtry
Xpath 'D'
catch /.*/
Xpath 'E'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
endfunc
func Test_empty_catch()
XpathINIT
call T44_F()
call assert_equal('abcdefghiklnoqrstuvwyABCD', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T45_F()
let loops = 3
while loops > 0
try
try
try
try
if loops == 3
Xpath 'a' . loops
throw "a"
Xpath 'b' . loops
elseif loops == 2
Xpath 'c' . loops
throw "ab"
Xpath 'd' . loops
elseif loops == 1
Xpath 'e' . loops
throw "abc"
Xpath 'f' . loops
endif
catch /abc/
Xpath 'g' . loops
endtry
catch /ab/
Xpath 'h' . loops
endtry
catch /.*/
Xpath 'i' . loops
endtry
catch /a/
Xpath 'j' . loops
endtry
let loops = loops - 1
endwhile
Xpath 'k'
endfunc
func Test_catch_from_nested_try()
XpathINIT
call T45_F()
call assert_equal('a3i3c2h2e1g1k', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T46_F()
let sum = 0
try
Xpath 'a'
try
Xpath 'b'
try
Xpath 'c'
try
Xpath 'd'
throw "ABC"
Xpath 'e'
catch /xyz/
Xpath 'f'
finally
Xpath 'g'
if sum != 0
Xpath 'h'
endif
let sum = sum + 1
endtry
Xpath 'i'
catch /123/
Xpath 'j'
catch /321/
Xpath 'k'
finally
Xpath 'l'
if sum != 1
Xpath 'm'
endif
let sum = sum + 2
endtry
Xpath 'n'
finally
Xpath 'o'
if sum != 3
Xpath 'p'
endif
let sum = sum + 4
endtry
Xpath 'q'
catch /ABC/
Xpath 'r'
if sum != 7
Xpath 's'
endif
let sum = sum + 8
finally
Xpath 't'
if sum != 15
Xpath 'u'
endif
let sum = sum + 16
endtry
Xpath 'v'
if sum != 31
Xpath 'w'
endif
endfunc
func Test_finally_after_throw()
XpathINIT
call T46_F()
call assert_equal('abcdglortv', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T47_F()
Xpath 'a'
try
Xpath 'b'
try
Xpath 'c'
try
Xpath 'd'
throw "x1"
Xpath 'e'
catch /x1/
Xpath 'f'
try
Xpath 'g'
throw "x2"
Xpath 'h'
catch /x1/
Xpath 'i'
catch /x2/
Xpath 'j'
try
Xpath 'k'
throw "x3"
Xpath 'l'
catch /x1/
Xpath 'm'
catch /x2/
Xpath 'n'
finally
Xpath 'o'
endtry
Xpath 'p'
catch /x3/
Xpath 'q'
endtry
Xpath 'r'
catch /x1/
Xpath 's'
catch /x2/
Xpath 't'
catch /x3/
Xpath 'u'
finally
Xpath 'v'
endtry
Xpath 'w'
catch /x1/
Xpath 'x'
catch /x2/
Xpath 'y'
catch /x3/
Xpath 'z'
endtry
Xpath 'A'
catch /.*/
Xpath 'B'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
Xpath 'C'
endfunc
func Test_throw_from_catch()
XpathINIT
call T47_F()
call assert_equal('abcdfgjkovzAC', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T48_F()
try
try
try
Xpath 'a'
catch /x1/
Xpath 'b'
finally
Xpath 'c'
throw "x1"
Xpath 'd'
endtry
Xpath 'e'
catch /x1/
Xpath 'f'
endtry
Xpath 'g'
try
try
Xpath 'h'
throw "x2"
Xpath 'i'
catch /x2/
Xpath 'j'
catch /x3/
Xpath 'k'
finally
Xpath 'l'
throw "x3"
Xpath 'm'
endtry
Xpath 'n'
catch /x2/
Xpath 'o'
catch /x3/
Xpath 'p'
endtry
Xpath 'q'
try
try
try
Xpath 'r'
throw "x4"
Xpath 's'
catch /x5/
Xpath 't'
finally
Xpath 'u'
throw "x5" " discards 'x4'
Xpath 'v'
endtry
Xpath 'w'
catch /x4/
Xpath 'x'
finally
Xpath 'y'
endtry
Xpath 'z'
catch /x5/
Xpath 'A'
endtry
Xpath 'B'
catch /.*/
Xpath 'C'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
Xpath 'D'
endfunc
func Test_throw_from_finally()
XpathINIT
call T48_F()
call assert_equal('acfghjlpqruyABD', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" Test 51: Throwing exceptions across :execute and user commands {{{1
"
" A :throw command may be executed under an ":execute" or from
" a user command.
"-------------------------------------------------------------------------------
func T51_F()
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 'a'
THROW1 "A"
catch /A/
Xpath 'b'
endtry
catch /1/
Xpath 'c'
endtry
try
try
Xpath 'd'
THROW2 "B"
catch /B/
Xpath 'e'
endtry
catch /2/
Xpath 'f'
endtry
try
try
Xpath 'g'
THROW3 "C"
catch /C/
Xpath 'h'
endtry
catch /3/
Xpath 'i'
endtry
try
try
Xpath 'j'
THROW4 "D"
catch /D/
Xpath 'k'
endtry
catch /4/
Xpath 'l'
endtry
try
try
Xpath 'm'
execute 'throw "E" | throw 5'
catch /E/
Xpath 'n'
endtry
catch /5/
Xpath 'o'
endtry
try
try
Xpath 'p'
execute 'try | throw "F" | endtry | throw 6'
catch /F/
Xpath 'q'
endtry
catch /6/
Xpath 'r'
endtry
try
try
Xpath 's'
execute'try | throw 7 | catch /7/ | throw "G" | endtry'
catch /G/
Xpath 't'
endtry
catch /7/
Xpath 'u'
endtry
try
try
Xpath 'v'
execute 'try | throw 8 | finally | throw "H" | endtry'
catch /H/
Xpath 'w'
endtry
catch /8/
Xpath 'x'
endtry
catch /.*/
Xpath 'y'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
Xpath 'z'
delcommand THROW1
delcommand THROW2
delcommand THROW3
delcommand THROW4
endfunc
func Test_throw_across_commands()
XpathINIT
call T51_F()
call assert_equal('abdeghjkmnpqstvwz', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T69_throw(x)
Xpath 'x'
throw a:x
endfunc
func Test_throw_ifelsewhile()
XpathINIT
try
try
Xpath 'a'
if 111 == T69_throw("if") + 111
Xpath 'b'
else
Xpath 'c'
endif
Xpath 'd'
catch /^if$/
Xpath 'e'
catch /.*/
Xpath 'f'
call assert_report("if: " . v:exception . " in " . v:throwpoint)
endtry
try
Xpath 'g'
if v:false
Xpath 'h'
elseif 222 == T69_throw("elseif") + 222
Xpath 'i'
else
Xpath 'j'
endif
Xpath 'k'
catch /^elseif$/
Xpath 'l'
catch /.*/
Xpath 'm'
call assert_report("elseif: " . v:exception . " in " . v:throwpoint)
endtry
try
Xpath 'n'
while 333 == T69_throw("while") + 333
Xpath 'o'
break
endwhile
Xpath 'p'
catch /^while$/
Xpath 'q'
catch /.*/
Xpath 'r'
call assert_report("while: " .. v:exception .. " in " .. v:throwpoint)
endtry
catch /^0$/ " default return value
Xpath 's'
call assert_report(v:throwpoint)
catch /.*/
call assert_report(v:exception .. " in " .. v:throwpoint)
Xpath 't'
endtry
call assert_equal('axegxlnxq', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
let T70_taken = ""
func T70_throw(x, n)
let g:T70_taken = g:T70_taken . "T" . a:n
throw a:x
endfunc
func T70_F(x, y, n)
let g:T70_taken = g:T70_taken . "F" . a:n
return a:x + T70_throw(a:y, a:n)
endfunc
func T70_G(x, y, n)
let g:T70_taken = g:T70_taken . "G" . a:n
throw a:x . T70_throw(a:y, a:n)
return a:x
endfunc
func Test_throwreturn()
XpathINIT
try
try
Xpath 'a'
call T70_F(4711, "return", 1)
Xpath 'b'
catch /^return$/
Xpath 'c'
catch /.*/
Xpath 'd'
call assert_report("return: " .. v:exception .. " in " .. v:throwpoint)
endtry
try
Xpath 'e'
let var = T70_F(4712, "return-var", 2)
Xpath 'f'
catch /^return-var$/
Xpath 'g'
catch /.*/
Xpath 'h'
call assert_report("return-var: " . v:exception . " in " . v:throwpoint)
finally
unlet! var
endtry
try
Xpath 'i'
throw "except1" . T70_throw("throw1", 3)
Xpath 'j'
catch /^except1/
Xpath 'k'
catch /^throw1$/
Xpath 'l'
catch /.*/
Xpath 'm'
call assert_report("throw1: " .. v:exception .. " in " .. v:throwpoint)
endtry
try
Xpath 'n'
call T70_G("except2", "throw2", 4)
Xpath 'o'
catch /^except2/
Xpath 'p'
catch /^throw2$/
Xpath 'q'
catch /.*/
Xpath 'r'
call assert_report("throw2: " .. v:exception .. " in " .. v:throwpoint)
endtry
try
Xpath 's'
let var = T70_G("except3", "throw3", 5)
Xpath 't'
catch /^except3/
Xpath 'u'
catch /^throw3$/
Xpath 'v'
catch /.*/
Xpath 'w'
call assert_report("throw3: " .. v:exception .. " in " .. v:throwpoint)
finally
unlet! var
endtry
call assert_equal('F1T1F2T2T3G4T4G5T5', g:T70_taken)
Xpath 'x'
catch /^0$/ " default return value
Xpath 'y'
call assert_report(v:throwpoint)
catch /.*/
Xpath 'z'
call assert_report('Caught' .. v:exception .. ' in ' .. v:throwpoint)
endtry
call assert_equal('acegilnqsvx', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
let T71_taken = ""
func T71_throw(x, n)
let g:T71_taken = g:T71_taken . "T" . a:n
throw a:x
endfunc
func T71_F(n)
let g:T71_taken = g:T71_taken . "F" . a:n
return "F" . a:n
endfunc
func Test_throw_echo()
XpathINIT
try
try
Xpath 'a'
echo 'echo ' . T71_throw("echo-except", 1) . T71_F(1)
Xpath 'b'
catch /^echo-except$/
Xpath 'c'
catch /.*/
Xpath 'd'
call assert_report("echo: " .. v:exception .. " in " .. v:throwpoint)
endtry
try
Xpath 'e'
echon "echon " . T71_throw("echon-except", 2) . T71_F(2)
Xpath 'f'
catch /^echon-except$/
Xpath 'g'
catch /.*/
Xpath 'h'
call assert_report('echon: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
Xpath 'i'
echomsg "echomsg " . T71_throw("echomsg-except", 3) . T71_F(3)
Xpath 'j'
catch /^echomsg-except$/
Xpath 'k'
catch /.*/
Xpath 'l'
call assert_report('echomsg: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
Xpath 'm'
echoerr "echoerr " . T71_throw("echoerr-except", 4) . T71_F(4)
Xpath 'n'
catch /^echoerr-except$/
Xpath 'o'
catch /Vim/
Xpath 'p'
catch /echoerr/
Xpath 'q'
catch /.*/
Xpath 'r'
call assert_report('echoerr: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
Xpath 's'
execute "echo 'execute " . T71_throw("execute-except", 5) . T71_F(5) "'"
Xpath 't'
catch /^execute-except$/
Xpath 'u'
catch /.*/
Xpath 'v'
call assert_report('execute: ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('T1T2T3T4T5', g:T71_taken)
Xpath 'w'
catch /^0$/ " default return value
Xpath 'x'
call assert_report(v:throwpoint)
catch /.*/
Xpath 'y'
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('acegikmosuw', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
let throwcount = 0
func T72_throw(x)
let g:throwcount = g:throwcount + 1
throw a:x
endfunc
let T72_addpath = ''
func T72_addpath(p)
let g:T72_addpath = g:T72_addpath . a:p
endfunc
func Test_throw_let()
XpathINIT
try
try
let $VAR = 'old_value'
Xpath 'a'
let $VAR = 'let(' . T72_throw('var') . ')'
Xpath 'b'
catch /^var$/
Xpath 'c'
finally
call assert_equal('old_value', $VAR)
endtry
try
let @a = 'old_value'
Xpath 'd'
let @a = 'let(' . T72_throw('reg') . ')'
Xpath 'e'
catch /^reg$/
try
Xpath 'f'
let @A = 'let(' . T72_throw('REG') . ')'
Xpath 'g'
catch /^REG$/
Xpath 'h'
endtry
finally
call assert_equal('old_value', @a)
call assert_equal('old_value', @A)
endtry
try
let saved_gpath = &g:path
let saved_lpath = &l:path
Xpath 'i'
let &path = 'let(' . T72_throw('opt') . ')'
Xpath 'j'
catch /^opt$/
try
Xpath 'k'
let &g:path = 'let(' . T72_throw('gopt') . ')'
Xpath 'l'
catch /^gopt$/
try
Xpath 'm'
let &l:path = 'let(' . T72_throw('lopt') . ')'
Xpath 'n'
catch /^lopt$/
Xpath 'o'
endtry
endtry
finally
call assert_equal(saved_gpath, &g:path)
call assert_equal(saved_lpath, &l:path)
let &g:path = saved_gpath
let &l:path = saved_lpath
endtry
unlet! var1 var2 var3
try
Xpath 'p'
let var1 = 'let(' . T72_throw('var1') . ')'
Xpath 'q'
catch /^var1$/
Xpath 'r'
finally
call assert_true(!exists('var1'))
endtry
try
let var2 = 'old_value'
Xpath 's'
let var2 = 'let(' . T72_throw('var2'). ')'
Xpath 't'
catch /^var2$/
Xpath 'u'
finally
call assert_equal('old_value', var2)
endtry
try
Xpath 'v'
let var{T72_throw('var3')} = 4711
Xpath 'w'
catch /^var3$/
Xpath 'x'
endtry
try
call T72_addpath('T1')
let var{T72_throw('var4')} var{T72_addpath('T2')} | call T72_addpath('T3')
call T72_addpath('T4')
catch /^var4$/
call T72_addpath('T5')
endtry
try
call T72_addpath('T6')
unlet var{T72_throw('var5')} var{T72_addpath('T7')}
\ | call T72_addpath('T8')
call T72_addpath('T9')
catch /^var5$/
call T72_addpath('T10')
endtry
call assert_equal('T1T5T6T10', g:T72_addpath)
call assert_equal(11, g:throwcount)
catch /.*/
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('acdfhikmoprsuvx', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
let T73_taken = ''
func T73_throw(x, n)
let g:T73_taken = g:T73_taken . 'T' . a:n
throw a:x
endfunc
func T73_expr(x, n)
let g:T73_taken = g:T73_taken . 'E' . a:n
if a:n % 2 == 0
call T73_throw(a:x, a:n)
endif
return 2 - a:n % 2
endfunc
func Test_throw_func()
XpathINIT
try
try
" Define function.
Xpath 'a'
function! F0()
endfunction
Xpath 'b'
function! F{T73_expr('function-def-ok', 1)}()
endfunction
Xpath 'c'
function! F{T73_expr('function-def', 2)}()
endfunction
Xpath 'd'
catch /^function-def-ok$/
Xpath 'e'
catch /^function-def$/
Xpath 'f'
catch /.*/
call assert_report('def: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
" List function.
Xpath 'g'
function F0
Xpath 'h'
function F{T73_expr('function-lst-ok', 3)}
Xpath 'i'
function F{T73_expr('function-lst', 4)}
Xpath 'j'
catch /^function-lst-ok$/
Xpath 'k'
catch /^function-lst$/
Xpath 'l'
catch /.*/
call assert_report('lst: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
" Delete function
Xpath 'm'
delfunction F0
Xpath 'n'
delfunction F{T73_expr('function-del-ok', 5)}
Xpath 'o'
delfunction F{T73_expr('function-del', 6)}
Xpath 'p'
catch /^function-del-ok$/
Xpath 'q'
catch /^function-del$/
Xpath 'r'
catch /.*/
call assert_report('del: ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('E1E2T2E3E4T4E5E6T6', g:T73_taken)
catch /.*/
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('abcfghilmnor', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
let T74_taken = ""
func T74_throw(x, n)
let g:T74_taken = g:T74_taken . "T" . a:n
throw a:x
endfunc
func T74_expr(x, n)
let g:T74_taken = g:T74_taken . "E" . a:n
call T74_throw(a:x . a:n, a:n)
return "EXPR"
endfunc
func T74_skip(x, n)
let g:T74_taken = g:T74_taken . "S" . a:n . "(" . line(".")
let theline = getline(".")
if theline =~ "skip"
let g:T74_taken = g:T74_taken . "s)"
return 1
elseif theline =~ "throw"
let g:T74_taken = g:T74_taken . "t)"
call T74_throw(a:x . a:n, a:n)
else
let g:T74_taken = g:T74_taken . ")"
return 0
endif
endfunc
func T74_subst(x, n)
let g:T74_taken = g:T74_taken . "U" . a:n . "(" . line(".")
let theline = getline(".")
if theline =~ "not" " T74_subst() should not be called for this line
let g:T74_taken = g:T74_taken . "n)"
call T74_throw(a:x . a:n, a:n)
elseif theline =~ "throw"
let g:T74_taken = g:T74_taken . "t)"
call T74_throw(a:x . a:n, a:n)
else
let g:T74_taken = g:T74_taken . ")"
return "replaced"
endif
endfunc
func Test_throw_builtin_func()
XpathINIT
try
try
Xpath 'a'
let result = exists('*{T74_expr("exists", 1)}')
Xpath 'b'
catch /^exists1$/
Xpath 'c'
try
let result = exists('{T74_expr("exists", 2)}')
Xpath 'd'
catch /^exists2$/
Xpath 'e'
catch /.*/
call assert_report('exists2: ' . v:exception . ' in ' . v:throwpoint)
endtry
catch /.*/
call assert_report('exists1: ' . v:exception . ' in ' . v:throwpoint)
endtry
try
let file = tempname()
exec "edit" file
call append(0, [
\ 'begin',
\ 'xx',
\ 'middle 3',
\ 'xx',
\ 'middle 5 skip',
\ 'xx',
\ 'middle 7 throw',
\ 'xx',
\ 'end'])
normal! gg
Xpath 'f'
let result = searchpair("begin", "middle", "end", '',
\ 'T74_skip("searchpair", 3)')
Xpath 'g'
let result = searchpair("begin", "middle", "end", '',
\ 'T74_skip("searchpair", 4)')
Xpath 'h'
let result = searchpair("begin", "middle", "end", '',
\ 'T74_skip("searchpair", 5)')
Xpath 'i'
catch /^searchpair[35]$/
Xpath 'j'
catch /^searchpair4$/
Xpath 'k'
catch /.*/
call assert_report('searchpair: ' . v:exception . ' in ' . v:throwpoint)
finally
bwipeout!
call delete(file)
endtry
try
let file = tempname()
exec "edit" file
call append(0, [
\ 'subst 1',
\ 'subst 2',
\ 'not',
\ 'subst 4',
\ 'subst throw',
\ 'subst 6'])
normal! gg
Xpath 'l'
1,2substitute/subst/\=T74_subst("substitute", 6)/
try
Xpath 'm'
try
let v:errmsg = ""
3substitute/subst/\=T74_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 'n'
3substitute/subst/\=T74_subst("substitute", 8)/e
Xpath 'o'
endtry
Xpath 'p'
4,6substitute/subst/\=T74_subst("substitute", 9)/
Xpath 'q'
catch /^substitute[678]/
Xpath 'r'
catch /^substitute9/
Xpath 's'
finally
bwipeout!
call delete(file)
endtry
try
Xpath 't'
let var = substitute("sub", "sub", '\=T74_throw("substitute()y", 10)', '')
Xpath 'u'
catch /substitute()y/
Xpath 'v'
catch /.*/
call assert_report('substitute()y: ' . v:exception . ' in '
\ . v:throwpoint)
endtry
try
Xpath 'w'
let var = substitute("not", "sub", '\=T74_throw("substitute()n", 11)', '')
Xpath 'x'
catch /substitute()n/
Xpath 'y'
catch /.*/
call assert_report('substitute()n: ' . v:exception . ' in '
\ . v:throwpoint)
endtry
call assert_equal('E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10',
\ g:T74_taken)
catch /.*/
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
endtry
call assert_equal('acefgklmnopstvwx', g:Xpath)
endfunc
"-------------------------------------------------------------------------------
" 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.
"-------------------------------------------------------------------------------
func T75_F1(arg1)
Xpath 'a'
endfunc
func T75_F2(arg1, arg2)
Xpath 'b'
endfunc
func T75_G()
Xpath 'c'
endfunc
func T75_H()
Xpath 'd'
endfunc
func T75_R()
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'e'
return append(1, "s")
catch /E21/
let caught = 1
catch /.*/
Xpath 'f'
finally
Xpath 'g'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'h'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
Xpath 'i'
endfunc
func Test_builtin_func_error()
XpathINIT
try
set noma " let append() fail with "E21"
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'j'
call append(1, "s")
catch /E21/
let caught = 1
catch /.*/
Xpath 'k'
finally
Xpath 'l'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'm'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'n'
call T75_F1('x' . append(1, "s"))
catch /E21/
let caught = 1
catch /.*/
Xpath 'o'
finally
Xpath 'p'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'q'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'r'
call T75_F2('x' . append(1, "s"), T75_G())
catch /E21/
let caught = 1
catch /.*/
Xpath 's'
finally
Xpath 't'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'u'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
call T75_R()
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'v'
throw "T" . append(1, "s")
catch /E21/
let caught = 1
catch /^T.*/
Xpath 'w'
catch /.*/
Xpath 'x'
finally
Xpath 'y'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'z'
endif
break " discard error for $VIMNOERRTHROW
endtry
endwhile
while 1
try
let caught = 0
let v:errmsg = ""
Xpath 'A'
let x = "a"
let x = x . "b" . append(1, "s") . T75_H()
catch /E21/
let caught = 1
catch /.*/
Xpath 'B'
finally
Xpath 'C'
if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
Xpath 'D'
endif
call assert_equal('a', x)
break " discard error for $VIMNOERRTHROW
endtry
endwhile
catch /.*/
call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
finally
set ma&
endtry
call assert_equal('jlmnpqrtueghivyzACD', g:Xpath)
endfunc
func Test_reload_in_try_catch()
call writefile(['x'], 'Xreload')
set autoread
edit Xreload
tabnew
call writefile(['xx'], 'Xreload')
augroup ReLoad
au FileReadPost Xreload let x = doesnotexist
au BufReadPost Xreload let x = doesnotexist
augroup END
try
edit Xreload
catch
endtry
tabnew
tabclose
tabclose
autocmd! ReLoad
set noautoread
bwipe! Xreload
call delete('Xreload')
endfunc
" Test for errors with :catch, :throw, :finally {{{1
func Test_try_catch_errors()
call assert_fails('throw |', 'E471:')
call assert_fails("throw \n ", 'E471:')
call assert_fails('catch abc', 'E654:')
call assert_fails('try | let i = 1| finally | catch | endtry', 'E604:')
call assert_fails('finally', 'E606:')
call assert_fails('try | finally | finally | endtry', 'E607:')
call assert_fails('try | for i in range(5) | endif | endtry', 'E580:')
call assert_fails('try | while v:true | endtry', 'E170:')
call assert_fails('try | if v:true | endtry', 'E171:')
" this was using a negative index in cstack[]
let lines =<< trim END
try
for
if
endwhile
if
finally
END
call CheckScriptFailure(lines, 'E690:')
let lines =<< trim END
try
for
if
endwhile
if
endtry
END
call CheckScriptFailure(lines, 'E690:')
endfunc
" Test for verbose messages with :try :catch, and :finally {{{1
func Test_try_catch_verbose()
" This test works only when the language is English
CheckEnglish
set verbose=14
" Test for verbose messages displayed when an exception is caught
redir => msg
try
echo i
catch /E121:/
finally
endtry
redir END
let expected = [
\ 'Exception thrown: Vim(echo):E121: Undefined variable: i', '',
\ 'Exception caught: Vim(echo):E121: Undefined variable: i', '',
\ 'Exception finished: Vim(echo):E121: Undefined variable: i']
call assert_equal(expected, split(msg, "\n"))
" Test for verbose messages displayed when an exception is discarded
redir => msg
try
try
throw 'abc'
finally
throw 'xyz'
endtry
catch
endtry
redir END
let expected = [
\ 'Exception thrown: abc', '',
\ 'Exception made pending: abc', '',
\ 'Exception thrown: xyz', '',
\ 'Exception discarded: abc', '',
\ 'Exception caught: xyz', '',
\ 'Exception finished: xyz']
call assert_equal(expected, split(msg, "\n"))
" Test for messages displayed when :throw is resumed after :finally
redir => msg
try
try
throw 'abc'
finally
endtry
catch
endtry
redir END
let expected = [
\ 'Exception thrown: abc', '',
\ 'Exception made pending: abc', '',
\ 'Exception resumed: abc', '',
\ 'Exception caught: abc', '',
\ 'Exception finished: abc']
call assert_equal(expected, split(msg, "\n"))
" Test for messages displayed when :break is resumed after :finally
redir => msg
for i in range(1)
try
break
finally
endtry
endfor
redir END
let expected = [':break made pending', '', ':break resumed']
call assert_equal(expected, split(msg, "\n"))
" Test for messages displayed when :continue is resumed after :finally
redir => msg
for i in range(1)
try
continue
finally
endtry
endfor
redir END
let expected = [':continue made pending', '', ':continue resumed']
call assert_equal(expected, split(msg, "\n"))
" Test for messages displayed when :return is resumed after :finally
func Xtest()
try
return 'vim'
finally
endtry
endfunc
redir => msg
call Xtest()
redir END
let expected = [
\ 'calling Xtest()', '',
\ ':return vim made pending', '',
\ ':return vim resumed', '',
\ 'Xtest returning ''vim''', '',
\ 'continuing in Test_try_catch_verbose']
call assert_equal(expected, split(msg, "\n"))
delfunc Xtest
" Test for messages displayed when :finish is resumed after :finally
call writefile(['try', 'finish', 'finally', 'endtry'], 'Xscript')
redir => msg
source Xscript
redir END
let expected = [
\ ':finish made pending', '',
\ ':finish resumed', '',
\ 'finished sourcing Xscript',
\ 'continuing in Test_try_catch_verbose']
call assert_equal(expected, split(msg, "\n")[1:])
call delete('Xscript')
" Test for messages displayed when a pending :continue is discarded by an
" exception in a finally handler
redir => msg
try
for i in range(1)
try
continue
finally
throw 'abc'
endtry
endfor
catch
endtry
redir END
let expected = [
\ ':continue made pending', '',
\ 'Exception thrown: abc', '',
\ ':continue discarded', '',
\ 'Exception caught: abc', '',
\ 'Exception finished: abc']
call assert_equal(expected, split(msg, "\n"))
set verbose&
endfunc
" Test for throwing an exception from a BufEnter autocmd {{{1
func Test_BufEnter_exception()
augroup bufenter_exception
au!
autocmd BufEnter Xfile1 throw 'abc'
augroup END
let caught_abc = 0
try
sp Xfile1
catch /^abc/
let caught_abc = 1
endtry
call assert_equal(1, caught_abc)
call assert_equal(1, winnr('$'))
augroup bufenter_exception
au!
augroup END
augroup! bufenter_exception
%bwipe!
" Test for recursively throwing exceptions in autocmds
augroup bufenter_exception
au!
autocmd BufEnter Xfile1 throw 'bufenter'
autocmd BufLeave Xfile1 throw 'bufleave'
augroup END
let ex_count = 0
try
try
sp Xfile1
catch /^bufenter/
let ex_count += 1
endtry
catch /^bufleave/
let ex_count += 10
endtry
call assert_equal(10, ex_count)
call assert_equal(2, winnr('$'))
augroup bufenter_exception
au!
augroup END
augroup! bufenter_exception
%bwipe!
endfunc
" Test for using try/catch when lines are joined by "|" or "\n" {{{1
func Test_try_catch_nextcmd()
func Throw()
throw "Failure"
endfunc
let lines =<< trim END
try
let s:x = Throw()
catch
let g:caught = 1
endtry
END
let g:caught = 0
call execute(lines)
call assert_equal(1, g:caught)
let g:caught = 0
call execute(join(lines, '|'))
call assert_equal(1, g:caught)
let g:caught = 0
call execute(join(lines, "\n"))
call assert_equal(1, g:caught)
unlet g:caught
delfunc Throw
endfunc
" Test for using try/catch in a user command with a failing expression {{{1
func Test_user_command_try_catch()
let lines =<< trim END
function s:throw() abort
throw 'error'
endfunction
command! Execute
\ try
\ | let s:x = s:throw()
\ | catch
\ | let g:caught = 'caught'
\ | endtry
let g:caught = 'no'
Execute
call assert_equal('caught', g:caught)
END
call writefile(lines, 'XtestTryCatch')
source XtestTryCatch
call delete('XtestTryCatch')
unlet g:caught
endfunc
" Test for using throw in a called function with following error {{{1
func Test_user_command_throw_in_function_call()
let lines =<< trim END
function s:get_dict() abort
throw 'my_error'
endfunction
try
call s:get_dict().foo()
catch /my_error/
let caught = 'yes'
catch
let caught = v:exception
endtry
call assert_equal('yes', caught)
END
call writefile(lines, 'XtestThrow')
source XtestThrow
call delete('XtestThrow')
unlet g:caught
endfunc
" Test that after reporting an uncaught exception there is no error for a
" missing :endif
func Test_after_exception_no_endif_error()
function Throw()
throw "Failure"
endfunction
function Foo()
if 1
call Throw()
endif
endfunction
call assert_fails('call Foo()', ['E605:', 'E605:'])
delfunc Throw
delfunc Foo
endfunc
" Test for using throw in a called function with following endtry {{{1
func Test_user_command_function_call_with_endtry()
let lines =<< trim END
funct s:throw(msg) abort
throw a:msg
endfunc
func s:main() abort
try
try
throw 'err1'
catch
call s:throw('err2') | endtry
catch
let s:caught = 'yes'
endtry
endfunc
call s:main()
call assert_equal('yes', s:caught)
END
call writefile(lines, 'XtestThrow')
source XtestThrow
call delete('XtestThrow')
endfunc
func ThisWillFail()
endfunc
" This was crashing prior to the fix in 8.2.3478.
func Test_error_in_catch_and_finally()
let lines =<< trim END
try
echo x
catch
for l in []
finally
END
call writefile(lines, 'XtestCatchAndFinally')
try
source XtestCatchAndFinally
catch /E600:/
endtry
call delete('XtestCatchAndFinally')
endfunc
" This was causing an illegal memory access
func Test_leave_block_in_endtry_not_called()
let lines =<< trim END
" vim9script
" try #
try "
for x in []
if
endwhile
if
endtry
END
call writefile(lines, 'XtestEndtry')
try
source XtestEndtry
catch /E171:/
endtry
call delete('XtestEndtry')
endfunc
" Modeline {{{1
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker