mirror of
https://github.com/vim/vim.git
synced 2025-07-25 10:54:51 -04:00
patch 8.2.2652: Vim9: can use command modifier without an effect
Problem: Vim9: can use command modifier without an effect. Solution: Give an error for a misplaced command modifier. Fix error message number.
This commit is contained in:
parent
a91a71322d
commit
fa984418e7
@ -2969,6 +2969,33 @@ parse_command_modifiers(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if "cmod" has anything set.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
has_cmdmod(cmdmod_T *cmod)
|
||||||
|
{
|
||||||
|
return cmod->cmod_flags != 0
|
||||||
|
|| cmod->cmod_split != 0
|
||||||
|
|| cmod->cmod_verbose != 0
|
||||||
|
|| cmod->cmod_tab != 0
|
||||||
|
|| cmod->cmod_filter_regmatch.regprog != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If Vim9 script and "cmdmod" has anything set give an error and return TRUE.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cmdmod_error(void)
|
||||||
|
{
|
||||||
|
if (in_vim9script() && has_cmdmod(&cmdmod))
|
||||||
|
{
|
||||||
|
emsg(_(e_misplaced_command_modifier));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply the command modifiers. Saves current state in "cmdmod", call
|
* Apply the command modifiers. Saves current state in "cmdmod", call
|
||||||
* undo_cmdmod() later.
|
* undo_cmdmod() later.
|
||||||
|
@ -1011,6 +1011,8 @@ ex_endif(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
cstack_T *cstack = eap->cstack;
|
cstack_T *cstack = eap->cstack;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
did_endif = TRUE;
|
did_endif = TRUE;
|
||||||
if (cstack->cs_idx < 0
|
if (cstack->cs_idx < 0
|
||||||
|| (cstack->cs_flags[cstack->cs_idx]
|
|| (cstack->cs_flags[cstack->cs_idx]
|
||||||
@ -1314,6 +1316,9 @@ ex_endwhile(exarg_T *eap)
|
|||||||
int csf;
|
int csf;
|
||||||
int fl;
|
int fl;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
|
|
||||||
if (eap->cmdidx == CMD_endwhile)
|
if (eap->cmdidx == CMD_endwhile)
|
||||||
{
|
{
|
||||||
err = e_while;
|
err = e_while;
|
||||||
@ -1539,6 +1544,9 @@ ex_try(exarg_T *eap)
|
|||||||
int skip;
|
int skip;
|
||||||
cstack_T *cstack = eap->cstack;
|
cstack_T *cstack = eap->cstack;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
|
|
||||||
if (cstack->cs_idx == CSTACK_LEN - 1)
|
if (cstack->cs_idx == CSTACK_LEN - 1)
|
||||||
eap->errmsg = _("E601: :try nesting too deep");
|
eap->errmsg = _("E601: :try nesting too deep");
|
||||||
else
|
else
|
||||||
@ -1617,6 +1625,9 @@ ex_catch(exarg_T *eap)
|
|||||||
cstack_T *cstack = eap->cstack;
|
cstack_T *cstack = eap->cstack;
|
||||||
char_u *pat;
|
char_u *pat;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
|
|
||||||
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
||||||
{
|
{
|
||||||
eap->errmsg = _(e_catch);
|
eap->errmsg = _(e_catch);
|
||||||
@ -1777,6 +1788,9 @@ ex_finally(exarg_T *eap)
|
|||||||
int pending = CSTP_NONE;
|
int pending = CSTP_NONE;
|
||||||
cstack_T *cstack = eap->cstack;
|
cstack_T *cstack = eap->cstack;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
|
|
||||||
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
||||||
eap->errmsg = _(e_finally);
|
eap->errmsg = _(e_finally);
|
||||||
else
|
else
|
||||||
@ -1906,6 +1920,9 @@ ex_endtry(exarg_T *eap)
|
|||||||
void *rettv = NULL;
|
void *rettv = NULL;
|
||||||
cstack_T *cstack = eap->cstack;
|
cstack_T *cstack = eap->cstack;
|
||||||
|
|
||||||
|
if (cmdmod_error())
|
||||||
|
return;
|
||||||
|
|
||||||
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
|
||||||
eap->errmsg = _(e_no_endtry);
|
eap->errmsg = _(e_no_endtry);
|
||||||
else
|
else
|
||||||
|
@ -8,6 +8,8 @@ void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void
|
|||||||
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
||||||
char *ex_errmsg(char *msg, char_u *arg);
|
char *ex_errmsg(char *msg, char_u *arg);
|
||||||
int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, int skip_only);
|
int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, int skip_only);
|
||||||
|
int has_cmdmod(cmdmod_T *cmod);
|
||||||
|
int cmdmod_error(void);
|
||||||
void apply_cmdmod(cmdmod_T *cmod);
|
void apply_cmdmod(cmdmod_T *cmod);
|
||||||
void undo_cmdmod(cmdmod_T *cmod);
|
void undo_cmdmod(cmdmod_T *cmod);
|
||||||
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
|
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
|
||||||
|
@ -247,7 +247,7 @@ enddef
|
|||||||
def Test_exepath()
|
def Test_exepath()
|
||||||
CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
|
CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
|
CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo exepath("")'], 'E1142:')
|
CheckDefExecFailure(['echo exepath("")'], 'E1175:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expand()
|
def Test_expand()
|
||||||
@ -406,13 +406,13 @@ enddef
|
|||||||
def Test_finddir()
|
def Test_finddir()
|
||||||
CheckDefExecFailure(['echo finddir(true)'], 'E1174:')
|
CheckDefExecFailure(['echo finddir(true)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:')
|
CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo finddir("")'], 'E1142:')
|
CheckDefExecFailure(['echo finddir("")'], 'E1175:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_findfile()
|
def Test_findfile()
|
||||||
CheckDefExecFailure(['echo findfile(true)'], 'E1174:')
|
CheckDefExecFailure(['echo findfile(true)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:')
|
CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:')
|
||||||
CheckDefExecFailure(['echo findfile("")'], 'E1142:')
|
CheckDefExecFailure(['echo findfile("")'], 'E1175:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_flattennew()
|
def Test_flattennew()
|
||||||
|
@ -797,6 +797,55 @@ def Test_silent_pattern()
|
|||||||
bwipe!
|
bwipe!
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_useless_command_modifier()
|
||||||
|
g:maybe = true
|
||||||
|
var lines =<< trim END
|
||||||
|
if g:maybe
|
||||||
|
silent endif
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
for i in [0]
|
||||||
|
silent endfor
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
while g:maybe
|
||||||
|
silent endwhile
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
silent try
|
||||||
|
finally
|
||||||
|
endtry
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 1)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
try
|
||||||
|
silent catch
|
||||||
|
endtry
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
try
|
||||||
|
silent finally
|
||||||
|
endtry
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
try
|
||||||
|
finally
|
||||||
|
silent endtry
|
||||||
|
END
|
||||||
|
CheckDefAndScriptFailure(lines, 'E1176:', 3)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_eval_command()
|
def Test_eval_command()
|
||||||
var from = 3
|
var from = 3
|
||||||
var to = 5
|
var to = 5
|
||||||
|
@ -1903,7 +1903,7 @@ enddef
|
|||||||
def s:SilentIf()
|
def s:SilentIf()
|
||||||
silent if 4 == g:five
|
silent if 4 == g:five
|
||||||
silent elseif 4 == g:five
|
silent elseif 4 == g:five
|
||||||
silent endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_silent_if()
|
def Test_silent_if()
|
||||||
@ -1924,14 +1924,14 @@ def Test_silent_if()
|
|||||||
'\d\+ COMPAREANY ==\_s*' ..
|
'\d\+ COMPAREANY ==\_s*' ..
|
||||||
'\d\+ CMDMOD_REV\_s*' ..
|
'\d\+ CMDMOD_REV\_s*' ..
|
||||||
'\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
|
'\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
|
||||||
'silent endif\_s*' ..
|
'endif\_s*' ..
|
||||||
'\d\+ RETURN 0',
|
'\d\+ RETURN 0',
|
||||||
res)
|
res)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def s:SilentFor()
|
def s:SilentFor()
|
||||||
silent for i in [0]
|
silent for i in [0]
|
||||||
silent endfor
|
endfor
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_silent_for()
|
def Test_silent_for()
|
||||||
@ -1945,7 +1945,7 @@ def Test_silent_for()
|
|||||||
'\d CMDMOD_REV\_s*' ..
|
'\d CMDMOD_REV\_s*' ..
|
||||||
'5 FOR $0 -> 8\_s*' ..
|
'5 FOR $0 -> 8\_s*' ..
|
||||||
'\d STORE $1\_s*' ..
|
'\d STORE $1\_s*' ..
|
||||||
'silent endfor\_s*' ..
|
'endfor\_s*' ..
|
||||||
'\d JUMP -> 5\_s*' ..
|
'\d JUMP -> 5\_s*' ..
|
||||||
'8 DROP\_s*' ..
|
'8 DROP\_s*' ..
|
||||||
'\d RETURN 0\_s*',
|
'\d RETURN 0\_s*',
|
||||||
@ -1954,7 +1954,7 @@ enddef
|
|||||||
|
|
||||||
def s:SilentWhile()
|
def s:SilentWhile()
|
||||||
silent while g:not
|
silent while g:not
|
||||||
silent endwhile
|
endwhile
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_silent_while()
|
def Test_silent_while()
|
||||||
@ -1967,7 +1967,7 @@ def Test_silent_while()
|
|||||||
'\d CMDMOD_REV\_s*' ..
|
'\d CMDMOD_REV\_s*' ..
|
||||||
'\d JUMP_IF_FALSE -> 6\_s*' ..
|
'\d JUMP_IF_FALSE -> 6\_s*' ..
|
||||||
|
|
||||||
'silent endwhile\_s*' ..
|
'endwhile\_s*' ..
|
||||||
'\d JUMP -> 0\_s*' ..
|
'\d JUMP -> 0\_s*' ..
|
||||||
'6 RETURN 0\_s*',
|
'6 RETURN 0\_s*',
|
||||||
res)
|
res)
|
||||||
|
@ -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 */
|
||||||
|
/**/
|
||||||
|
2652,
|
||||||
/**/
|
/**/
|
||||||
2651,
|
2651,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2142,11 +2142,7 @@ generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
|
|||||||
{
|
{
|
||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
|
|
||||||
if (cmod->cmod_flags != 0
|
if (has_cmdmod(cmod))
|
||||||
|| cmod->cmod_split != 0
|
|
||||||
|| cmod->cmod_verbose != 0
|
|
||||||
|| cmod->cmod_tab != 0
|
|
||||||
|| cmod->cmod_filter_regmatch.regprog != NULL)
|
|
||||||
{
|
{
|
||||||
cctx->ctx_has_cmdmod = TRUE;
|
cctx->ctx_has_cmdmod = TRUE;
|
||||||
|
|
||||||
@ -2172,22 +2168,19 @@ generate_undo_cmdmods(cctx_T *cctx)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int
|
||||||
* If an ISN_CMDMOD was just generated drop it.
|
misplaced_cmdmod(cctx_T *cctx)
|
||||||
*/
|
|
||||||
static void
|
|
||||||
drop_cmdmod(cctx_T *cctx)
|
|
||||||
{
|
{
|
||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
|
|
||||||
// Drop any CMDMOD instruction
|
|
||||||
if (cctx->ctx_has_cmdmod
|
if (cctx->ctx_has_cmdmod
|
||||||
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
|
||||||
== ISN_CMDMOD)
|
== ISN_CMDMOD)
|
||||||
{
|
{
|
||||||
--instr->ga_len;
|
emsg(_(e_misplaced_command_modifier));
|
||||||
cctx->ctx_has_cmdmod = FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7147,7 +7140,9 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
|||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
|
|
||||||
drop_cmdmod(cctx);
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (scope == NULL || scope->se_type != IF_SCOPE)
|
if (scope == NULL || scope->se_type != IF_SCOPE)
|
||||||
{
|
{
|
||||||
emsg(_(e_endif_without_if));
|
emsg(_(e_endif_without_if));
|
||||||
@ -7393,7 +7388,8 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
|||||||
forscope_T *forscope;
|
forscope_T *forscope;
|
||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
|
|
||||||
drop_cmdmod(cctx);
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (scope == NULL || scope->se_type != FOR_SCOPE)
|
if (scope == NULL || scope->se_type != FOR_SCOPE)
|
||||||
{
|
{
|
||||||
@ -7479,7 +7475,8 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
|
|||||||
scope_T *scope = cctx->ctx_scope;
|
scope_T *scope = cctx->ctx_scope;
|
||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
|
|
||||||
drop_cmdmod(cctx);
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
if (scope == NULL || scope->se_type != WHILE_SCOPE)
|
if (scope == NULL || scope->se_type != WHILE_SCOPE)
|
||||||
{
|
{
|
||||||
emsg(_(e_while));
|
emsg(_(e_while));
|
||||||
@ -7644,6 +7641,9 @@ compile_try(char_u *arg, cctx_T *cctx)
|
|||||||
scope_T *try_scope;
|
scope_T *try_scope;
|
||||||
scope_T *scope;
|
scope_T *scope;
|
||||||
|
|
||||||
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// scope that holds the jumps that go to catch/finally/endtry
|
// scope that holds the jumps that go to catch/finally/endtry
|
||||||
try_scope = new_scope(cctx, TRY_SCOPE);
|
try_scope = new_scope(cctx, TRY_SCOPE);
|
||||||
if (try_scope == NULL)
|
if (try_scope == NULL)
|
||||||
@ -7684,6 +7684,9 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
|
|||||||
char_u *p;
|
char_u *p;
|
||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
|
|
||||||
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// end block scope from :try or :catch
|
// end block scope from :try or :catch
|
||||||
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
||||||
compile_endblock(cctx);
|
compile_endblock(cctx);
|
||||||
@ -7796,6 +7799,9 @@ compile_finally(char_u *arg, cctx_T *cctx)
|
|||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
int this_instr;
|
int this_instr;
|
||||||
|
|
||||||
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// end block scope from :try or :catch
|
// end block scope from :try or :catch
|
||||||
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
||||||
compile_endblock(cctx);
|
compile_endblock(cctx);
|
||||||
@ -7854,6 +7860,9 @@ compile_endtry(char_u *arg, cctx_T *cctx)
|
|||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
isn_T *try_isn;
|
isn_T *try_isn;
|
||||||
|
|
||||||
|
if (misplaced_cmdmod(cctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// end block scope from :catch or :finally
|
// end block scope from :catch or :finally
|
||||||
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
|
||||||
compile_endblock(cctx);
|
compile_endblock(cctx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user