mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.0595: Vim9: not all commands using ends_excmd() tested
Problem: Vim9: not all commands using ends_excmd() tested. Solution: Find # comment after regular commands. Add more tests. Report error for where it was caused.
This commit is contained in:
parent
b6fb0516ec
commit
a26b9700d7
@ -2706,6 +2706,17 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
||||
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
|
||||
if (*name != NUL)
|
||||
s = NULL;
|
||||
else if (trans_name != NULL
|
||||
&& ASCII_ISUPPER(*s)
|
||||
&& current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
||||
&& find_func(trans_name, NULL) == NULL)
|
||||
{
|
||||
// With Vim9 script "MyFunc" can be script-local to the current
|
||||
// script or global. The script-local name is not found, assume
|
||||
// global.
|
||||
vim_free(trans_name);
|
||||
trans_name = vim_strsave(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))
|
||||
|
@ -1836,7 +1836,8 @@ do_one_cmd(
|
||||
*/
|
||||
if (*ea.cmd == NUL || *ea.cmd == '"'
|
||||
#ifdef FEAT_EVAL
|
||||
|| (*ea.cmd == '#' && !starts_with_colon && in_vim9script())
|
||||
|| (*ea.cmd == '#' && ea.cmd[1] != '{'
|
||||
&& !starts_with_colon && in_vim9script())
|
||||
#endif
|
||||
|| (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
|
||||
{
|
||||
@ -4436,6 +4437,10 @@ separate_nextcmd(exarg_T *eap)
|
||||
|| p != eap->arg)
|
||||
&& (eap->cmdidx != CMD_redir
|
||||
|| p != eap->arg + 1 || p[-1] != '@'))
|
||||
#ifdef FEAT_EVAL
|
||||
|| (*p == '#' && in_vim9script()
|
||||
&& p[1] != '{' && p > eap->cmd && VIM_ISWHITE(p[-1]))
|
||||
#endif
|
||||
|| *p == '|' || *p == '\n')
|
||||
{
|
||||
/*
|
||||
@ -4790,7 +4795,7 @@ ends_excmd2(char_u *cmd_start UNUSED, char_u *cmd)
|
||||
int c = *cmd;
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
if (c == '#' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1])))
|
||||
if (c == '#' && cmd[1] != '{' && (cmd == cmd_start || VIM_ISWHITE(cmd[-1])))
|
||||
return in_vim9script();
|
||||
#endif
|
||||
return (c == NUL || c == '|' || c == '"' || c == '\n');
|
||||
|
@ -20,6 +20,7 @@ int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount,
|
||||
void user_func_error(int error, char_u *name);
|
||||
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
|
||||
char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fdp, partial_T **partial);
|
||||
char_u *untrans_function_name(char_u *name);
|
||||
void ex_function(exarg_T *eap);
|
||||
int eval_fname_script(char_u *p);
|
||||
int translated_function_exists(char_u *name);
|
||||
|
@ -251,8 +251,8 @@ def Test_disassemble_pcall()
|
||||
enddef
|
||||
|
||||
|
||||
def FuncWithForwardCall(): string
|
||||
return DefinedLater("yes")
|
||||
def s:FuncWithForwardCall(): string
|
||||
return g:DefinedLater("yes")
|
||||
enddef
|
||||
|
||||
def DefinedLater(arg: string): string
|
||||
@ -260,11 +260,11 @@ def DefinedLater(arg: string): string
|
||||
enddef
|
||||
|
||||
def Test_disassemble_update_instr()
|
||||
let res = execute('disass FuncWithForwardCall')
|
||||
let res = execute('disass s:FuncWithForwardCall')
|
||||
assert_match('FuncWithForwardCall.*' ..
|
||||
'return DefinedLater("yes").*' ..
|
||||
'return g:DefinedLater("yes").*' ..
|
||||
'\d PUSHS "yes".*' ..
|
||||
'\d UCALL DefinedLater(argc 1).*' ..
|
||||
'\d UCALL g:DefinedLater(argc 1).*' ..
|
||||
'\d CHECKTYPE string stack\[-1].*' ..
|
||||
'\d RETURN.*',
|
||||
res)
|
||||
@ -272,9 +272,9 @@ def Test_disassemble_update_instr()
|
||||
" Calling the function will change UCALL into the faster DCALL
|
||||
assert_equal('yes', FuncWithForwardCall())
|
||||
|
||||
res = execute('disass FuncWithForwardCall')
|
||||
res = execute('disass s:FuncWithForwardCall')
|
||||
assert_match('FuncWithForwardCall.*' ..
|
||||
'return DefinedLater("yes").*' ..
|
||||
'return g:DefinedLater("yes").*' ..
|
||||
'\d PUSHS "yes".*' ..
|
||||
'\d DCALL DefinedLater(argc 1).*' ..
|
||||
'\d CHECKTYPE string stack\[-1].*' ..
|
||||
|
@ -587,7 +587,7 @@ def Test_vim9script_fails()
|
||||
CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
|
||||
|
||||
assert_fails('vim9script', 'E1038')
|
||||
assert_fails('export something', 'E1042')
|
||||
assert_fails('export something', 'E1043')
|
||||
enddef
|
||||
|
||||
def Test_vim9script_reload()
|
||||
@ -1098,6 +1098,27 @@ def Test_vim9_comment()
|
||||
], 'E488:')
|
||||
enddef
|
||||
|
||||
def Test_vim9_comment_not_compiled()
|
||||
au TabEnter *.vim let g:entered = 1
|
||||
au TabEnter *.x let g:entered = 2
|
||||
|
||||
edit test.vim
|
||||
doautocmd TabEnter #comment
|
||||
assert_equal(1, g:entered)
|
||||
|
||||
doautocmd TabEnter f.x
|
||||
assert_equal(2, g:entered)
|
||||
|
||||
g:entered = 0
|
||||
doautocmd TabEnter f.x #comment
|
||||
assert_equal(2, g:entered)
|
||||
|
||||
assert_fails('doautocmd Syntax#comment', 'E216:')
|
||||
|
||||
au! TabEnter
|
||||
unlet g:entered
|
||||
enddef
|
||||
|
||||
" Keep this last, it messes up highlighting.
|
||||
def Test_substitute_cmd()
|
||||
new
|
||||
|
@ -1663,6 +1663,7 @@ do_ucmd(exarg_T *eap)
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
|
||||
current_sctx.sc_version = cmd->uc_script_ctx.sc_version;
|
||||
#endif
|
||||
(void)do_cmdline(buf, eap->getline, eap->cookie,
|
||||
DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
|
||||
|
@ -730,7 +730,8 @@ find_func_even_dead(char_u *name, cctx_T *cctx)
|
||||
}
|
||||
}
|
||||
|
||||
hi = hash_find(&func_hashtab, name);
|
||||
hi = hash_find(&func_hashtab,
|
||||
STRNCMP(name, "g:", 2) == 0 ? name + 2 : name);
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
return HI2UF(hi);
|
||||
|
||||
@ -1651,7 +1652,7 @@ free_all_functions(void)
|
||||
|
||||
/*
|
||||
* Return TRUE if "name" looks like a builtin function name: starts with a
|
||||
* lower case letter and doesn't contain AUTOLOAD_CHAR.
|
||||
* lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
|
||||
* "len" is the length of "name", or -1 for NUL terminated.
|
||||
*/
|
||||
int
|
||||
@ -1659,7 +1660,7 @@ builtin_function(char_u *name, int len)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (!ASCII_ISLOWER(name[0]))
|
||||
if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
|
||||
return FALSE;
|
||||
p = vim_strchr(name, AUTOLOAD_CHAR);
|
||||
return p == NULL || (len > 0 && p > name + len);
|
||||
@ -1894,6 +1895,15 @@ call_func(
|
||||
// loaded a package, search for the function again
|
||||
fp = find_func(rfname, NULL);
|
||||
}
|
||||
if (fp == NULL)
|
||||
{
|
||||
char_u *p = untrans_function_name(rfname);
|
||||
|
||||
// If using Vim9 script try not local to the script.
|
||||
// TODO: should not do this if the name started with "s:".
|
||||
if (p != NULL)
|
||||
fp = find_func(p, NULL);
|
||||
}
|
||||
|
||||
if (fp != NULL && (fp->uf_flags & FC_DELETED))
|
||||
error = FCERR_DELETED;
|
||||
@ -2297,6 +2307,27 @@ theend:
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assuming "name" is the result of trans_function_name() and it was prefixed
|
||||
* to use the script-local name, return the unmodified name (points into
|
||||
* "name"). Otherwise return NULL.
|
||||
* This can be used to first search for a script-local function and fall back
|
||||
* to the global function if not found.
|
||||
*/
|
||||
char_u *
|
||||
untrans_function_name(char_u *name)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (*name == K_SPECIAL && current_sctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||
{
|
||||
p = vim_strchr(name, '_');
|
||||
if (p != NULL)
|
||||
return p + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ":function"
|
||||
*/
|
||||
@ -2467,6 +2498,16 @@ ex_function(exarg_T *eap)
|
||||
if (!eap->skip && !got_int)
|
||||
{
|
||||
fp = find_func(name, NULL);
|
||||
if (fp == NULL && ASCII_ISUPPER(*eap->arg))
|
||||
{
|
||||
char_u *up = untrans_function_name(name);
|
||||
|
||||
// With Vim9 script the name was made script-local, if not
|
||||
// found try again with the original name.
|
||||
if (p != NULL)
|
||||
fp = find_func(up, NULL);
|
||||
}
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
list_func_head(fp, TRUE);
|
||||
@ -2494,7 +2535,7 @@ ex_function(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
else
|
||||
emsg_funcname(N_("E123: Undefined function: %s"), name);
|
||||
emsg_funcname(N_("E123: Undefined function: %s"), eap->arg);
|
||||
}
|
||||
goto ret_free;
|
||||
}
|
||||
|
@ -746,6 +746,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
595,
|
||||
/**/
|
||||
594,
|
||||
/**/
|
||||
|
@ -2434,8 +2434,10 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
|
||||
}
|
||||
|
||||
// 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.
|
||||
p = namebuf;
|
||||
if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
|
||||
if (STRNCMP(namebuf, "g:", 2) != 0
|
||||
&& compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
|
||||
{
|
||||
res = generate_PCALL(cctx, argcount, FALSE);
|
||||
goto theend;
|
||||
|
@ -488,6 +488,7 @@ call_def_function(
|
||||
int idx;
|
||||
int ret = FAIL;
|
||||
int defcount = ufunc->uf_args.ga_len - argc;
|
||||
int save_sc_version = current_sctx.sc_version;
|
||||
|
||||
// Get pointer to item in the stack.
|
||||
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
|
||||
@ -565,6 +566,9 @@ call_def_function(
|
||||
ectx.ec_instr = dfunc->df_instr;
|
||||
}
|
||||
|
||||
// Commands behave like vim9script.
|
||||
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
|
||||
|
||||
// Decide where to start execution, handles optional arguments.
|
||||
init_instr_idx(ufunc, argc, &ectx);
|
||||
|
||||
@ -582,6 +586,16 @@ call_def_function(
|
||||
did_throw = TRUE;
|
||||
}
|
||||
|
||||
if (did_emsg && msg_list != NULL && *msg_list != NULL)
|
||||
{
|
||||
// Turn an error message into an exception.
|
||||
did_emsg = FALSE;
|
||||
if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
|
||||
goto failed;
|
||||
did_throw = TRUE;
|
||||
*msg_list = NULL;
|
||||
}
|
||||
|
||||
if (did_throw && !ectx.ec_in_catch)
|
||||
{
|
||||
garray_T *trystack = &ectx.ec_trystack;
|
||||
@ -1774,6 +1788,7 @@ failed:
|
||||
while (ectx.ec_frame != initial_frame_ptr)
|
||||
func_return(&ectx);
|
||||
failed_early:
|
||||
current_sctx.sc_version = save_sc_version;
|
||||
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
|
||||
clear_tv(STACK_TV(idx));
|
||||
vim_free(ectx.ec_stack.ga_data);
|
||||
@ -1807,6 +1822,14 @@ ex_disassemble(exarg_T *eap)
|
||||
}
|
||||
|
||||
ufunc = find_func(fname, NULL);
|
||||
if (ufunc == NULL)
|
||||
{
|
||||
char_u *p = untrans_function_name(fname);
|
||||
|
||||
if (p != NULL)
|
||||
// Try again without making it script-local.
|
||||
ufunc = find_func(p, NULL);
|
||||
}
|
||||
vim_free(fname);
|
||||
if (ufunc == NULL)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user