0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.2.1426: Vim9: cannot call autoload function in :def function

Problem:    Vim9: cannot call autoload function in :def function.
Solution:   Load the autoload script. (closes #6690)
This commit is contained in:
Bram Moolenaar
2020-08-12 15:21:22 +02:00
parent 575f24b3f3
commit a177344dc0
5 changed files with 45 additions and 4 deletions

View File

@@ -1991,7 +1991,7 @@ autoload_name(char_u *name)
if (scriptname == NULL) if (scriptname == NULL)
return NULL; return NULL;
STRCPY(scriptname, "autoload/"); 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; for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL;
q = p, ++p) q = p, ++p)
*p = '/'; *p = '/';

View File

@@ -1752,6 +1752,21 @@ def Test_expr7_call()
"vim9script", "vim9script",
"let x = substitute ('x', 'x', 'x', 'x')" "let x = substitute ('x', 'x', 'x', 'x')"
], 'E121:') ], '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 enddef

View File

@@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1426,
/**/ /**/
1425, 1425,
/**/ /**/

View File

@@ -2214,6 +2214,7 @@ compile_call(
int error = FCERR_NONE; int error = FCERR_NONE;
ufunc_T *ufunc; ufunc_T *ufunc;
int res = FAIL; int res = FAIL;
int is_autoload;
// we can evaluate "has('name')" at compile time // we can evaluate "has('name')" at compile time
if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
@@ -2258,7 +2259,8 @@ compile_call(
if (compile_arguments(arg, cctx, &argcount) == FAIL) if (compile_arguments(arg, cctx, &argcount) == FAIL)
goto theend; goto theend;
if (ASCII_ISLOWER(*name) && name[1] != ':') is_autoload = vim_strchr(name, '#') != NULL;
if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
{ {
int idx; int idx;
@@ -2281,8 +2283,9 @@ compile_call(
// If the name is a variable, load it and use PCALL. // 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 g:Func(), we don't know if it is a variable or not.
// Not for eome#Func(), it will be loaded later.
p = namebuf; p = namebuf;
if (STRNCMP(namebuf, "g:", 2) != 0 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
&& compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
{ {
garray_T *stack = &cctx->ctx_type_stack; 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 // A global function may be defined only later. Need to figure out at
// runtime. Also handles a FuncRef at runtime. // 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); res = generate_UCALL(cctx, name, argcount);
else else
semsg(_(e_unknownfunc), namebuf); semsg(_(e_unknownfunc), namebuf);

View File

@@ -545,6 +545,15 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
return OK; return OK;
} }
/*
* 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". * Execute a function by "name".
* This can be a builtin function or a user function. * This can be a builtin function or a user function.
@@ -568,6 +577,18 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
} }
ufunc = find_func(name, FALSE, NULL); 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) if (ufunc != NULL)
return call_ufunc(ufunc, argcount, ectx, iptr); return call_ufunc(ufunc, argcount, ectx, iptr);