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.
|
||||
* 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.
|
||||
*/
|
||||
int
|
||||
lookup_scriptitem(
|
||||
char_u *name,
|
||||
size_t len,
|
||||
int cmd,
|
||||
cctx_T *dummy UNUSED)
|
||||
{
|
||||
hashtab_T *ht = get_script_local_ht();
|
||||
@@ -2845,12 +2848,18 @@ lookup_scriptitem(
|
||||
if (p != buffer)
|
||||
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)
|
||||
{
|
||||
// Find a function, so that a following "->" works. Skip "g:" before a
|
||||
// function name.
|
||||
p = skipwhite(name + len);
|
||||
|
||||
if (!cmd || name[len] == '(' || (p[0] == '-' && p[1] == '>'))
|
||||
{
|
||||
// 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] == ':')
|
||||
{
|
||||
is_global = TRUE;
|
||||
@@ -2859,6 +2868,7 @@ lookup_scriptitem(
|
||||
if (find_func(fname, is_global, NULL) != NULL)
|
||||
res = OK;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -3288,7 +3298,7 @@ set_var_const(
|
||||
{
|
||||
// Item not found, check if a function already exists.
|
||||
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);
|
||||
goto failed;
|
||||
|
@@ -3311,7 +3311,7 @@ skip_option_env_lead(char_u *start)
|
||||
find_ex_command(
|
||||
exarg_T *eap,
|
||||
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)
|
||||
{
|
||||
int len;
|
||||
@@ -3430,7 +3430,7 @@ find_ex_command(
|
||||
|| *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;
|
||||
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
|
||||
// line, if the variable exists it can't be an Ex command.
|
||||
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] == ':')))
|
||||
{
|
||||
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_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
|
||||
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);
|
||||
char_u *get_var_value(char_u *name);
|
||||
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 checkforcmd(char_u **pp, char *cmd, int len);
|
||||
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 cmd_exists(char_u *name);
|
||||
void f_fullcommand(typval_T *argvars, typval_T *rettv);
|
||||
|
@@ -364,8 +364,7 @@ def Test_method_call_linebreak()
|
||||
return F()
|
||||
enddef
|
||||
def Test()
|
||||
Foo
|
||||
->Bar()
|
||||
Foo ->Bar()
|
||||
->setline(1)
|
||||
enddef
|
||||
Test()
|
||||
@@ -401,8 +400,7 @@ def Test_method_call_linebreak()
|
||||
return F()
|
||||
enddef
|
||||
|
||||
Foo
|
||||
->Bar()
|
||||
Foo->Bar()
|
||||
->setline(1)
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
@@ -424,6 +422,33 @@ def Test_method_call_whitespace()
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
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()
|
||||
if 0
|
||||
var x = []
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2603,
|
||||
/**/
|
||||
2602,
|
||||
/**/
|
||||
|
@@ -391,19 +391,29 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
|
||||
* imported or function.
|
||||
*/
|
||||
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;
|
||||
char_u *p;
|
||||
|
||||
if (variable_exists(name, len, cctx))
|
||||
return TRUE;
|
||||
|
||||
// Find a function, so that a following "->" works. Skip "g:" before a
|
||||
// function name.
|
||||
// This is similar to what is in lookup_scriptitem():
|
||||
// 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
|
||||
// valid command, such as ":split" versuse "split()".
|
||||
// Skip "g:" before a function name.
|
||||
is_global = (name[0] == 'g' && name[1] == ':');
|
||||
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
|
||||
: (int (*)(char_u *, size_t, cctx_T *))item_exists, &cctx);
|
||||
p = find_ex_command(&ea, NULL, starts_with_colon
|
||||
? NULL : item_exists, &cctx);
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
|
Reference in New Issue
Block a user