mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.3221: Vim9: argument types are not checked at compile time (#23480)
Problem: Vim9: argument types are not checked at compile time.
Solution: Add several more type checks. (Yegappan Lakshmanan, closes vim/vim#8632)
a764e73d4f
Cherry-pick test_assert.vim change from patch 8.2.3229.
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
parent
b16729f816
commit
f6299e9d6e
@ -52,6 +52,8 @@ static const char e_list_required_for_argument_nr[]
|
|||||||
= N_("E1211: List required for argument %d");
|
= N_("E1211: List required for argument %d");
|
||||||
static const char e_bool_required_for_argument_nr[]
|
static const char e_bool_required_for_argument_nr[]
|
||||||
= N_("E1212: Bool required for argument %d");
|
= N_("E1212: Bool required for argument %d");
|
||||||
|
static const char e_string_or_number_required_for_argument_nr[]
|
||||||
|
= N_("E1220: String or Number required for argument %d");
|
||||||
static const char e_string_or_list_required_for_argument_nr[]
|
static const char e_string_or_list_required_for_argument_nr[]
|
||||||
= N_("E1222: String or List required for argument %d");
|
= N_("E1222: String or List required for argument %d");
|
||||||
static const char e_list_or_blob_required_for_argument_nr[]
|
static const char e_list_or_blob_required_for_argument_nr[]
|
||||||
@ -4160,6 +4162,17 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
|
|||||||
|| tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
|
|| tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Give an error and return FAIL unless "args[idx]" is a float or a number.
|
||||||
|
int tv_check_for_float_or_nr_arg(const typval_T *const args, const int idx)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
|
{
|
||||||
|
if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER) {
|
||||||
|
semsg(_(e_number_required_for_argument_nr), idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Give an error and return FAIL unless "args[idx]" is a bool.
|
/// Give an error and return FAIL unless "args[idx]" is a bool.
|
||||||
int tv_check_for_bool_arg(const typval_T *const args, const int idx)
|
int tv_check_for_bool_arg(const typval_T *const args, const int idx)
|
||||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
@ -4240,6 +4253,18 @@ int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx)
|
|||||||
|| tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
|
|| tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Give an error and return FAIL unless "args[idx]" is a string or
|
||||||
|
/// a number.
|
||||||
|
int tv_check_for_string_or_number_arg(const typval_T *const args, const int idx)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
|
{
|
||||||
|
if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_NUMBER) {
|
||||||
|
semsg(_(e_string_or_number_required_for_argument_nr), idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Give an error and return FAIL unless "args[idx]" is a string or a list.
|
/// Give an error and return FAIL unless "args[idx]" is a string or a list.
|
||||||
int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
|
int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
|
||||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
@ -4251,6 +4276,14 @@ int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check for an optional string or list argument at 'idx'
|
||||||
|
int tv_check_for_opt_string_or_list_arg(const typval_T *const args, const int idx)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
|
{
|
||||||
|
return (args[idx].v_type == VAR_UNKNOWN
|
||||||
|
|| tv_check_for_string_or_list_arg(args, idx) != FAIL) ? OK : FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/// Give an error and return FAIL unless "args[idx]" is a string
|
/// Give an error and return FAIL unless "args[idx]" is a string
|
||||||
/// or a function reference.
|
/// or a function reference.
|
||||||
int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx)
|
int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx)
|
||||||
|
@ -500,12 +500,23 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
/// "assert_fails(cmd [, error [, msg]])" function
|
/// "assert_fails(cmd [, error [, msg]])" function
|
||||||
void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||||
{
|
{
|
||||||
const char *const cmd = tv_get_string_chk(&argvars[0]);
|
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
int save_trylevel = trylevel;
|
const int save_trylevel = trylevel;
|
||||||
const int called_emsg_before = called_emsg;
|
const int called_emsg_before = called_emsg;
|
||||||
const char *wrong_arg_msg = NULL;
|
const char *wrong_arg_msg = NULL;
|
||||||
|
|
||||||
|
if (tv_check_for_string_or_number_arg(argvars, 0) == FAIL
|
||||||
|
|| tv_check_for_opt_string_or_list_arg(argvars, 1) == FAIL
|
||||||
|
|| (argvars[1].v_type != VAR_UNKNOWN
|
||||||
|
&& (argvars[2].v_type != VAR_UNKNOWN
|
||||||
|
&& (tv_check_for_opt_number_arg(argvars, 3) == FAIL
|
||||||
|
|| (argvars[3].v_type != VAR_UNKNOWN
|
||||||
|
&& tv_check_for_opt_string_arg(argvars, 4) == FAIL))))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *const cmd = tv_get_string_chk(&argvars[0]);
|
||||||
|
|
||||||
// trylevel must be zero for a ":throw" command to be considered failed
|
// trylevel must be zero for a ":throw" command to be considered failed
|
||||||
trylevel = 0;
|
trylevel = 0;
|
||||||
suppress_errthrow = true;
|
suppress_errthrow = true;
|
||||||
@ -682,6 +693,13 @@ static int assert_inrange(typval_T *argvars)
|
|||||||
/// "assert_inrange(lower, upper[, msg])" function
|
/// "assert_inrange(lower, upper[, msg])" function
|
||||||
void f_assert_inrange(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
void f_assert_inrange(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||||
{
|
{
|
||||||
|
if (tv_check_for_float_or_nr_arg(argvars, 0) == FAIL
|
||||||
|
|| tv_check_for_float_or_nr_arg(argvars, 1) == FAIL
|
||||||
|
|| tv_check_for_float_or_nr_arg(argvars, 2) == FAIL
|
||||||
|
|| tv_check_for_opt_string_arg(argvars, 3) == FAIL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rettv->vval.v_number = assert_inrange(argvars);
|
rettv->vval.v_number = assert_inrange(argvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,21 +254,21 @@ func Test_assert_fail_fails()
|
|||||||
catch
|
catch
|
||||||
let exp = v:exception
|
let exp = v:exception
|
||||||
endtry
|
endtry
|
||||||
call assert_match("E856: \"assert_fails()\" second argument", exp)
|
call assert_match("E1222: String or List required for argument 2", exp)
|
||||||
|
|
||||||
try
|
try
|
||||||
call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp'))
|
call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp'))
|
||||||
catch
|
catch
|
||||||
let exp = v:exception
|
let exp = v:exception
|
||||||
endtry
|
endtry
|
||||||
call assert_match("E1115: \"assert_fails()\" fourth argument must be a number", exp)
|
call assert_match("E1210: Number required for argument 4", exp)
|
||||||
|
|
||||||
try
|
try
|
||||||
call assert_equal(1, assert_fails('xxx', 'E492', '', 54, 123))
|
call assert_equal(1, assert_fails('xxx', 'E492', '', 54, 123))
|
||||||
catch
|
catch
|
||||||
let exp = v:exception
|
let exp = v:exception
|
||||||
endtry
|
endtry
|
||||||
call assert_match("E1116: \"assert_fails()\" fifth argument must be a string", exp)
|
call assert_match("E1174: String required for argument 5", exp)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_assert_fails_in_try_block()
|
func Test_assert_fails_in_try_block()
|
||||||
|
Loading…
Reference in New Issue
Block a user