summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-08-12 15:21:22 +0200
committerBram Moolenaar <Bram@vim.org>2020-08-12 15:21:22 +0200
commita177344dc0c337e5b272c1c59d13964a8318bcfa (patch)
treef7e343d4db0e54ea97e6a3c82fe921db35f6395d
parent575f24b3f3d8cd8bfc2da402c2938c0c7ace7877 (diff)
downloadvim-git-a177344dc0c337e5b272c1c59d13964a8318bcfa.tar.gz
patch 8.2.1426: Vim9: cannot call autoload function in :def functionv8.2.1426
Problem: Vim9: cannot call autoload function in :def function. Solution: Load the autoload script. (closes #6690)
-rw-r--r--src/scriptfile.c2
-rw-r--r--src/testdir/test_vim9_expr.vim15
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c9
-rw-r--r--src/vim9execute.c21
5 files changed, 45 insertions, 4 deletions
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 38215914d..320340f8d 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1991,7 +1991,7 @@ autoload_name(char_u *name)
if (scriptname == NULL)
return NULL;
STRCPY(scriptname, "autoload/");
- STRCAT(scriptname, name);
+ STRCAT(scriptname, name[0] == 'g' && name[1] == ':' ? name + 2: name);
for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL;
q = p, ++p)
*p = '/';
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 22ac442bc..3d1605356 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -1752,6 +1752,21 @@ def Test_expr7_call()
"vim9script",
"let x = substitute ('x', 'x', 'x', 'x')"
], 'E121:')
+
+ let auto_lines =<< trim END
+ def g:some#func(): string
+ return 'found'
+ enddef
+ END
+ mkdir('Xruntime/autoload', 'p')
+ writefile(auto_lines, 'Xruntime/autoload/some.vim')
+ let save_rtp = &rtp
+ &rtp = getcwd() .. '/Xruntime,' .. &rtp
+ assert_equal('found', g:some#func())
+ assert_equal('found', some#func())
+
+ &rtp = save_rtp
+ delete('Xruntime', 'rf')
enddef
diff --git a/src/version.c b/src/version.c
index 1ab7a618c..6edd5ec2e 100644
--- 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 */
/**/
+ 1426,
+/**/
1425,
/**/
1424,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 53dca8057..88108f498 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2214,6 +2214,7 @@ compile_call(
int error = FCERR_NONE;
ufunc_T *ufunc;
int res = FAIL;
+ int is_autoload;
// we can evaluate "has('name')" at compile time
if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
@@ -2258,7 +2259,8 @@ compile_call(
if (compile_arguments(arg, cctx, &argcount) == FAIL)
goto theend;
- if (ASCII_ISLOWER(*name) && name[1] != ':')
+ is_autoload = vim_strchr(name, '#') != NULL;
+ if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
{
int idx;
@@ -2281,8 +2283,9 @@ compile_call(
// If the name is a variable, load it and use PCALL.
// Not for g:Func(), we don't know if it is a variable or not.
+ // Not for eome#Func(), it will be loaded later.
p = namebuf;
- if (STRNCMP(namebuf, "g:", 2) != 0
+ if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
&& compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
{
garray_T *stack = &cctx->ctx_type_stack;
@@ -2295,7 +2298,7 @@ compile_call(
// A global function may be defined only later. Need to figure out at
// runtime. Also handles a FuncRef at runtime.
- if (STRNCMP(namebuf, "g:", 2) == 0)
+ if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload)
res = generate_UCALL(cctx, name, argcount);
else
semsg(_(e_unknownfunc), namebuf);
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 6e9b53d68..fed7fed0e 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -546,6 +546,15 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
}
/*
+ * Return TRUE if an error was given or CTRL-C was pressed.
+ */
+ static int
+vim9_aborting(int prev_called_emsg)
+{
+ return called_emsg > prev_called_emsg || got_int || did_throw;
+}
+
+/*
* Execute a function by "name".
* This can be a builtin function or a user function.
* "iptr" can be used to replace the instruction with a more efficient one.
@@ -568,6 +577,18 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
}
ufunc = find_func(name, FALSE, NULL);
+
+ if (ufunc == NULL)
+ {
+ int called_emsg_before = called_emsg;
+
+ if (script_autoload(name, TRUE))
+ // loaded a package, search for the function again
+ ufunc = find_func(name, FALSE, NULL);
+ if (vim9_aborting(called_emsg_before))
+ return FAIL; // bail out if loading the script caused an error
+ }
+
if (ufunc != NULL)
return call_ufunc(ufunc, argcount, ectx, iptr);