summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-01-20 19:10:25 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-20 19:10:25 +0000
commit9c7cae66bc21a3dc5c6e60cd64216ce7c9073003 (patch)
treecf9de73f0e9671be44fc0ee58e2033670ccdf908
parent21f0d6cbca9c93e2319d45a33ba26b10a85ff4dc (diff)
downloadvim-git-9c7cae66bc21a3dc5c6e60cd64216ce7c9073003.tar.gz
patch 8.2.4162: Vim9: no error for redefining function with exportv8.2.4162
Problem: Vim9: no error for redefining function with export. Solution: Check for existing function with/without prefix. (closes #9577)
-rw-r--r--src/scriptfile.c3
-rw-r--r--src/testdir/test_vim9_import.vim74
-rw-r--r--src/userfunc.c57
-rw-r--r--src/version.c2
4 files changed, 129 insertions, 7 deletions
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 5b1e43b78..dec512a72 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -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;
}
}
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index 6a38106a7..c26ccf80a 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -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
diff --git a/src/userfunc.c b/src/userfunc.c
index 7d3bb292d..014ec5524 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -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)
diff --git a/src/version.c b/src/version.c
index fae00dc9d..7fd24f5ee 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4162,
+/**/
4161,
/**/
4160,