Skip to content

Commit f3dc0fe

Browse files
h-eastchrisbra
authored andcommitted
patch 9.2.1132: skip condition not considered for certain commands
Problem: "if 0" condition not correctly skipped for :command, :autocmd, :class, :interface, :enum and :loadkeymap Solution: Skip those commands and discard the blocks they read (Hirohito Higashi). closes: #21349 Assisted-by: Claude Signed-off-by: Hirohito Higashi <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 33402ca commit f3dc0fe

9 files changed

Lines changed: 157 additions & 0 deletions

File tree

‎src/digraph.c‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,14 @@ ex_loadkeymap(exarg_T *eap)
22992299
return;
23002300
}
23012301

2302+
if (eap->skip)
2303+
{
2304+
// The rest of the script is the keymap, read it and throw it away.
2305+
while ((line = eap->ea_getline(0, eap->cookie, 0, TRUE)) != NULL)
2306+
vim_free(line);
2307+
return;
2308+
}
2309+
23022310
/*
23032311
* Stop any active keymap and clear the table.
23042312
*/

‎src/ex_docmd.c‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,6 +2526,16 @@ do_one_cmd(
25262526
case CMD_def:
25272527
break;
25282528

2529+
// commands that read a block of lines
2530+
case CMD_abstract:
2531+
case CMD_autocmd:
2532+
case CMD_class:
2533+
case CMD_command:
2534+
case CMD_enum:
2535+
case CMD_interface:
2536+
case CMD_loadkeymap:
2537+
break;
2538+
25292539
// Commands that handle '|' themselves. Check: A command should
25302540
// either have the EX_TRLBAR flag, appear in this list or appear in
25312541
// the list at ":help :bar".
@@ -5834,6 +5844,12 @@ expand_argopt(
58345844
static void
58355845
ex_autocmd(exarg_T *eap)
58365846
{
5847+
if (eap->skip)
5848+
{
5849+
skip_cmd_block(eap);
5850+
return;
5851+
}
5852+
58375853
/*
58385854
* Disallow autocommands from .exrc and .vimrc in current
58395855
* directory for security reasons.

‎src/proto/usercmd.pro‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int cmdcomplete_str_to_type(char_u *complete_str);
1515
char *uc_fun_cmd(void);
1616
int parse_compl_arg(char_u *value, int vallen, int *complp, long *argt, char_u **compl_arg);
1717
char_u *may_get_cmd_block(exarg_T *eap, char_u *p, char_u **tofree, int *flags);
18+
void skip_cmd_block(exarg_T *eap);
1819
void ex_command(exarg_T *eap);
1920
void ex_comclear(exarg_T *eap);
2021
void uc_clear(garray_T *gap);

‎src/testdir/test_digraph.vim‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,15 @@ func Test_loadkeymap_error()
505505
call assert_fails('source Xkeymap', 'E791:')
506506
endfunc
507507

508+
" Test for ":loadkeymap" in a block that is not executed: it reads the rest of
509+
" the script, so that rest, the "endif" with it, is thrown away instead of
510+
" being read as commands.
511+
func Test_loadkeymap_skipped()
512+
CheckFeature keymap
513+
call writefile(['if 0', ' loadkeymap', ' a b', 'endif'], 'Xkeymap', 'D')
514+
call assert_fails('source Xkeymap', 'E171:')
515+
endfunc
516+
508517
" Test for the characters displayed on the screen when entering a digraph
509518
func Test_entering_digraph()
510519
CheckRunVimInTerminal

‎src/testdir/test_usercommands.vim‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,4 +1276,41 @@ func Test_command_list_0()
12761276
delcommand VeryMuchLongerCommand
12771277
endfunc
12781278

1279+
" Test for a block of ":command" or ":autocmd" in a block that is not
1280+
" executed: the lines up to the "}" are skipped, not parsed as commands.
1281+
func Test_command_block_skipped()
1282+
let lines =<< trim END
1283+
vim9script
1284+
def Something(s: string)
1285+
echo s
1286+
enddef
1287+
if 0
1288+
command! -bar -nargs=? Xfoo {
1289+
Something(<q-args>)
1290+
}
1291+
endif
1292+
if 0
1293+
autocmd BufRead *.xyz {
1294+
Something(<q-args>)
1295+
}
1296+
endif
1297+
while 0
1298+
command! Xbar {
1299+
Something('x')
1300+
}
1301+
endwhile
1302+
g:skipped = 'all three'
1303+
END
1304+
call writefile(lines, 'Xcmdblock.vim', 'D')
1305+
1306+
let g:skipped = ''
1307+
source Xcmdblock.vim
1308+
call assert_equal('all three', g:skipped)
1309+
call assert_equal(0, exists(':Xfoo'))
1310+
call assert_equal(0, exists(':Xbar'))
1311+
call assert_notmatch('xyz', execute('autocmd BufRead'))
1312+
1313+
unlet g:skipped
1314+
endfunc
1315+
12791316
" vim: shiftwidth=2 sts=2 expandtab

‎src/testdir/test_vim9_class.vim‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11965,4 +11965,33 @@ def Test_nested_object_member_op_assign()
1196511965
v9.CheckSourceSuccess(lines)
1196611966
enddef
1196711967

11968+
" Test for a class, interface or enum in a block that is not executed: the
11969+
" body is skipped, not read as commands.
11970+
def Test_class_body_skipped()
11971+
var lines =<< trim END
11972+
vim9script
11973+
if 0
11974+
interface Bar
11975+
def M(): number
11976+
endinterface
11977+
endif
11978+
if 0
11979+
class Foo
11980+
var x: number = 1
11981+
endclass
11982+
endif
11983+
while 0
11984+
enum Baz
11985+
One,
11986+
Two
11987+
endenum
11988+
endwhile
11989+
g:skipped = 'all three'
11990+
END
11991+
g:skipped = ''
11992+
v9.CheckSourceSuccess(lines)
11993+
assert_equal('all three', g:skipped)
11994+
unlet g:skipped
11995+
enddef
11996+
1196811997
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

‎src/usercmd.c‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,20 @@ may_get_cmd_block(exarg_T *eap, char_u *p, char_u **tofree, int *flags)
13721372
return retp;
13731373
}
13741374

1375+
/*
1376+
* Read the block of commands that may follow and throw it away.
1377+
* Used for ":command" and ":autocmd" while skipping.
1378+
*/
1379+
void
1380+
skip_cmd_block(exarg_T *eap)
1381+
{
1382+
char_u *tofree = NULL;
1383+
int flags = 0;
1384+
1385+
(void)may_get_cmd_block(eap, eap->cmd, &tofree, &flags);
1386+
vim_free(tofree);
1387+
}
1388+
13751389
/*
13761390
* ":command ..." implementation
13771391
*/
@@ -1391,6 +1405,12 @@ ex_command(exarg_T *eap)
13911405
int has_attr = (eap->arg[0] == '-');
13921406
int name_len;
13931407

1408+
if (eap->skip)
1409+
{
1410+
skip_cmd_block(eap);
1411+
return;
1412+
}
1413+
13941414
p = eap->arg;
13951415

13961416
// Check for attributes

‎src/version.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ static char *(features[]) =
763763

764764
static int included_patches[] =
765765
{ /* Add new patch number below this line */
766+
/**/
767+
1132,
766768
/**/
767769
1131,
768770
/**/

‎src/vim9class.c‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,35 @@ enum_set_internal_obj_vars(class_T *en, object_T *enval)
19341934
ord_tv->vval.v_number = i;
19351935
}
19361936

1937+
/*
1938+
* Read the body up to ":endclass", ":endenum" or ":endinterface" and throw it
1939+
* away. Used while skipping.
1940+
*/
1941+
static void
1942+
skip_class_body(exarg_T *eap)
1943+
{
1944+
for (;;)
1945+
{
1946+
char_u *theline = eap->ea_getline(':', eap->cookie, 0,
1947+
GETLINE_CONCAT_ALL);
1948+
if (theline == NULL)
1949+
break;
1950+
1951+
char_u *p = theline;
1952+
int found;
1953+
1954+
// skip ':' and blanks
1955+
for (; VIM_ISWHITE(*p) || *p == ':'; ++p)
1956+
;
1957+
found = checkforcmd(&p, "endclass", 4)
1958+
|| checkforcmd(&p, "endenum", 4)
1959+
|| checkforcmd(&p, "endinterface", 5);
1960+
vim_free(theline);
1961+
if (found)
1962+
break;
1963+
}
1964+
}
1965+
19371966
/*
19381967
* Handle ":class" and ":abstract class" up to ":endclass".
19391968
* Handle ":enum" up to ":endenum".
@@ -1950,6 +1979,12 @@ ex_class(exarg_T *eap)
19501979
long start_lnum = SOURCING_LNUM;
19511980
char_u *arg = eap->arg;
19521981

1982+
if (eap->skip)
1983+
{
1984+
skip_class_body(eap);
1985+
return;
1986+
}
1987+
19531988
if (is_abstract)
19541989
{
19551990
if (STRNCMP(arg, "class", 5) != 0 || !VIM_ISWHITE(arg[5]))

0 commit comments

Comments
 (0)