]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.4162: Vim9: no error for redefining function with export v8.2.4162
authorBram Moolenaar <Bram@vim.org>
Thu, 20 Jan 2022 19:10:25 +0000 (19:10 +0000)
committerBram Moolenaar <Bram@vim.org>
Thu, 20 Jan 2022 19:10:25 +0000 (19:10 +0000)
Problem:    Vim9: no error for redefining function with export.
Solution:   Check for existing function with/without prefix. (closes #9577)

src/scriptfile.c
src/testdir/test_vim9_import.vim
src/userfunc.c
src/version.c

index 5b1e43b78f490e446514da1f99da5e714041bee8..dec512a72ba133196269102a65cb393db7e2a02a 100644 (file)
@@ -2190,7 +2190,7 @@ get_autoload_prefix(scriptitem_T *si)
 
 /*
  * If in a Vim9 autoload script return "name" with the autoload prefix for the
- * script.  If successful "name" is freed, the returned name is allocated.
+ * script.  If successful the returned name is allocated.
  * Otherwise it returns "name" unmodified.
  */
     char_u *
@@ -2221,7 +2221,6 @@ may_prefix_autoload(char_u *name)
            {
                vim_snprintf((char *)res, len, "%s%s",
                                             si->sn_autoload_prefix, basename);
-               vim_free(name);
                return res;
            }
        }
index 6a38106a7d82c0127e2839a36753d627c60a1c95..c26ccf80aa71b5ef0f77079481019bc9100f6c4a 100644 (file)
@@ -1440,6 +1440,80 @@ def Test_vim9script_autoload_call()
   &rtp = save_rtp
 enddef
 
+def Test_vim9script_autoload_duplicate()
+  mkdir('Xdir/autoload', 'p')
+
+  var lines =<< trim END
+     vim9script
+
+     export def Func()
+     enddef
+
+     def Func()
+     enddef
+  END
+  writefile(lines, 'Xdir/autoload/dupfunc.vim')
+  assert_fails('source Xdir/autoload/dupfunc.vim', 'E1073:')
+
+  lines =<< trim END
+     vim9script
+
+     def Func()
+     enddef
+
+     export def Func()
+     enddef
+  END
+  writefile(lines, 'Xdir/autoload/dup2func.vim')
+  assert_fails('source Xdir/autoload/dup2func.vim', 'E1073:')
+
+  lines =<< trim END
+     vim9script
+
+     def Func()
+     enddef
+
+     export var Func = 'asdf'
+  END
+  writefile(lines, 'Xdir/autoload/dup3func.vim')
+  assert_fails('source Xdir/autoload/dup3func.vim', 'E1041: Redefining script item Func')
+
+  lines =<< trim END
+     vim9script
+
+     export var Func = 'asdf'
+
+     def Func()
+     enddef
+  END
+  writefile(lines, 'Xdir/autoload/dup4func.vim')
+  assert_fails('source Xdir/autoload/dup4func.vim', 'E707:')
+
+  lines =<< trim END
+     vim9script
+
+     var Func = 'asdf'
+
+     export def Func()
+     enddef
+  END
+  writefile(lines, 'Xdir/autoload/dup5func.vim')
+  assert_fails('source Xdir/autoload/dup5func.vim', 'E707:')
+
+  lines =<< trim END
+     vim9script
+
+     export def Func()
+     enddef
+
+     var Func = 'asdf'
+  END
+  writefile(lines, 'Xdir/autoload/dup6func.vim')
+  assert_fails('source Xdir/autoload/dup6func.vim', 'E1041: Redefining script item Func')
+
+  delete('Xdir', 'rf')
+enddef
+
 def Test_import_autoload_postponed()
   mkdir('Xdir/autoload', 'p')
   var save_rtp = &rtp
index 7d3bb292d8f5748f1c75060843466a613962f93d..014ec5524387497e0a71d7aca6306dc7660afaf2 100644 (file)
@@ -1911,6 +1911,12 @@ find_func_with_prefix(char_u *name, int sid)
     {
        size_t  len = STRLEN(si->sn_autoload_prefix) + STRLEN(name) + 1;
        char_u  *auto_name;
+       char_u  *namep;
+
+       // skip a "<SNR>99_" prefix
+       namep = untrans_function_name(name);
+       if (namep == NULL)
+           namep = name;
 
        // An exported function in an autoload script is stored as
        // "dir#path#name".
@@ -1921,7 +1927,7 @@ find_func_with_prefix(char_u *name, int sid)
        if (auto_name != NULL)
        {
            vim_snprintf((char *)auto_name, len, "%s%s",
-                                                si->sn_autoload_prefix, name);
+                                               si->sn_autoload_prefix, namep);
            hi = hash_find(&func_hashtab, auto_name);
            if (auto_name != buffer)
                vim_free(auto_name);
@@ -4175,7 +4181,15 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
        // is stored with the legacy autoload name "dir#script#FuncName" so
        // that it can also be found in legacy script.
        if (is_export && name != NULL)
-           name = may_prefix_autoload(name);
+       {
+           char_u *prefixed = may_prefix_autoload(name);
+
+           if (prefixed != NULL && prefixed != name)
+           {
+               vim_free(name);
+               name = prefixed;
+           }
+       }
     }
 
     // An error in a function call during evaluation of an expression in magic
@@ -4447,20 +4461,53 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
     if (fudi.fd_dict == NULL)
     {
        hashtab_T       *ht;
+       char_u          *find_name = name;
+       int             var_conflict = FALSE;
 
        v = find_var(name, &ht, TRUE);
-       if (v != NULL && v->di_tv.v_type == VAR_FUNC)
+       if (v != NULL)
+           var_conflict = TRUE;
+
+       if (SCRIPT_ID_VALID(current_sctx.sc_sid))
+       {
+           scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
+
+           if (si->sn_autoload_prefix != NULL)
+           {
+               if (is_export)
+               {
+                   find_name = name + STRLEN(si->sn_autoload_prefix);
+                   v = find_var(find_name, &ht, TRUE);
+                   if (v != NULL)
+                       var_conflict = TRUE;
+               }
+               else
+               {
+                   char_u *prefixed = may_prefix_autoload(name);
+
+                   if (prefixed != NULL)
+                   {
+                       v = find_var(prefixed, &ht, TRUE);
+                       if (v != NULL)
+                           var_conflict = TRUE;
+                       vim_free(prefixed);
+                   }
+               }
+           }
+       }
+       if (var_conflict)
        {
            emsg_funcname(e_function_name_conflicts_with_variable_str, name);
            goto erret;
        }
 
-       fp = find_func_even_dead(name, is_global);
+       fp = find_func_even_dead(find_name, is_global);
        if (vim9script)
        {
            char_u *uname = untrans_function_name(name);
 
-           import = find_imported(uname == NULL ? name : uname, 0, FALSE, NULL);
+           import = find_imported(uname == NULL ? name : uname, 0,
+                                                                 FALSE, NULL);
        }
 
        if (fp != NULL || import != NULL)
index fae00dc9d3b0d425a21cee14f64e0e7bf64096f2..7fd24f5eea0b68629bb2c2243673dda812e0a9f9 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4162,
 /**/
     4161,
 /**/