Patch 8.2.2603
Problem: Vim9: no effect if user command is also a function.
Solution: Check for paren following. (closes #7960)
Files: src/evalvars.c, src/proto/evalvars.pro, src/ex_docmd.c,
src/proto/ex_docmd.pro, src/vim9compile.c,
src/testdir/test_vim9_cmd.vim
*** ../vim-8.2.2602/src/evalvars.c 2021-03-13 20:57:15.855515074 +0100
--- src/evalvars.c 2021-03-14 13:21:05.809109446 +0100
***************
*** 2805,2816 ****
--- 2805,2819 ----
/*
* 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,2863 ****
if (p != buffer)
vim_free(p);
if (res != OK)
{
! // Find a function, so that a following "->" works. Skip "g:" before a
! // function name.
! // Do not check for an internal function, since it might also be a
! // valid command, such as ":split" versuse "split()".
! if (name[0] == 'g' && name[1] == ':')
{
! is_global = TRUE;
! fname = name + 2;
}
- if (find_func(fname, is_global, NULL) != NULL)
- res = OK;
}
return res;
--- 2848,2873 ----
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)
{
! 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" versus "split()".
! // Skip "g:" before a function name.
! if (name[0] == 'g' && name[1] == ':')
! {
! is_global = TRUE;
! fname = name + 2;
! }
! if (find_func(fname, is_global, NULL) != NULL)
! res = OK;
}
}
return res;
***************
*** 3288,3294 ****
{
// 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)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
--- 3298,3304 ----
{
// 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), FALSE, NULL) == OK)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
*** ../vim-8.2.2602/src/proto/evalvars.pro 2021-03-13 20:57:15.855515074
+0100
--- src/proto/evalvars.pro 2021-03-14 12:35:30.444537708 +0100
***************
*** 61,67 ****
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);
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);
--- 61,67 ----
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, 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);
*** ../vim-8.2.2602/src/ex_docmd.c 2021-03-13 21:07:17.742458250 +0100
--- src/ex_docmd.c 2021-03-14 12:32:04.745121747 +0100
***************
*** 3311,3317 ****
find_ex_command(
exarg_T *eap,
int *full UNUSED,
! int (*lookup)(char_u *, size_t, cctx_T *) UNUSED,
cctx_T *cctx UNUSED)
{
int len;
--- 3311,3317 ----
find_ex_command(
exarg_T *eap,
int *full UNUSED,
! int (*lookup)(char_u *, size_t, int cmd, cctx_T *) UNUSED,
cctx_T *cctx UNUSED)
{
int len;
***************
*** 3430,3436 ****
|| *eap->cmd == '&'
|| *eap->cmd == '$'
|| *eap->cmd == '@'
! || lookup(eap->cmd, p - eap->cmd, cctx) == OK)
{
eap->cmdidx = CMD_var;
return eap->cmd;
--- 3430,3436 ----
|| *eap->cmd == '&'
|| *eap->cmd == '$'
|| *eap->cmd == '@'
! || lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK)
{
eap->cmdidx = CMD_var;
return eap->cmd;
***************
*** 3449,3455 ****
// 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
|| (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':')))
{
eap->cmdidx = CMD_eval;
--- 3449,3455 ----
// 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, TRUE, cctx) == OK
|| (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':')))
{
eap->cmdidx = CMD_eval;
*** ../vim-8.2.2602/src/proto/ex_docmd.pro 2021-02-17 14:52:10.539374448
+0100
--- src/proto/ex_docmd.pro 2021-03-14 12:36:15.644409316 +0100
***************
*** 13,19 ****
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);
int modifier_len(char_u *cmd);
int cmd_exists(char_u *name);
void f_fullcommand(typval_T *argvars, typval_T *rettv);
--- 13,19 ----
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, 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);
*** ../vim-8.2.2602/src/vim9compile.c 2021-03-13 21:14:15.165663825 +0100
--- src/vim9compile.c 2021-03-14 12:52:30.129640837 +0100
***************
*** 391,409 ****
* imported or function.
*/
static int
! item_exists(char_u *name, size_t len, cctx_T *cctx)
{
int is_global;
if (variable_exists(name, len, cctx))
return TRUE;
! // Find a function, so that a following "->" works. Skip "g:" before a
! // function name.
! // Do not check for an internal function, since it might also be a
! // valid command, such as ":split" versuse "split()".
! is_global = (name[0] == 'g' && name[1] == ':');
! return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
}
/*
--- 391,419 ----
* imported or function.
*/
static int
! 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;
! // 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,8436 ****
}
}
}
! p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
! : (int (*)(char_u *, size_t, cctx_T *))item_exists, &cctx);
if (p == NULL)
{
--- 8439,8446 ----
}
}
}
! p = find_ex_command(&ea, NULL, starts_with_colon
! ? NULL : item_exists, &cctx);
if (p == NULL)
{
*** ../vim-8.2.2602/src/testdir/test_vim9_cmd.vim 2021-03-06
21:01:05.865089577 +0100
--- src/testdir/test_vim9_cmd.vim 2021-03-14 13:03:28.750325986 +0100
***************
*** 364,372 ****
return F()
enddef
def Test()
! Foo
! ->Bar()
! ->setline(1)
enddef
Test()
assert_equal('the text', getline(1))
--- 364,371 ----
return F()
enddef
def Test()
! Foo ->Bar()
! ->setline(1)
enddef
Test()
assert_equal('the text', getline(1))
***************
*** 401,408 ****
return F()
enddef
! Foo
! ->Bar()
->setline(1)
END
CheckScriptSuccess(lines)
--- 400,406 ----
return F()
enddef
! Foo->Bar()
->setline(1)
END
CheckScriptSuccess(lines)
***************
*** 424,429 ****
--- 422,454 ----
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 = []
*** ../vim-8.2.2602/src/version.c 2021-03-14 12:13:30.192279488 +0100
--- src/version.c 2021-03-14 12:27:38.717876588 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2603,
/**/
--
Are leaders born or made? And if they're made, can we return them under
warranty?
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202103141222.12ECM1Mf220199%40masaka.moolenaar.net.