diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-01-16 19:38:07 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-01-16 19:38:07 +0000 |
commit | c665dabdf4c49a0fbf1dc566253c75c2abe2effa (patch) | |
tree | 3f55d76cf3fed62974742d4739836cc3cb554d09 /src/eval.c | |
parent | c84287d6d8dd055bb6e30605465a23a8addb6fde (diff) | |
download | vim-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.c | 101 |
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; } |