0
0
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:
Bram Moolenaar
2021-03-14 13:21:35 +01:00
parent 2e34c34be1
commit 77b10ffad4
7 changed files with 76 additions and 29 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 = []

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2603,
/**/
2602,
/**/

View File

@@ -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)
{