From a177344dc0c337e5b272c1c59d13964a8318bcfa Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 15:21:22 +0200 Subject: 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) --- src/scriptfile.c | 2 +- src/testdir/test_vim9_expr.vim | 15 +++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 9 ++++++--- src/vim9execute.c | 21 +++++++++++++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index 38215914d5..320340f8d7 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 22ac442bcb..3d16053561 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 1ab7a618ce..6edd5ec2e8 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1426, /**/ 1425, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 53dca8057b..88108f4982 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 6e9b53d689..fed7fed0e6 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -545,6 +545,15 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) 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". * 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); + + 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); -- cgit v1.2.3