aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-07-30 13:54:32 +0800
committerzeertzjq <zeertzjq@outlook.com>2024-07-31 10:49:57 +0800
commit5463b5c9e1ffa753746e7babd7e985f3efac05e3 (patch)
treeafee1b9e30f4d94e24278f7935f1b02301e4d3d7 /src/nvim/eval.c
parent98d05a2dee7b90d7c23a47bc4d96e257c3a3d31e (diff)
downloadrneovim-5463b5c9e1ffa753746e7babd7e985f3efac05e3.tar.gz
rneovim-5463b5c9e1ffa753746e7babd7e985f3efac05e3.tar.bz2
rneovim-5463b5c9e1ffa753746e7babd7e985f3efac05e3.zip
vim-patch:8.2.4115: cannot use a method with a complex expression
Problem: Cannot use a method with a complex expression. Solution: Evaluate the expression after "->" and use the result. https://github.com/vim/vim/commit/c665dabdf4c49a0fbf1dc566253c75c2abe2effa Cherry-pick a "verbose" check from patch 8.2.4123. N/A patches for version.c: vim-patch:8.2.4102: Vim9: import cannot be used after method vim-patch:8.2.4110: Coverity warns for using NULL pointer Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c97
1 files changed, 78 insertions, 19 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b084328f77..6bd117c5b2 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -122,6 +122,8 @@ static const char e_empty_function_name[]
= N_("E1192: Empty function name");
static const char e_argument_of_str_must_be_list_string_dictionary_or_blob[]
= N_("E1250: Argument of %s must be a List, String, Dictionary or Blob");
+static const char e_cannot_use_partial_here[]
+ = N_("E1265: Cannot use a partial here");
static char * const namespace_char = "abglstvw";
@@ -3488,20 +3490,22 @@ static int eval_method(char **const arg, typval_T *const rettv, evalarg_T *const
int len;
char *name = *arg;
char *lua_funcname = NULL;
+ char *alias = NULL;
if (strnequal(name, "v:lua.", 6)) {
lua_funcname = name + 6;
*arg = (char *)skip_luafunc_name(lua_funcname);
*arg = skipwhite(*arg); // to detect trailing whitespace later
len = (int)(*arg - lua_funcname);
} else {
- char *alias;
len = get_name_len((const char **)arg, &alias, evaluate, true);
if (alias != NULL) {
name = alias;
}
}
- int ret;
+ char *tofree = NULL;
+ int ret = OK;
+
if (len <= 0) {
if (verbose) {
if (lua_funcname == NULL) {
@@ -3512,25 +3516,79 @@ static int eval_method(char **const arg, typval_T *const rettv, evalarg_T *const
}
ret = FAIL;
} else {
- if (**arg != '(') {
- if (verbose) {
- semsg(_(e_missingparen), name);
- }
- ret = FAIL;
- } else if (ascii_iswhite((*arg)[-1])) {
- if (verbose) {
- emsg(_(e_nowhitespace));
+ *arg = skipwhite(*arg);
+
+ // If there is no "(" immediately following, but there is further on,
+ // it can be "dict.Func()", "list[nr]", etc.
+ // Does not handle anything where "(" is part of the expression.
+ char *paren;
+ if (**arg != '(' && lua_funcname == NULL && alias == NULL
+ && (paren = vim_strchr(*arg, '(')) != NULL) {
+ *arg = name;
+ *paren = NUL;
+ typval_T ref;
+ ref.v_type = VAR_UNKNOWN;
+ if (eval7(arg, &ref, evalarg, false) == FAIL) {
+ *arg = name + len;
+ ret = FAIL;
+ } else if (*skipwhite(*arg) != NUL) {
+ if (verbose) {
+ semsg(_(e_trailing_arg), *arg);
+ }
+ ret = FAIL;
+ } else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL) {
+ name = ref.vval.v_string;
+ ref.vval.v_string = NULL;
+ tofree = name;
+ len = (int)strlen(name);
+ } else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL) {
+ if (ref.vval.v_partial->pt_argc > 0 || ref.vval.v_partial->pt_dict != NULL) {
+ if (verbose) {
+ emsg(_(e_cannot_use_partial_here));
+ }
+ ret = FAIL;
+ } else {
+ name = xstrdup(partial_name(ref.vval.v_partial));
+ tofree = name;
+ if (name == NULL) {
+ ret = FAIL;
+ name = *arg;
+ } else {
+ len = (int)strlen(name);
+ }
+ }
+ } else {
+ if (verbose) {
+ semsg(_(e_not_callable_type_str), name);
+ }
+ ret = FAIL;
}
- ret = FAIL;
- } else if (lua_funcname != NULL) {
- if (evaluate) {
- rettv->v_type = VAR_PARTIAL;
- rettv->vval.v_partial = vvlua_partial;
- rettv->vval.v_partial->pt_refcount++;
+ tv_clear(&ref);
+ *paren = '(';
+ }
+
+ if (ret == OK) {
+ if (**arg != '(') {
+ if (verbose) {
+ semsg(_(e_missingparen), name);
+ }
+ ret = FAIL;
+ } else if (ascii_iswhite((*arg)[-1])) {
+ if (verbose) {
+ emsg(_(e_nowhitespace));
+ }
+ ret = FAIL;
+ } else if (lua_funcname != NULL) {
+ if (evaluate) {
+ rettv->v_type = VAR_PARTIAL;
+ rettv->vval.v_partial = vvlua_partial;
+ rettv->vval.v_partial->pt_refcount++;
+ }
+ ret = call_func_rettv(arg, evalarg, rettv, evaluate, NULL, &base, lua_funcname);
+ } else {
+ ret = eval_func(arg, evalarg, name, len, rettv,
+ evaluate ? EVAL_EVALUATE : 0, &base);
}
- ret = call_func_rettv(arg, evalarg, rettv, evaluate, NULL, &base, lua_funcname);
- } else {
- ret = eval_func(arg, evalarg, name, len, rettv, evaluate ? EVAL_EVALUATE : 0, &base);
}
}
@@ -3539,6 +3597,7 @@ static int eval_method(char **const arg, typval_T *const rettv, evalarg_T *const
if (evaluate) {
tv_clear(&base);
}
+ xfree(tofree);
return ret;
}