mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.1236: Vim9: a few errors not caught by try/catch
Problem: Vim9: a few errors not caught by try/catch. Solution: Do not bail out if an error is inside try/catch. Fix that a not matching catch doesn't jump to :endtry.
This commit is contained in:
@@ -511,6 +511,22 @@ def Test_try_catch()
|
|||||||
endtry # comment
|
endtry # comment
|
||||||
assert_equal(['1', 'wrong', '3'], l)
|
assert_equal(['1', 'wrong', '3'], l)
|
||||||
|
|
||||||
|
l = []
|
||||||
|
try
|
||||||
|
try
|
||||||
|
add(l, '1')
|
||||||
|
throw 'wrong'
|
||||||
|
add(l, '2')
|
||||||
|
catch /right/
|
||||||
|
add(l, v:exception)
|
||||||
|
endtry
|
||||||
|
catch /wrong/
|
||||||
|
add(l, 'caught')
|
||||||
|
finally
|
||||||
|
add(l, 'finally')
|
||||||
|
endtry
|
||||||
|
assert_equal(['1', 'caught', 'finally'], l)
|
||||||
|
|
||||||
let n: number
|
let n: number
|
||||||
try
|
try
|
||||||
n = l[3]
|
n = l[3]
|
||||||
@@ -591,15 +607,63 @@ def Test_try_catch()
|
|||||||
endtry
|
endtry
|
||||||
assert_equal(277, n)
|
assert_equal(277, n)
|
||||||
|
|
||||||
# TODO: make this work
|
try
|
||||||
# try
|
&ts = g:astring
|
||||||
# &ts = g:astring
|
catch /E1029:/
|
||||||
# catch /E1093:/
|
n = 288
|
||||||
# n = 288
|
endtry
|
||||||
# endtry
|
assert_equal(288, n)
|
||||||
# assert_equal(288, n)
|
|
||||||
|
try
|
||||||
|
&backspace = 'asdf'
|
||||||
|
catch /E474:/
|
||||||
|
n = 299
|
||||||
|
endtry
|
||||||
|
assert_equal(299, n)
|
||||||
|
|
||||||
|
l = [1]
|
||||||
|
try
|
||||||
|
l[3] = 3
|
||||||
|
catch /E684:/
|
||||||
|
n = 300
|
||||||
|
endtry
|
||||||
|
assert_equal(300, n)
|
||||||
|
|
||||||
|
try
|
||||||
|
d[''] = 3
|
||||||
|
catch /E713:/
|
||||||
|
n = 311
|
||||||
|
endtry
|
||||||
|
assert_equal(311, n)
|
||||||
|
|
||||||
|
try
|
||||||
|
unlet g:does_not_exist
|
||||||
|
catch /E108:/
|
||||||
|
n = 322
|
||||||
|
endtry
|
||||||
|
assert_equal(322, n)
|
||||||
|
|
||||||
|
try
|
||||||
|
d = {'text': 1, g:astring: 2}
|
||||||
|
catch /E721:/
|
||||||
|
n = 333
|
||||||
|
endtry
|
||||||
|
assert_equal(333, n)
|
||||||
|
|
||||||
|
try
|
||||||
|
l = DeletedFunc()
|
||||||
|
catch /E933:/
|
||||||
|
n = 344
|
||||||
|
endtry
|
||||||
|
assert_equal(344, n)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def DeletedFunc(): list<any>
|
||||||
|
return ['delete me']
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
delfunc DeletedFunc
|
||||||
|
|
||||||
def ThrowFromDef()
|
def ThrowFromDef()
|
||||||
throw "getout" # comment
|
throw "getout" # comment
|
||||||
enddef
|
enddef
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1236,
|
||||||
/**/
|
/**/
|
||||||
1235,
|
1235,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -4961,6 +4961,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
|
if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
// TODO: check the length of a constant list here
|
||||||
generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
|
generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
|
||||||
semicolon);
|
semicolon);
|
||||||
}
|
}
|
||||||
@@ -6539,6 +6540,7 @@ compile_finally(char_u *arg, cctx_T *cctx)
|
|||||||
// Previous catch without match jumps here
|
// Previous catch without match jumps here
|
||||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
|
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
|
||||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
|
scope->se_u.se_try.ts_catch_label = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: set index in ts_finally_label jumps
|
// TODO: set index in ts_finally_label jumps
|
||||||
@@ -6584,8 +6586,18 @@ compile_endtry(char_u *arg, cctx_T *cctx)
|
|||||||
compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
|
compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
|
||||||
|
|
||||||
// End :catch or :finally scope: set value in ISN_TRY instruction
|
// End :catch or :finally scope: set value in ISN_TRY instruction
|
||||||
|
if (isn->isn_arg.try.try_catch == 0)
|
||||||
|
isn->isn_arg.try.try_catch = instr->ga_len;
|
||||||
if (isn->isn_arg.try.try_finally == 0)
|
if (isn->isn_arg.try.try_finally == 0)
|
||||||
isn->isn_arg.try.try_finally = instr->ga_len;
|
isn->isn_arg.try.try_finally = instr->ga_len;
|
||||||
|
|
||||||
|
if (scope->se_u.se_try.ts_catch_label != 0)
|
||||||
|
{
|
||||||
|
// Last catch without match jumps here
|
||||||
|
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
|
||||||
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
|
}
|
||||||
|
|
||||||
compile_endblock(cctx);
|
compile_endblock(cctx);
|
||||||
|
|
||||||
if (generate_instr(cctx, ISN_ENDTRY) == NULL)
|
if (generate_instr(cctx, ISN_ENDTRY) == NULL)
|
||||||
|
@@ -1241,7 +1241,7 @@ call_def_function(
|
|||||||
if (msg != NULL)
|
if (msg != NULL)
|
||||||
{
|
{
|
||||||
emsg(_(msg));
|
emsg(_(msg));
|
||||||
goto failed;
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1272,7 +1272,8 @@ call_def_function(
|
|||||||
--ectx.ec_stack.ga_len;
|
--ectx.ec_stack.ga_len;
|
||||||
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
|
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
|
||||||
== FAIL)
|
== FAIL)
|
||||||
goto failed;
|
// should not happen, type is checked when compiling
|
||||||
|
goto on_error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// store g:/b:/w:/t: variable
|
// store g:/b:/w:/t: variable
|
||||||
@@ -1335,7 +1336,7 @@ call_def_function(
|
|||||||
if (lidx < 0 || lidx > list->lv_len)
|
if (lidx < 0 || lidx > list->lv_len)
|
||||||
{
|
{
|
||||||
semsg(_(e_listidx), lidx);
|
semsg(_(e_listidx), lidx);
|
||||||
goto failed;
|
goto on_error;
|
||||||
}
|
}
|
||||||
tv = STACK_TV_BOT(-3);
|
tv = STACK_TV_BOT(-3);
|
||||||
if (lidx < list->lv_len)
|
if (lidx < list->lv_len)
|
||||||
@@ -1348,7 +1349,7 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// append to list
|
// append to list, only fails when out of memory
|
||||||
if (list_append_tv(list, tv) == FAIL)
|
if (list_append_tv(list, tv) == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
clear_tv(tv);
|
clear_tv(tv);
|
||||||
@@ -1371,18 +1372,19 @@ call_def_function(
|
|||||||
if (key == NULL || *key == NUL)
|
if (key == NULL || *key == NUL)
|
||||||
{
|
{
|
||||||
emsg(_(e_emptykey));
|
emsg(_(e_emptykey));
|
||||||
goto failed;
|
goto on_error;
|
||||||
}
|
}
|
||||||
tv = STACK_TV_BOT(-3);
|
tv = STACK_TV_BOT(-3);
|
||||||
di = dict_find(dict, key, -1);
|
di = dict_find(dict, key, -1);
|
||||||
if (di != NULL)
|
if (di != NULL)
|
||||||
{
|
{
|
||||||
|
// overwrite existing value
|
||||||
clear_tv(&di->di_tv);
|
clear_tv(&di->di_tv);
|
||||||
di->di_tv = *tv;
|
di->di_tv = *tv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// add to dict
|
// add to dict, only fails when out of memory
|
||||||
if (dict_add_tv(dict, (char *)key, tv) == FAIL)
|
if (dict_add_tv(dict, (char *)key, tv) == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
clear_tv(tv);
|
clear_tv(tv);
|
||||||
@@ -1465,7 +1467,7 @@ call_def_function(
|
|||||||
case ISN_UNLET:
|
case ISN_UNLET:
|
||||||
if (do_unlet(iptr->isn_arg.unlet.ul_name,
|
if (do_unlet(iptr->isn_arg.unlet.ul_name,
|
||||||
iptr->isn_arg.unlet.ul_forceit) == FAIL)
|
iptr->isn_arg.unlet.ul_forceit) == FAIL)
|
||||||
goto failed;
|
goto on_error;
|
||||||
break;
|
break;
|
||||||
case ISN_UNLETENV:
|
case ISN_UNLETENV:
|
||||||
vim_unsetenv(iptr->isn_arg.unlet.ul_name);
|
vim_unsetenv(iptr->isn_arg.unlet.ul_name);
|
||||||
@@ -1489,17 +1491,31 @@ call_def_function(
|
|||||||
goto failed;
|
goto failed;
|
||||||
for (idx = 0; idx < count; ++idx)
|
for (idx = 0; idx < count; ++idx)
|
||||||
{
|
{
|
||||||
// check key type is VAR_STRING
|
// have already checked key type is VAR_STRING
|
||||||
tv = STACK_TV_BOT(2 * (idx - count));
|
tv = STACK_TV_BOT(2 * (idx - count));
|
||||||
|
// check key is unique
|
||||||
|
item = dict_find(dict, tv->vval.v_string, -1);
|
||||||
|
if (item != NULL)
|
||||||
|
{
|
||||||
|
semsg(_(e_duplicate_key), tv->vval.v_string);
|
||||||
|
dict_unref(dict);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
item = dictitem_alloc(tv->vval.v_string);
|
item = dictitem_alloc(tv->vval.v_string);
|
||||||
clear_tv(tv);
|
clear_tv(tv);
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
|
{
|
||||||
|
dict_unref(dict);
|
||||||
goto failed;
|
goto failed;
|
||||||
|
}
|
||||||
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
|
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
|
||||||
item->di_tv.v_lock = 0;
|
item->di_tv.v_lock = 0;
|
||||||
if (dict_add(dict, item) == FAIL)
|
if (dict_add(dict, item) == FAIL)
|
||||||
|
{
|
||||||
|
dict_unref(dict);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
ectx.ec_stack.ga_len -= 2 * count - 1;
|
ectx.ec_stack.ga_len -= 2 * count - 1;
|
||||||
@@ -1519,7 +1535,7 @@ call_def_function(
|
|||||||
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
|
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
|
||||||
iptr->isn_arg.dfunc.cdf_argcount,
|
iptr->isn_arg.dfunc.cdf_argcount,
|
||||||
&ectx) == FAIL)
|
&ectx) == FAIL)
|
||||||
goto failed;
|
goto on_error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// call a builtin function
|
// call a builtin function
|
||||||
|
Reference in New Issue
Block a user