mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.2603: Vim9: no effect if user command is also a function
Problem: Vim9: no effect if user command is also a function. Solution: Check for paren following. (closes #7960)
This commit is contained in:
@@ -2805,12 +2805,15 @@ get_script_local_ht(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Look for "name[len]" in script-local variables and functions.
|
* Look for "name[len]" in script-local variables and functions.
|
||||||
|
* When "cmd" is TRUE it must look like a command, a function must be followed
|
||||||
|
* by "(" or "->".
|
||||||
* Return OK when found, FAIL when not found.
|
* Return OK when found, FAIL when not found.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lookup_scriptitem(
|
lookup_scriptitem(
|
||||||
char_u *name,
|
char_u *name,
|
||||||
size_t len,
|
size_t len,
|
||||||
|
int cmd,
|
||||||
cctx_T *dummy UNUSED)
|
cctx_T *dummy UNUSED)
|
||||||
{
|
{
|
||||||
hashtab_T *ht = get_script_local_ht();
|
hashtab_T *ht = get_script_local_ht();
|
||||||
@@ -2845,12 +2848,18 @@ lookup_scriptitem(
|
|||||||
if (p != buffer)
|
if (p != buffer)
|
||||||
vim_free(p);
|
vim_free(p);
|
||||||
|
|
||||||
|
// Find a function, so that a following "->" works.
|
||||||
|
// When used as a command require "(" or "->" to follow, "Cmd" is a user
|
||||||
|
// command while "Cmd()" is a function call.
|
||||||
if (res != OK)
|
if (res != OK)
|
||||||
{
|
{
|
||||||
// Find a function, so that a following "->" works. Skip "g:" before a
|
p = skipwhite(name + len);
|
||||||
// function name.
|
|
||||||
|
if (!cmd || name[len] == '(' || (p[0] == '-' && p[1] == '>'))
|
||||||
|
{
|
||||||
// Do not check for an internal function, since it might also be a
|
// Do not check for an internal function, since it might also be a
|
||||||
// valid command, such as ":split" versuse "split()".
|
// valid command, such as ":split" versus "split()".
|
||||||
|
// Skip "g:" before a function name.
|
||||||
if (name[0] == 'g' && name[1] == ':')
|
if (name[0] == 'g' && name[1] == ':')
|
||||||
{
|
{
|
||||||
is_global = TRUE;
|
is_global = TRUE;
|
||||||
@@ -2859,6 +2868,7 @@ lookup_scriptitem(
|
|||||||
if (find_func(fname, is_global, NULL) != NULL)
|
if (find_func(fname, is_global, NULL) != NULL)
|
||||||
res = OK;
|
res = OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -3288,7 +3298,7 @@ set_var_const(
|
|||||||
{
|
{
|
||||||
// Item not found, check if a function already exists.
|
// Item not found, check if a function already exists.
|
||||||
if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
|
if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
|
||||||
&& lookup_scriptitem(name, STRLEN(name), NULL) == OK)
|
&& lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
|
||||||
{
|
{
|
||||||
semsg(_(e_redefining_script_item_str), name);
|
semsg(_(e_redefining_script_item_str), name);
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@@ -3311,7 +3311,7 @@ skip_option_env_lead(char_u *start)
|
|||||||
find_ex_command(
|
find_ex_command(
|
||||||
exarg_T *eap,
|
exarg_T *eap,
|
||||||
int *full UNUSED,
|
int *full UNUSED,
|
||||||
int (*lookup)(char_u *, size_t, cctx_T *) UNUSED,
|
int (*lookup)(char_u *, size_t, int cmd, cctx_T *) UNUSED,
|
||||||
cctx_T *cctx UNUSED)
|
cctx_T *cctx UNUSED)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
@@ -3430,7 +3430,7 @@ find_ex_command(
|
|||||||
|| *eap->cmd == '&'
|
|| *eap->cmd == '&'
|
||||||
|| *eap->cmd == '$'
|
|| *eap->cmd == '$'
|
||||||
|| *eap->cmd == '@'
|
|| *eap->cmd == '@'
|
||||||
|| lookup(eap->cmd, p - eap->cmd, cctx) == OK)
|
|| lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK)
|
||||||
{
|
{
|
||||||
eap->cmdidx = CMD_var;
|
eap->cmdidx = CMD_var;
|
||||||
return eap->cmd;
|
return eap->cmd;
|
||||||
@@ -3449,7 +3449,7 @@ find_ex_command(
|
|||||||
// If it is an ID it might be a variable with an operator on the next
|
// If it is an ID it might be a variable with an operator on the next
|
||||||
// line, if the variable exists it can't be an Ex command.
|
// line, if the variable exists it can't be an Ex command.
|
||||||
if (p > eap->cmd && ends_excmd(*skipwhite(p))
|
if (p > eap->cmd && ends_excmd(*skipwhite(p))
|
||||||
&& (lookup(eap->cmd, p - eap->cmd, cctx) == OK
|
&& (lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK
|
||||||
|| (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':')))
|
|| (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':')))
|
||||||
{
|
{
|
||||||
eap->cmdidx = CMD_eval;
|
eap->cmdidx = CMD_eval;
|
||||||
|
@@ -61,7 +61,7 @@ void check_vars(char_u *name, int len);
|
|||||||
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
|
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
|
||||||
dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
|
dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
|
||||||
hashtab_T *get_script_local_ht(void);
|
hashtab_T *get_script_local_ht(void);
|
||||||
int lookup_scriptitem(char_u *name, size_t len, cctx_T *dummy);
|
int lookup_scriptitem(char_u *name, size_t len, int cmd, cctx_T *dummy);
|
||||||
hashtab_T *find_var_ht(char_u *name, char_u **varname);
|
hashtab_T *find_var_ht(char_u *name, char_u **varname);
|
||||||
char_u *get_var_value(char_u *name);
|
char_u *get_var_value(char_u *name);
|
||||||
void new_script_vars(scid_T id);
|
void new_script_vars(scid_T id);
|
||||||
|
@@ -13,7 +13,7 @@ void undo_cmdmod(cmdmod_T *cmod);
|
|||||||
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
|
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
|
||||||
int checkforcmd(char_u **pp, char *cmd, int len);
|
int checkforcmd(char_u **pp, char *cmd, int len);
|
||||||
char_u *skip_option_env_lead(char_u *start);
|
char_u *skip_option_env_lead(char_u *start);
|
||||||
char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, cctx_T *), cctx_T *cctx);
|
char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, int cmd, cctx_T *), cctx_T *cctx);
|
||||||
int modifier_len(char_u *cmd);
|
int modifier_len(char_u *cmd);
|
||||||
int cmd_exists(char_u *name);
|
int cmd_exists(char_u *name);
|
||||||
void f_fullcommand(typval_T *argvars, typval_T *rettv);
|
void f_fullcommand(typval_T *argvars, typval_T *rettv);
|
||||||
|
@@ -364,8 +364,7 @@ def Test_method_call_linebreak()
|
|||||||
return F()
|
return F()
|
||||||
enddef
|
enddef
|
||||||
def Test()
|
def Test()
|
||||||
Foo
|
Foo ->Bar()
|
||||||
->Bar()
|
|
||||||
->setline(1)
|
->setline(1)
|
||||||
enddef
|
enddef
|
||||||
Test()
|
Test()
|
||||||
@@ -401,8 +400,7 @@ def Test_method_call_linebreak()
|
|||||||
return F()
|
return F()
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
Foo
|
Foo->Bar()
|
||||||
->Bar()
|
|
||||||
->setline(1)
|
->setline(1)
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
CheckScriptSuccess(lines)
|
||||||
@@ -424,6 +422,33 @@ def Test_method_call_whitespace()
|
|||||||
CheckDefAndScriptSuccess(lines)
|
CheckDefAndScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_method_and_user_command()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Cmd()
|
||||||
|
g:didFunc = 1
|
||||||
|
enddef
|
||||||
|
command Cmd g:didCmd = 1
|
||||||
|
Cmd
|
||||||
|
assert_equal(1, g:didCmd)
|
||||||
|
Cmd()
|
||||||
|
assert_equal(1, g:didFunc)
|
||||||
|
unlet g:didFunc
|
||||||
|
unlet g:didCmd
|
||||||
|
|
||||||
|
def InDefFunc()
|
||||||
|
Cmd
|
||||||
|
assert_equal(1, g:didCmd)
|
||||||
|
Cmd()
|
||||||
|
assert_equal(1, g:didFunc)
|
||||||
|
unlet g:didFunc
|
||||||
|
unlet g:didCmd
|
||||||
|
enddef
|
||||||
|
InDefFunc()
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_skipped_expr_linebreak()
|
def Test_skipped_expr_linebreak()
|
||||||
if 0
|
if 0
|
||||||
var x = []
|
var x = []
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
2603,
|
||||||
/**/
|
/**/
|
||||||
2602,
|
2602,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -391,19 +391,29 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
|
|||||||
* imported or function.
|
* imported or function.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
item_exists(char_u *name, size_t len, cctx_T *cctx)
|
item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
int is_global;
|
int is_global;
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
if (variable_exists(name, len, cctx))
|
if (variable_exists(name, len, cctx))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
// Find a function, so that a following "->" works. Skip "g:" before a
|
// This is similar to what is in lookup_scriptitem():
|
||||||
// function name.
|
// Find a function, so that a following "->" works.
|
||||||
|
// Require "(" or "->" to follow, "Cmd" is a user command while "Cmd()" is
|
||||||
|
// a function call.
|
||||||
|
p = skipwhite(name + len);
|
||||||
|
|
||||||
|
if (name[len] == '(' || (p[0] == '-' && p[1] == '>'))
|
||||||
|
{
|
||||||
// Do not check for an internal function, since it might also be a
|
// Do not check for an internal function, since it might also be a
|
||||||
// valid command, such as ":split" versuse "split()".
|
// valid command, such as ":split" versuse "split()".
|
||||||
|
// Skip "g:" before a function name.
|
||||||
is_global = (name[0] == 'g' && name[1] == ':');
|
is_global = (name[0] == 'g' && name[1] == ':');
|
||||||
return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
|
return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -8429,8 +8439,8 @@ compile_def_function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
|
p = find_ex_command(&ea, NULL, starts_with_colon
|
||||||
: (int (*)(char_u *, size_t, cctx_T *))item_exists, &cctx);
|
? NULL : item_exists, &cctx);
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user