0
0
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:
Bram Moolenaar 2021-03-25 22:15:28 +01:00
parent a91a71322d
commit fa984418e7
8 changed files with 131 additions and 25 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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)

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 */
/**/
2652,
/**/ /**/
2651, 2651,
/**/ /**/

View File

@ -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);