changeset 21699:1b96535705a0 v8.2.1399

patch 8.2.1399: Vim9: may find imported item in wrong script Commit: https://github.com/vim/vim/commit/efa94447e85eacce62c1fcf6b63e7f3431e2cb1b Author: Bram Moolenaar <Bram@vim.org> Date: Sat Aug 8 22:16:00 2020 +0200 patch 8.2.1399: Vim9: may find imported item in wrong script Problem: Vim9: may find imported item in wrong script. Solution: When looking up script-local function use the embedded script ID. (issue #6644)
author Bram Moolenaar <Bram@vim.org>
date Sat, 08 Aug 2020 22:30:03 +0200
parents df2188073dca
children a5743521c118
files src/proto/vim9compile.pro src/testdir/test_vim9_script.vim src/userfunc.c src/version.c src/vim9compile.c
diffstat 5 files changed, 45 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/proto/vim9compile.pro
+++ b/src/proto/vim9compile.pro
@@ -12,6 +12,7 @@ char *vartype_name(vartype_T type);
 char *type_name(type_T *type, char **tofree);
 int get_script_item_idx(int sid, char_u *name, int check_writable);
 imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
+imported_T *find_imported_in_script(char_u *name, size_t len, int sid);
 int vim9_comment_start(char_u *p);
 char_u *peek_next_line_from_context(cctx_T *cctx);
 char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1430,6 +1430,31 @@ def Test_import_in_filetype()
   &rtp = save_rtp
 enddef
 
+def Test_use_import_in_mapping()
+  let lines =<< trim END
+      vim9script
+      export def Funcx()
+        g:result = 42
+      enddef
+  END
+  writefile(lines, 'XsomeExport.vim')
+  lines =<< trim END
+      vim9script
+      import Funcx from './XsomeExport.vim'
+      nnoremap <C-B> :call <sid>Funcx()<cr>
+  END
+  writefile(lines, 'Xmapscript.vim')
+
+  source Xmapscript.vim
+  feedkeys("\<c-b>", "xt")
+  assert_equal(42, g:result)
+
+  unlet g:result
+  delete('XsomeExport.vim')
+  delete('Xmapscript.vim')
+  nunmap <C-B>
+enddef
+
 def Test_vim9script_fails()
   CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
   CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -791,6 +791,7 @@ find_func_even_dead(char_u *name, int is
     {
 	int	vim9script = in_vim9script();
 	char_u	*after_script = NULL;
+	long	sid = 0;
 
 	if (vim9script)
 	{
@@ -800,18 +801,15 @@ find_func_even_dead(char_u *name, int is
 		return func;
 	}
 
-	if (!vim9script
-		&& name[0] == K_SPECIAL
+	if (name[0] == K_SPECIAL
 		&& name[1] == KS_EXTRA
 		&& name[2] == KE_SNR)
 	{
-	    long sid;
-
 	    // Caller changes s: to <SNR>99_name.
 
 	    after_script = name + 3;
 	    sid = getdigits(&after_script);
-	    if (sid == current_sctx.sc_sid && *after_script == '_')
+	    if (*after_script == '_')
 		++after_script;
 	    else
 		after_script = NULL;
@@ -819,8 +817,11 @@ find_func_even_dead(char_u *name, int is
 	if (vim9script || after_script != NULL)
 	{
 	    // Find imported function before global one.
-	    imported = find_imported(
-			  after_script == NULL ? name : after_script, 0, cctx);
+	    if (after_script != NULL && sid != current_sctx.sc_sid)
+		imported = find_imported_in_script(after_script, 0, sid);
+	    else
+		imported = find_imported(after_script == NULL
+					       ? name : after_script, 0, cctx);
 	    if (imported != NULL && imported->imp_funcname != NULL)
 	    {
 		hi = hash_find(&func_hashtab, imported->imp_funcname);
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1399,
+/**/
     1398,
 /**/
     1397,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2548,12 +2548,10 @@ get_script_item_idx(int sid, char_u *nam
     imported_T *
 find_imported(char_u *name, size_t len, cctx_T *cctx)
 {
-    scriptitem_T    *si;
     int		    idx;
 
     if (current_sctx.sc_sid <= 0)
 	return NULL;
-    si = SCRIPT_ITEM(current_sctx.sc_sid);
     if (cctx != NULL)
 	for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
 	{
@@ -2566,6 +2564,15 @@ find_imported(char_u *name, size_t len, 
 		return import;
 	}
 
+    return find_imported_in_script(name, len, current_sctx.sc_sid);
+}
+
+    imported_T *
+find_imported_in_script(char_u *name, size_t len, int sid)
+{
+    scriptitem_T    *si = SCRIPT_ITEM(sid);
+    int		    idx;
+
     for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
     {
 	imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;