patch 9.1.0646: Vim9: imported function may not be found Commit: https://github.com/vim/vim/commit/164096927b8691085206dae3975766639a9a16e2 Author: Ernie Rael <err...@raelity.com> Date: Wed Jul 31 22:18:11 2024 +0200
patch 9.1.0646: Vim9: imported function may not be found Problem: Vim9: imported function may not be found Solution: Try to find the function by name (Ernie Rael) fixes: #15381 closes: #15382 Signed-off-by: Ernie Rael <err...@raelity.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index c8baaf687..7ed912365 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -497,6 +497,56 @@ def Test_call_call() v9.CheckSourceDefAndScriptFailure(['call("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) enddef +def Test_call_imports() + # Use call with an imported function + var lines =<< trim END + vim9script + + export const foo = 'foo' + + export def Imported() + enddef + + var count: number + export def ImportedListArg(l: list<number>) + count += 1 + l[0] += count + enddef + END + writefile(lines, 'Test_call_imports_importme', 'D') + lines =<< trim END + vim9script + import './Test_call_imports_importme' as i_imp + + var l = [12] + call('i_imp.ImportedListArg', [l]) + assert_equal(13, l[0]) + const ImportedListArg = i_imp.ImportedListArg + call('ImportedListArg', [l]) + assert_equal(15, l[0]) + const Imported = i_imp.Imported + call("Imported", []) + + assert_equal('foo', i_imp.foo) + const foo = i_imp.foo + assert_equal('foo', foo) + END + v9.CheckSourceScriptSuccess(lines) + + # A few error cases + lines =<< trim END + vim9script + import './Test_call_imports_importme' as i_imp + const Imported = i_imp.Imported + const foo = i_imp.foo + + assert_fails('call("i_imp.foo", [])', 'E117:') # foo is not a function + assert_fails('call("foo", [])', 'E117:') # foo is not a function + assert_fails('call("i_xxx.foo", [])', 'E117:') # i_xxx not imported file + END + v9.CheckSourceScriptSuccess(lines) +enddef + def Test_ch_canread() if !has('channel') CheckFeature channel diff --git a/src/userfunc.c b/src/userfunc.c index e44397d81..1c58b01c7 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2211,6 +2211,48 @@ find_func_with_prefix(char_u *name, int sid) return NULL; } +/* + * Find a function by name, return pointer to it. + * The name may be a local script variable, VAR_FUNC. or it may be a fully + * qualified import name such as 'i_imp.FuncName'. + * + * When VAR_FUNC, the import might either direct or autoload. + * When 'i_imp.FuncName' it is direct, autoload is rewritten as i_imp#FuncName + * in f_call and subsequently found. + */ + static ufunc_T * +find_func_imported(char_u *name, int flags) +{ + ufunc_T *func = NULL; + char_u *dot = name; // Find a dot, '.', in the name + + // Either run into '.' or the end of the string + while (eval_isnamec(*dot)) + ++dot; + + if (*dot == '.') + { + imported_T *import = find_imported(name, dot - name, FALSE); + if (import != NULL) + func = find_func_with_sid(dot + 1, import->imp_sid); + } + else if (*dot == NUL) // looking at the entire string + { + hashtab_T *ht = get_script_local_ht(); + if (ht != NULL) + { + hashitem_T *hi = hash_find(ht, name); + if (!HASHITEM_EMPTY(hi)) + { + dictitem_T *di = HI2DI(hi); + if (di->di_tv.v_type == VAR_FUNC) + func = find_func_even_dead(di->di_tv.vval.v_string, flags); + } + } + } + return func; +} + /* * Find a function by name, return pointer to it in ufuncs. * When "flags" has FFED_IS_GLOBAL don't find script-local or imported @@ -2260,8 +2302,15 @@ find_func_even_dead(char_u *name, int flags) } // Find autoload function if this is an autoload script. - return find_func_with_prefix(name[0] == 's' && name[1] == ':' + func = find_func_with_prefix(name[0] == 's' && name[1] == ':' ? name + 2 : name, current_sctx.sc_sid); + if (func != NULL) + return func; + + // Find a script-local "VAR_FUNC" or i_"imp.Func", so vim9script). + if (in_vim9script()) + func = find_func_imported(name, flags); + return func; } /* diff --git a/src/version.c b/src/version.c index f19e9415e..4dc9948d9 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 646, /**/ 645, /**/ -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/E1sZFxZ-006RO5-Dk%40256bit.org.