From 857c8bb1bbe754cf2c5b709703d2eb848c800285 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 15 Jan 2022 21:08:19 +0000 Subject: [PATCH] patch 8.2.4102: Vim9: import cannot be used after method Problem: Vim9: import cannot be used after method. Solution: Recognize an imported function name. (closes #9496) --- src/eval.c | 91 +++++++++++++++++++++++++++----- src/testdir/test_vim9_import.vim | 7 +++ src/version.c | 2 + 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/src/eval.c b/src/eval.c index 08804c092..5588abd02 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3949,7 +3949,7 @@ eval_method( long len; char_u *alias; typval_T base = *rettv; - int ret; + int ret = OK; int evaluate = evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE); @@ -3968,22 +3968,87 @@ eval_method( } else { - *arg = skipwhite(*arg); - if (**arg != '(') + if (**arg == '.') { - if (verbose) - semsg(_(e_missing_parenthesis_str), name); - ret = FAIL; + int len2; + char_u *fname; + int idx; + imported_T *import = find_imported(name, len, + TRUE, evalarg->eval_cctx); + type_T *type; + + // value->import.func() + if (import != NULL) + { + name = NULL; + ++*arg; + fname = *arg; + len2 = get_name_len(arg, &alias, evaluate, TRUE); + if (len2 <= 0) + { + emsg(_(e_missing_name_after_dot)); + ret = FAIL; + } + 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) + { + 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? + semsg(_(e_not_callable_type_str), fname); + ret = FAIL; + } + } + else if (ufunc != NULL) + { + name = ufunc->uf_name; + len = STRLEN(name); + } + else + ret = FAIL; + } + } } - else if (VIM_ISWHITE((*arg)[-1])) + + if (ret == OK) { - if (verbose) - emsg(_(e_no_white_space_allowed_before_parenthesis)); - ret = FAIL; - } - else - ret = eval_func(arg, evalarg, name, len, rettv, + *arg = skipwhite(*arg); + + if (**arg != '(') + { + if (verbose) + semsg(_(e_missing_parenthesis_str), name); + ret = FAIL; + } + else if (VIM_ISWHITE((*arg)[-1])) + { + if (verbose) + emsg(_(e_no_white_space_allowed_before_parenthesis)); + ret = FAIL; + } + else + ret = eval_func(arg, evalarg, name, len, rettv, evaluate ? EVAL_EVALUATE : 0, &base); + } } // Clear the funcref afterwards, so that deleting it while diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index f5e449714..79e572896 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -27,6 +27,10 @@ let s:export_script_lines =<< trim END exported += 5 enddef export final theList = [1] + export def AddSome(s: string): string + return s .. 'some' + enddef + export var AddRef = AddSome END def Undo_export_script_lines() @@ -70,6 +74,9 @@ def Test_vim9_import_export() expo.theList->add(2) assert_equal([1, 2], expo.theList) + + assert_equal('andthensome', 'andthen'->expo.AddSome()) + assert_equal('awesome', 'awe'->expo.AddRef()) END writefile(import_script_lines, 'Ximport.vim') source Ximport.vim diff --git a/src/version.c b/src/version.c index e6bcb1ba3..dd97a716e 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4102, /**/ 4101, /**/ -- 2.40.0