summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-01-16 19:38:07 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-16 19:38:07 +0000
commitc665dabdf4c49a0fbf1dc566253c75c2abe2effa (patch)
tree3f55d76cf3fed62974742d4739836cc3cb554d09 /src/eval.c
parentc84287d6d8dd055bb6e30605465a23a8addb6fde (diff)
downloadvim-git-c665dabdf4c49a0fbf1dc566253c75c2abe2effa.tar.gz
patch 8.2.4115: cannot use a method with a complex expressionv8.2.4115
Problem: Cannot use a method with a complex expression. Solution: Evaluate the expression after "->" and use the result.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c101
1 files changed, 52 insertions, 49 deletions
diff --git a/src/eval.c b/src/eval.c
index 935f19aa7..c8907defd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3948,6 +3948,7 @@ eval_method(
char_u *name;
long len;
char_u *alias;
+ char_u *tofree = NULL;
typval_T base = *rettv;
int ret = OK;
int evaluate = evalarg != NULL
@@ -3968,67 +3969,68 @@ eval_method(
}
else
{
- if (**arg == '.')
+ char_u *paren;
+
+ // If there is no "(" immediately following, but there is further on,
+ // it can be "import.Func()", "dict.Func()", "list[nr]", etc.
+ // Does not handle anything where "(" is part of the expression.
+ *arg = skipwhite(*arg);
+
+ if (**arg != '(' && alias == NULL
+ && (paren = vim_strchr(*arg, '(')) != NULL)
{
- int len2;
- char_u *fname;
- int idx;
- imported_T *import = find_imported(name, len, TRUE,
- evalarg == NULL ? NULL : evalarg->eval_cctx);
- type_T *type;
+ typval_T ref;
- // value->import.func()
- if (import != NULL)
+ *arg = name;
+ *paren = NUL;
+ ref.v_type = VAR_UNKNOWN;
+ if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
{
- name = NULL;
- ++*arg;
- fname = *arg;
- len2 = get_name_len(arg, &alias, evaluate, TRUE);
- if (len2 <= 0)
+ *arg = name + len;
+ ret = FAIL;
+ }
+ else if (*skipwhite(*arg) != NUL)
+ {
+ if (verbose)
+ semsg(_(e_trailing_characters_str), *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 = 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_missing_name_after_dot));
+ emsg(_(e_cannot_use_partial_here));
ret = FAIL;
}
- else if (evaluate)
+ else
{
- int cc = fname[len2];
- ufunc_T *ufunc;
-
- fname[len2] = NUL;
- idx = find_exported(import->imp_sid, fname, &ufunc, &type,
- evalarg->eval_cctx, verbose);
- fname[len2] = cc;
-
- if (idx >= 0)
+ name = vim_strsave(partial_name(ref.vval.v_partial));
+ tofree = name;
+ if (name == NULL)
{
- scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
- svar_T *sv =
- ((svar_T *)si->sn_var_vals.ga_data) + idx;
-
- if (sv->sv_tv->v_type == VAR_FUNC
- && sv->sv_tv->vval.v_string != NULL)
- {
- name = sv->sv_tv->vval.v_string;
- len = STRLEN(name);
- }
- else
- {
- // TODO: how about a partial?
- if (verbose)
- semsg(_(e_not_callable_type_str), fname);
- ret = FAIL;
- }
- }
- else if (ufunc != NULL)
- {
- name = ufunc->uf_name;
- len = STRLEN(name);
+ ret = FAIL;
+ name = *arg;
}
else
- ret = FAIL;
+ len = STRLEN(name);
}
}
+ else
+ {
+ if (verbose)
+ semsg(_(e_not_callable_type_str), name);
+ ret = FAIL;
+ }
+ clear_tv(&ref);
+ *paren = '(';
}
if (ret == OK)
@@ -4057,6 +4059,7 @@ eval_method(
// evaluating the arguments is possible (see test55).
if (evaluate)
clear_tv(&base);
+ vim_free(tofree);
return ret;
}