1
0
forked from aniani/vim

patch 8.2.4137: Vim9: calling import with and without method is inconsistent

Problem:    Vim9: calling import with and without method is inconsistent.
Solution:   Set a flag that a parenthsis follows to compile_load_scriptvar().
            Add some more tests.  Improve error message.
This commit is contained in:
Bram Moolenaar
2022-01-18 17:43:04 +00:00
parent fd218c8a36
commit d02dce2bb5
5 changed files with 170 additions and 29 deletions

View File

@@ -1256,6 +1256,136 @@ def Test_vim9script_autoload()
&rtp = save_rtp &rtp = save_rtp
enddef enddef
def Test_import_autoload_not_exported()
mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
# error when using an item that is not exported from an autoload script
var exportLines =<< trim END
vim9script
var notExported = 123
def NotExport()
echo 'nop'
enddef
END
writefile(exportLines, 'Xdir/autoload/notExport1.vim')
var lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notFound
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notFound')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notExported
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: notExported')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
# using a :def function we use a different autoload script every time so that
# the function is compiled without the script loaded
writefile(exportLines, 'Xdir/autoload/notExport2.vim')
lines =<< trim END
vim9script
import autoload 'notExport2.vim'
def Testit()
echo notExport2.notFound
enddef
Testit()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport2#notFound')
writefile(exportLines, 'Xdir/autoload/notExport3.vim')
lines =<< trim END
vim9script
import autoload 'notExport3.vim'
def Testit()
echo notExport3.notExported
enddef
Testit()
END
# don't get E1049 because it is too complicated to figure out
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport3#notExported')
writefile(exportLines, 'Xdir/autoload/notExport4.vim')
lines =<< trim END
vim9script
import autoload 'notExport4.vim'
def Testit()
echo notExport4.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport4#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport5.vim')
lines =<< trim END
vim9script
import autoload 'notExport5.vim'
def Testit()
echo notExport5.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport5#NotExport')
writefile(exportLines, 'Xdir/autoload/notExport6.vim')
lines =<< trim END
vim9script
import autoload 'notExport6.vim'
def Testit()
echo 'text'->notExport6.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport6#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport7.vim')
lines =<< trim END
vim9script
import autoload 'notExport7.vim'
def Testit()
echo 'text'->notExport7.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport7#NotExport')
delete('Xdir', 'rf')
&rtp = save_rtp
enddef
def Test_vim9script_autoload_call() def Test_vim9script_autoload_call()
mkdir('Xdir/autoload', 'p') mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp var save_rtp = &rtp

View File

@@ -750,6 +750,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 */
/**/
4137,
/**/ /**/
4136, 4136,
/**/ /**/

View File

@@ -2240,33 +2240,19 @@ exec_instructions(ectx_T *ectx)
iptr->isn_arg.string, TRUE); iptr->isn_arg.string, TRUE);
if (did_emsg) if (did_emsg)
goto on_error; goto on_error;
if (di == NULL)
{
isn_T *next = &ectx->ec_instr[ectx->ec_iidx];
// When compiling "script.Func()" when "script" is
// an autoload import then this results in
// "LOADG script#Func" because we don't know if it
// is a funcref variable or a function name. In
// that case a PCALL follows, push the function
// name instead.
if (next->isn_type == ISN_PCALL)
{
tv = STACK_TV_BOT(0);
tv->v_type = VAR_FUNC;
tv->v_lock = 0;
tv->vval.v_string =
vim_strsave(iptr->isn_arg.string);
++ectx->ec_stack.ga_len;
break;
}
}
} }
if (di == NULL) if (di == NULL)
{ {
SOURCING_LNUM = iptr->isn_lnum; SOURCING_LNUM = iptr->isn_lnum;
semsg(_(e_undefined_variable_char_str), if (vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
// no check if the item exists in the script but
// isn't exported, it is too complicated
semsg(_(e_item_not_found_in_script_str),
iptr->isn_arg.string);
else
semsg(_(e_undefined_variable_char_str),
namespace, iptr->isn_arg.string); namespace, iptr->isn_arg.string);
goto on_error; goto on_error;
} }

View File

@@ -21,6 +21,9 @@
# include "vim9.h" # include "vim9.h"
#endif #endif
// flag passed from compile_subscript() to compile_load_scriptvar()
static int paren_follows_after_expr = 0;
/* /*
* Generate code for any ppconst entries. * Generate code for any ppconst entries.
*/ */
@@ -277,7 +280,6 @@ compile_load_scriptvar(
int done = FALSE; int done = FALSE;
int res = OK; int res = OK;
// TODO: if this is an autoload import do something else.
// Need to lookup the member. // Need to lookup the member.
if (*p != '.') if (*p != '.')
{ {
@@ -306,7 +308,7 @@ compile_load_scriptvar(
// autoload script must be loaded later, access by the autoload // autoload script must be loaded later, access by the autoload
// name. // name.
if (cc == '(') if (cc == '(' || paren_follows_after_expr)
res = generate_PUSHFUNC(cctx, auto_name, &t_func_any); res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
else else
res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any); res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any);
@@ -1736,12 +1738,19 @@ compile_subscript(
int save_len = cctx->ctx_ufunc->uf_lines.ga_len; int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
*paren = NUL; *paren = NUL;
// instead of using LOADG for "import.Func" use PUSHFUNC
++paren_follows_after_expr;
// do not look in the next line // do not look in the next line
cctx->ctx_ufunc->uf_lines.ga_len = 1; cctx->ctx_ufunc->uf_lines.ga_len = 1;
fail = compile_expr8(arg, cctx, ppconst) == FAIL fail = compile_expr8(arg, cctx, ppconst) == FAIL
|| *skipwhite(*arg) != NUL; || *skipwhite(*arg) != NUL;
*paren = '('; *paren = '(';
--paren_follows_after_expr;
cctx->ctx_ufunc->uf_lines.ga_len = save_len; cctx->ctx_ufunc->uf_lines.ga_len = save_len;
if (fail) if (fail)
{ {
semsg(_(e_invalid_expression_str), pstart); semsg(_(e_invalid_expression_str), pstart);

View File

@@ -707,22 +707,36 @@ find_exported(
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
} }
*ufunc = find_func(funcname, FALSE); *ufunc = find_func(funcname, FALSE);
if (funcname != buffer)
vim_free(funcname);
if (*ufunc == NULL) if (*ufunc == NULL)
{ {
if (verbose) if (verbose)
semsg(_(e_item_not_found_in_script_str), name); {
return -1; ufunc_T *alt_ufunc = NULL;
if (script->sn_autoload_prefix != NULL)
{
// try find the function by the script-local name
funcname[0] = K_SPECIAL;
funcname[1] = KS_EXTRA;
funcname[2] = (int)KE_SNR;
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
alt_ufunc = find_func(funcname, FALSE);
}
if (alt_ufunc != NULL)
semsg(_(e_item_not_exported_in_script_str), name);
else
semsg(_(e_item_not_found_in_script_str), name);
}
} }
else if (((*ufunc)->uf_flags & FC_EXPORT) == 0) else if (((*ufunc)->uf_flags & FC_EXPORT) == 0)
{ {
if (verbose) if (verbose)
semsg(_(e_item_not_exported_in_script_str), name); semsg(_(e_item_not_exported_in_script_str), name);
*ufunc = NULL; *ufunc = NULL;
return -1;
} }
if (funcname != buffer)
vim_free(funcname);
} }
return idx; return idx;