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:
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2240,32 +2240,18 @@ 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;
|
||||||
|
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),
|
semsg(_(e_undefined_variable_char_str),
|
||||||
namespace, iptr->isn_arg.string);
|
namespace, iptr->isn_arg.string);
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
|
{
|
||||||
|
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);
|
semsg(_(e_item_not_found_in_script_str), name);
|
||||||
return -1;
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user