mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.2441: Vim9: extend() does not give an error for a type mismatch
Problem: Vim9: extend() does not give an error for a type mismatch. Solution: Check the type of the second argument. (closes #7760)
This commit is contained in:
parent
853886722c
commit
c03f5c677a
34
src/list.c
34
src/list.c
@ -2493,6 +2493,16 @@ f_count(typval_T *argvars, typval_T *rettv)
|
|||||||
static void
|
static void
|
||||||
extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||||
{
|
{
|
||||||
|
type_T *type = NULL;
|
||||||
|
garray_T type_list;
|
||||||
|
|
||||||
|
if (!is_new && in_vim9script())
|
||||||
|
{
|
||||||
|
// Check that map() does not change the type of the dict.
|
||||||
|
ga_init2(&type_list, sizeof(type_T *), 10);
|
||||||
|
type = typval2type(argvars, &type_list);
|
||||||
|
}
|
||||||
|
|
||||||
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
|
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
|
||||||
{
|
{
|
||||||
list_T *l1, *l2;
|
list_T *l1, *l2;
|
||||||
@ -2504,7 +2514,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
if (l1 == NULL)
|
if (l1 == NULL)
|
||||||
{
|
{
|
||||||
emsg(_(e_cannot_extend_null_list));
|
emsg(_(e_cannot_extend_null_list));
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
l2 = argvars[1].vval.v_list;
|
l2 = argvars[1].vval.v_list;
|
||||||
if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
|
if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
|
||||||
@ -2514,14 +2524,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
{
|
{
|
||||||
l1 = list_copy(l1, FALSE, get_copyID());
|
l1 = list_copy(l1, FALSE, get_copyID());
|
||||||
if (l1 == NULL)
|
if (l1 == NULL)
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||||
{
|
{
|
||||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||||
if (error)
|
if (error)
|
||||||
return; // type error; errmsg already given
|
goto theend; // type error; errmsg already given
|
||||||
|
|
||||||
if (before == l1->lv_len)
|
if (before == l1->lv_len)
|
||||||
item = NULL;
|
item = NULL;
|
||||||
@ -2531,12 +2541,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
{
|
{
|
||||||
semsg(_(e_listidx), before);
|
semsg(_(e_listidx), before);
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
item = NULL;
|
item = NULL;
|
||||||
|
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
||||||
|
goto theend;
|
||||||
list_extend(l1, l2, item);
|
list_extend(l1, l2, item);
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
@ -2559,7 +2571,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
if (d1 == NULL)
|
if (d1 == NULL)
|
||||||
{
|
{
|
||||||
emsg(_(e_cannot_extend_null_dict));
|
emsg(_(e_cannot_extend_null_dict));
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
d2 = argvars[1].vval.v_dict;
|
d2 = argvars[1].vval.v_dict;
|
||||||
if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
|
if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
|
||||||
@ -2569,7 +2581,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
{
|
{
|
||||||
d1 = dict_copy(d1, FALSE, get_copyID());
|
d1 = dict_copy(d1, FALSE, get_copyID());
|
||||||
if (d1 == NULL)
|
if (d1 == NULL)
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the third argument.
|
// Check the third argument.
|
||||||
@ -2579,19 +2591,21 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
|
|
||||||
action = tv_get_string_chk(&argvars[2]);
|
action = tv_get_string_chk(&argvars[2]);
|
||||||
if (action == NULL)
|
if (action == NULL)
|
||||||
return; // type error; errmsg already given
|
goto theend; // type error; errmsg already given
|
||||||
for (i = 0; i < 3; ++i)
|
for (i = 0; i < 3; ++i)
|
||||||
if (STRCMP(action, av[i]) == 0)
|
if (STRCMP(action, av[i]) == 0)
|
||||||
break;
|
break;
|
||||||
if (i == 3)
|
if (i == 3)
|
||||||
{
|
{
|
||||||
semsg(_(e_invarg2), action);
|
semsg(_(e_invarg2), action);
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
action = (char_u *)"force";
|
action = (char_u *)"force";
|
||||||
|
|
||||||
|
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
||||||
|
goto theend;
|
||||||
dict_extend(d1, d2, action);
|
dict_extend(d1, d2, action);
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
@ -2606,6 +2620,10 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
|
semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
|
||||||
|
|
||||||
|
theend:
|
||||||
|
if (type != NULL)
|
||||||
|
clear_type_list(&type_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -240,19 +240,24 @@ def Test_expand()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_extend_arg_types()
|
def Test_extend_arg_types()
|
||||||
|
g:number_one = 1
|
||||||
|
g:string_keep = 'keep'
|
||||||
|
var lines =<< trim END
|
||||||
assert_equal([1, 2, 3], extend([1, 2], [3]))
|
assert_equal([1, 2, 3], extend([1, 2], [3]))
|
||||||
assert_equal([3, 1, 2], extend([1, 2], [3], 0))
|
assert_equal([3, 1, 2], extend([1, 2], [3], 0))
|
||||||
assert_equal([1, 3, 2], extend([1, 2], [3], 1))
|
assert_equal([1, 3, 2], extend([1, 2], [3], 1))
|
||||||
assert_equal([1, 3, 2], extend([1, 2], [3], s:number_one))
|
assert_equal([1, 3, 2], extend([1, 2], [3], g:number_one))
|
||||||
|
|
||||||
assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
|
assert_equal({a: 1, b: 2, c: 3}, extend({a: 1, b: 2}, {c: 3}))
|
||||||
assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
|
assert_equal({a: 1, b: 4}, extend({a: 1, b: 2}, {b: 4}))
|
||||||
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
|
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, 'keep'))
|
||||||
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, s:string_keep))
|
assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, g:string_keep))
|
||||||
|
|
||||||
var res: list<dict<any>>
|
var res: list<dict<any>>
|
||||||
extend(res, mapnew([1, 2], (_, v) => ({})))
|
extend(res, mapnew([1, 2], (_, v) => ({})))
|
||||||
assert_equal([{}, {}], res)
|
assert_equal([{}, {}], res)
|
||||||
|
END
|
||||||
|
CheckDefAndScriptSuccess(lines)
|
||||||
|
|
||||||
CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list<number> but got number')
|
CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list<number> but got number')
|
||||||
CheckDefFailure(['extend([1, 2], ["x"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
|
CheckDefFailure(['extend([1, 2], ["x"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
|
||||||
@ -300,8 +305,7 @@ def Test_extend_dict_item_type()
|
|||||||
var d: dict<number> = {a: 1}
|
var d: dict<number> = {a: 1}
|
||||||
extend(d, {b: 'x'})
|
extend(d, {b: 'x'})
|
||||||
END
|
END
|
||||||
CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
|
CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
|
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
var d: dict<number> = {a: 1}
|
var d: dict<number> = {a: 1}
|
||||||
@ -326,8 +330,7 @@ def Test_extend_list_item_type()
|
|||||||
var l: list<number> = [1]
|
var l: list<number> = [1]
|
||||||
extend(l, ['x'])
|
extend(l, ['x'])
|
||||||
END
|
END
|
||||||
CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
|
CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 3)
|
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
var l: list<number> = [1]
|
var l: list<number> = [1]
|
||||||
|
@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
2441,
|
||||||
/**/
|
/**/
|
||||||
2440,
|
2440,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user