mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:7.4.2134
Problem: No error for using function() badly.
Solution: Check for passing wrong function name. (Ken Takata)
b54c3ff317
This commit is contained in:
parent
d7c798cd86
commit
1e3c0efa0f
@ -200,14 +200,15 @@ static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
|
|||||||
|
|
||||||
static int echo_attr = 0; /* attributes used for ":echo" */
|
static int echo_attr = 0; /* attributes used for ":echo" */
|
||||||
|
|
||||||
/* Values for trans_function_name() argument: */
|
// Values for trans_function_name() argument:
|
||||||
#define TFN_INT 1 /* internal function name OK */
|
#define TFN_INT 1 // internal function name OK
|
||||||
#define TFN_QUIET 2 /* no error messages */
|
#define TFN_QUIET 2 // no error messages
|
||||||
#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */
|
#define TFN_NO_AUTOLOAD 4 // do not use script autoloading
|
||||||
|
#define TFN_NO_DEREF 8 // do not dereference a Funcref
|
||||||
|
|
||||||
/* Values for get_lval() flags argument: */
|
// Values for get_lval() flags argument:
|
||||||
#define GLV_QUIET TFN_QUIET /* no error messages */
|
#define GLV_QUIET TFN_QUIET // no error messages
|
||||||
#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */
|
#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD // do not use script autoloading
|
||||||
|
|
||||||
// function flags
|
// function flags
|
||||||
#define FC_ABORT 1 // abort function on error
|
#define FC_ABORT 1 // abort function on error
|
||||||
@ -7018,7 +7019,8 @@ err_ret:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a lambda expression and get a Funcref from "*arg".
|
/// Parse a lambda expression and get a Funcref from "*arg".
|
||||||
/// Return OK or FAIL. Returns NOTDONE for dict or {expr}.
|
///
|
||||||
|
/// @return OK or FAIL. Returns NOTDONE for dict or {expr}.
|
||||||
static int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
|
static int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||||
{
|
{
|
||||||
garray_T newargs;
|
garray_T newargs;
|
||||||
@ -7056,7 +7058,7 @@ static int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
|
|||||||
goto errret;
|
goto errret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up dictionaries for checking local variables and arguments.
|
// Set up a flag for checking local variables and arguments.
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
eval_lavars_used = &eval_lavars;
|
eval_lavars_used = &eval_lavars;
|
||||||
}
|
}
|
||||||
@ -9242,12 +9244,13 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
n = TRUE;
|
n = TRUE;
|
||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
} else if (*p == '&' || *p == '+') { /* option */
|
} else if (*p == '&' || *p == '+') { // option
|
||||||
n = (get_option_tv(&p, NULL, TRUE) == OK);
|
n = (get_option_tv(&p, NULL, true) == OK);
|
||||||
if (*skipwhite(p) != NUL)
|
if (*skipwhite(p) != NUL) {
|
||||||
n = FALSE; /* trailing garbage */
|
n = false; // trailing garbage
|
||||||
} else if (*p == '*') { /* internal or user defined function */
|
}
|
||||||
n = function_exists(p + 1);
|
} else if (*p == '*') { // internal or user defined function
|
||||||
|
n = function_exists(p + 1, false);
|
||||||
} else if (*p == ':') {
|
} else if (*p == ':') {
|
||||||
n = cmd_exists(p + 1);
|
n = cmd_exists(p + 1);
|
||||||
} else if (*p == '#') {
|
} else if (*p == '#') {
|
||||||
@ -10019,7 +10022,7 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s))) {
|
if (s == NULL || *s == NUL || (use_string && ascii_isdigit(*s))) {
|
||||||
EMSG2(_(e_invarg2), s);
|
EMSG2(_(e_invarg2), s);
|
||||||
} else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
|
} else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
|
||||||
&& !function_exists(s)) {
|
&& !function_exists(s, true)) {
|
||||||
// Don't check an autoload name for existence here.
|
// Don't check an autoload name for existence here.
|
||||||
EMSG2(_("E700: Unknown function: %s"), s);
|
EMSG2(_("E700: Unknown function: %s"), s);
|
||||||
} else {
|
} else {
|
||||||
@ -20457,10 +20460,10 @@ var_check_func_name (
|
|||||||
EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
|
EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
/* Don't allow hiding a function. When "v" is not NULL we might be
|
// Don't allow hiding a function. When "v" is not NULL we might be
|
||||||
* assigning another function to the same var, the type is checked
|
// assigning another function to the same var, the type is checked
|
||||||
* below. */
|
// below.
|
||||||
if (new_var && function_exists(name)) {
|
if (new_var && function_exists(name, false)) {
|
||||||
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
|
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
|
||||||
name);
|
name);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -21397,16 +21400,16 @@ ret_free:
|
|||||||
need_wait_return |= saved_wait_return;
|
need_wait_return |= saved_wait_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Get a function name, translating "<SID>" and "<SNR>".
|
||||||
* Get a function name, translating "<SID>" and "<SNR>".
|
/// Also handles a Funcref in a List or Dictionary.
|
||||||
* Also handles a Funcref in a List or Dictionary.
|
/// flags:
|
||||||
* Returns the function name in allocated memory, or NULL for failure.
|
/// TFN_INT: internal function name OK
|
||||||
* flags:
|
/// TFN_QUIET: be quiet
|
||||||
* TFN_INT: internal function name OK
|
/// TFN_NO_AUTOLOAD: do not use script autoloading
|
||||||
* TFN_QUIET: be quiet
|
/// TFN_NO_DEREF: do not dereference a Funcref
|
||||||
* TFN_NO_AUTOLOAD: do not use script autoloading
|
/// Advances "pp" to just after the function name (if no error).
|
||||||
* Advances "pp" to just after the function name (if no error).
|
///
|
||||||
*/
|
/// @return the function name in allocated memory, or NULL for failure.
|
||||||
static char_u *
|
static char_u *
|
||||||
trans_function_name (
|
trans_function_name (
|
||||||
char_u **pp,
|
char_u **pp,
|
||||||
@ -21509,7 +21512,7 @@ trans_function_name (
|
|||||||
if (name == lv.ll_exp_name) {
|
if (name == lv.ll_exp_name) {
|
||||||
name = NULL;
|
name = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!(flags & TFN_NO_DEREF)) {
|
||||||
len = (int)(end - *pp);
|
len = (int)(end - *pp);
|
||||||
name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
|
name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
|
||||||
if (name == *pp) {
|
if (name == *pp) {
|
||||||
@ -21572,7 +21575,7 @@ trans_function_name (
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skip && !(flags & TFN_QUIET)) {
|
if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF)) {
|
||||||
char_u *cp = vim_strchr(lv.ll_name, ':');
|
char_u *cp = vim_strchr(lv.ll_name, ':');
|
||||||
|
|
||||||
if (cp != NULL && cp < end) {
|
if (cp != NULL && cp < end) {
|
||||||
@ -21709,17 +21712,23 @@ int translated_function_exists(char_u *name)
|
|||||||
return find_func(name) != NULL;
|
return find_func(name) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Check if a function exists by name
|
||||||
* Return TRUE if a function "name" exists.
|
///
|
||||||
*/
|
/// @param[in] name The name of the function to check.
|
||||||
static int function_exists(char_u *name)
|
/// @param[in] no_deref If true, do not dereference a Funcref.
|
||||||
|
///
|
||||||
|
/// @return true if a function "name" exists.
|
||||||
|
static int function_exists(char_u *name, bool no_deref)
|
||||||
{
|
{
|
||||||
char_u *nm = name;
|
char_u *nm = name;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int n = FALSE;
|
int n = false;
|
||||||
|
int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
|
||||||
|
|
||||||
p = trans_function_name(&nm, false, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
|
if (no_deref) {
|
||||||
NULL, NULL);
|
flag |= TFN_NO_DEREF;
|
||||||
|
}
|
||||||
|
p = trans_function_name(&nm, false, flag, NULL, NULL);
|
||||||
nm = skipwhite(nm);
|
nm = skipwhite(nm);
|
||||||
|
|
||||||
/* Only accept "funcname", "funcname ", "funcname (..." and
|
/* Only accept "funcname", "funcname ", "funcname (..." and
|
||||||
@ -21730,9 +21739,13 @@ static int function_exists(char_u *name)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return TRUE if "name" looks like a builtin function name: starts with a
|
/// Checks if a builtin function with the given name exists.
|
||||||
|
///
|
||||||
|
/// @param[in] name The name of the builtin function to check.
|
||||||
|
/// @param[in] len The length of "name", or -1 for NUL terminated.
|
||||||
|
///
|
||||||
|
/// @return true if "name" looks like a builtin function name: starts with a
|
||||||
/// lower case letter and doesn't contain AUTOLOAD_CHAR.
|
/// lower case letter and doesn't contain AUTOLOAD_CHAR.
|
||||||
/// "len" is the length of "name", or -1 for NUL terminated.
|
|
||||||
static bool builtin_function(char_u *name, int len)
|
static bool builtin_function(char_u *name, int len)
|
||||||
{
|
{
|
||||||
if (!ASCII_ISLOWER(name[0])) {
|
if (!ASCII_ISLOWER(name[0])) {
|
||||||
|
@ -143,3 +143,10 @@ func Test_substitute_expr_arg()
|
|||||||
call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:')
|
call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:')
|
||||||
call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:')
|
call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_function_with_funcref()
|
||||||
|
let s:f = function('type')
|
||||||
|
let s:fref = function(s:f)
|
||||||
|
call assert_equal(v:t_string, s:fref('x'))
|
||||||
|
call assert_fails("call function('s:f')", 'E700:')
|
||||||
|
endfunc
|
||||||
|
@ -306,7 +306,7 @@ static int included_patches[] = {
|
|||||||
// 2137,
|
// 2137,
|
||||||
// 2136,
|
// 2136,
|
||||||
// 2135,
|
// 2135,
|
||||||
// 2134,
|
2134,
|
||||||
// 2133 NA
|
// 2133 NA
|
||||||
// 2132 NA
|
// 2132 NA
|
||||||
// 2131 NA
|
// 2131 NA
|
||||||
|
Loading…
Reference in New Issue
Block a user