mirror of
https://github.com/neovim/neovim.git
synced 2026-05-06 08:26:45 -04:00
vim-patch:9.2.0447: cindent does not ignore comments (#39622)
Problem: When find_start_brace() scans backwards for the enclosing
block, '{' and '}' inside // and /* */ comments are counted,
producing wrong indent for code following such comments
(rendcrx).
Solution: Implement FM_SKIPCOMM in findmatchlimit() to track block-
comment state and skip matches inside comments. Pass
FM_SKIPCOMM from cindent's call sites
(find_start_brace, find_match_char, cin_iswhileofdo,
get_c_indent).
fixes: vim/vim#4
fixes: vim/vim#648
fixes: vim/vim#19578
closes: vim/vim#19581
closes: vim/vim#20111
https://github.com/vim/vim/commit/c06002f3cb07c374bfc1a1310cf13ee1914e86da
Co-authored-by: magnus-rattlehead <magnus-rattlehead@users.noreply.github.com>
This commit is contained in:
+4
-4
@@ -1079,7 +1079,7 @@ static int cin_iswhileofdo(const char *p, linenr_T lnum) // XXX
|
||||
p++;
|
||||
curwin->w_cursor.col++;
|
||||
}
|
||||
if ((trypos = findmatchlimit(NULL, 0, 0, curbuf->b_ind_maxparen)) != NULL
|
||||
if ((trypos = findmatchlimit(NULL, 0, FM_SKIPCOMM, curbuf->b_ind_maxparen)) != NULL
|
||||
&& *cin_skipcomment(ml_get_pos(trypos) + 1) == ';') {
|
||||
retval = true;
|
||||
}
|
||||
@@ -1484,7 +1484,7 @@ static pos_T *find_start_brace(void) // XXX
|
||||
static pos_T pos_copy;
|
||||
|
||||
cursor_save = curwin->w_cursor;
|
||||
while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL) {
|
||||
while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP | FM_SKIPCOMM, 0)) != NULL) {
|
||||
pos_copy = *trypos; // copy pos_T, next findmatch will change it
|
||||
trypos = &pos_copy;
|
||||
curwin->w_cursor = *trypos;
|
||||
@@ -1519,7 +1519,7 @@ static pos_T *find_match_char(char c, int ind_maxparen)
|
||||
cursor_save = curwin->w_cursor;
|
||||
ind_maxp_wk = ind_maxparen;
|
||||
retry:
|
||||
if ((trypos = findmatchlimit(NULL, (uint8_t)c, 0, ind_maxp_wk)) != NULL) {
|
||||
if ((trypos = findmatchlimit(NULL, (uint8_t)c, FM_SKIPCOMM, ind_maxp_wk)) != NULL) {
|
||||
// check if the ( is in a // comment
|
||||
if ((colnr_T)cin_skip2pos(trypos) > trypos->col) {
|
||||
ind_maxp_wk = ind_maxparen - (cursor_save.lnum - trypos->lnum);
|
||||
@@ -2299,7 +2299,7 @@ int get_c_indent(void)
|
||||
line = get_cursor_line_ptr();
|
||||
look_col = (int)(look - line);
|
||||
curwin->w_cursor.col = look_col + 1;
|
||||
if ((trypos = findmatchlimit(NULL, ')', 0,
|
||||
if ((trypos = findmatchlimit(NULL, ')', FM_SKIPCOMM,
|
||||
curbuf->b_ind_maxparen))
|
||||
!= NULL
|
||||
&& trypos->lnum == our_paren_pos.lnum
|
||||
|
||||
+54
-7
@@ -1763,10 +1763,10 @@ static void find_mps_values(int *initc, int *findc, bool *backwards, bool switch
|
||||
// '#' look for preprocessor directives
|
||||
// 'R' look for raw string start: R"delim(text)delim" (only backwards)
|
||||
//
|
||||
// flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
|
||||
// FM_FORWARD search forwards (when initc is '/', '*' or '#')
|
||||
// FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
|
||||
// FM_SKIPCOMM skip comments (not implemented yet!)
|
||||
// flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
|
||||
// FM_FORWARD search forwards (when initc is '/', '*' or '#')
|
||||
// FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
|
||||
// FM_SKIPCOMM skip over comments (cursor must start outside a block comment)
|
||||
//
|
||||
// "oap" is only used to set oap->motion_type for a linewise motion, it can be
|
||||
// NULL
|
||||
@@ -1788,6 +1788,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
int comment_col = MAXCOL; // start of / / comment
|
||||
bool lispcomm = false; // inside of Lisp-style comment
|
||||
bool lisp = curbuf->b_p_lisp; // engage Lisp-specific hacks ;)
|
||||
bool skip_comments = (flags & FM_SKIPCOMM) != 0;
|
||||
bool in_block_comment = false; // inside / * * / block comment
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
pos.coladd = 0;
|
||||
@@ -1985,12 +1987,17 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
clearpos(&match_pos);
|
||||
|
||||
// backward search: Check if this line contains a single-line comment
|
||||
if ((backwards && comment_dir) || lisp) {
|
||||
if ((backwards && comment_dir) || lisp || skip_comments) {
|
||||
comment_col = check_linecomment(linep);
|
||||
}
|
||||
if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col) {
|
||||
lispcomm = true; // find match inside this comment
|
||||
}
|
||||
// skip // comment portion at starting position
|
||||
if (skip_comments && !in_block_comment && comment_col != MAXCOL
|
||||
&& backwards && pos.col > (colnr_T)comment_col) {
|
||||
pos.col = comment_col;
|
||||
}
|
||||
|
||||
while (!got_int) {
|
||||
// Go to the next position, forward or backward. We could use
|
||||
@@ -2016,12 +2023,16 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
line_breakcheck();
|
||||
|
||||
// Check if this line contains a single-line comment
|
||||
if (comment_dir || lisp) {
|
||||
if (comment_dir || lisp || skip_comments) {
|
||||
comment_col = check_linecomment(linep);
|
||||
}
|
||||
// skip comment
|
||||
if (lisp && comment_col != MAXCOL) {
|
||||
pos.col = comment_col;
|
||||
} else if (skip_comments && !in_block_comment
|
||||
&& comment_col != MAXCOL
|
||||
&& pos.col > (colnr_T)comment_col) {
|
||||
pos.col = comment_col;
|
||||
}
|
||||
} else {
|
||||
pos.col--;
|
||||
@@ -2049,7 +2060,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
pos.col = 0;
|
||||
do_quotes = -1;
|
||||
line_breakcheck();
|
||||
if (lisp) { // find comment pos in new line
|
||||
if (lisp || skip_comments) { // find comment pos in new line
|
||||
comment_col = check_linecomment(linep);
|
||||
}
|
||||
} else {
|
||||
@@ -2057,6 +2068,35 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
}
|
||||
}
|
||||
|
||||
// Track block comment state when FM_SKIPCOMM is set.
|
||||
// Backward: '/' of end-marker enters comment; '*' of start-marker exits.
|
||||
// Forward: '/' of start-marker enters comment; '/' of end-marker exits.
|
||||
if (skip_comments && !comment_dir) {
|
||||
if (backwards) {
|
||||
// Guard pos.col < comment_col: don't misread '* /' at the '//'
|
||||
// position as a block-comment end-marker.
|
||||
if (!in_block_comment && pos.col > 0
|
||||
&& linep[pos.col - 1] == '*' && linep[pos.col] == '/'
|
||||
&& (comment_col == MAXCOL || (int)pos.col < comment_col)) {
|
||||
in_block_comment = true;
|
||||
} else if (in_block_comment && pos.col > 0
|
||||
&& linep[pos.col - 1] == '/' && linep[pos.col] == '*') {
|
||||
in_block_comment = false;
|
||||
}
|
||||
} else {
|
||||
// Guard pos.col < comment_col: don't treat '/ *' inside a '//'
|
||||
// comment as a block-comment start-marker.
|
||||
if (!in_block_comment && linep[pos.col] == '/'
|
||||
&& linep[pos.col + 1] == '*'
|
||||
&& (comment_col == MAXCOL || (int)pos.col < comment_col)) {
|
||||
in_block_comment = true;
|
||||
} else if (in_block_comment && pos.col > 0
|
||||
&& linep[pos.col - 1] == '*' && linep[pos.col] == '/') {
|
||||
in_block_comment = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
|
||||
if (pos.col == 0 && (flags & FM_BLOCKSTOP)
|
||||
&& (linep[0] == '{' || linep[0] == '}')) {
|
||||
@@ -2258,6 +2298,13 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip matches inside comments when FM_SKIPCOMM is set.
|
||||
if (skip_comments
|
||||
&& (in_block_comment
|
||||
|| (comment_col != MAXCOL && (int)pos.col >= comment_col))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for match outside of quotes, and inside of
|
||||
// quotes when the start is also inside of quotes.
|
||||
if ((!inquote || start_in_quotes == kTrue)
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ enum {
|
||||
FM_BACKWARD = 0x01, ///< search backwards
|
||||
FM_FORWARD = 0x02, ///< search forwards
|
||||
FM_BLOCKSTOP = 0x04, ///< stop at start/end of block
|
||||
FM_SKIPCOMM = 0x08, ///< skip comments
|
||||
FM_SKIPCOMM = 0x08, ///< skip comments (cursor must start outside)
|
||||
};
|
||||
|
||||
/// Values for sub_cmd and which_pat argument for search_regcomp()
|
||||
|
||||
@@ -5512,5 +5512,85 @@ func Test_find_brace_backwards()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Brackets inside comments must not affect C indent calculation (FM_SKIPCOMM)
|
||||
func Test_cindent_comment_brackets()
|
||||
" stray } in inline block comment must not confuse enclosing-brace search
|
||||
new
|
||||
setl cindent sw=4
|
||||
let code =<< trim [CODE]
|
||||
int foo() {
|
||||
/* } */
|
||||
int bar;
|
||||
}
|
||||
[CODE]
|
||||
call setline(1, code)
|
||||
call cursor(3, 1)
|
||||
normal ==
|
||||
call assert_equal(' int bar;', getline(3))
|
||||
bwipe!
|
||||
|
||||
" stray } in // line comment: same
|
||||
new
|
||||
setl cindent sw=4
|
||||
let code2 =<< trim [CODE]
|
||||
int foo() {
|
||||
// }
|
||||
int bar;
|
||||
}
|
||||
[CODE]
|
||||
call setline(1, code2)
|
||||
call cursor(3, 1)
|
||||
normal ==
|
||||
call assert_equal(' int bar;', getline(3))
|
||||
bwipe!
|
||||
|
||||
" stray } on continuation line inside multi-line block comment
|
||||
new
|
||||
setl cindent sw=4
|
||||
let code3 =<< trim [CODE]
|
||||
int foo() {
|
||||
/*
|
||||
}
|
||||
*/
|
||||
int bar;
|
||||
}
|
||||
[CODE]
|
||||
call setline(1, code3)
|
||||
call cursor(5, 1)
|
||||
normal ==
|
||||
call assert_equal(' int bar;', getline(5))
|
||||
bwipe!
|
||||
|
||||
" { in inline block comment must not be treated as enclosing brace
|
||||
new
|
||||
setl cindent sw=4
|
||||
let code4 =<< trim [CODE]
|
||||
int foo() {
|
||||
/* { */
|
||||
int bar;
|
||||
}
|
||||
[CODE]
|
||||
call setline(1, code4)
|
||||
call cursor(3, 1)
|
||||
normal ==
|
||||
call assert_equal(' int bar;', getline(3))
|
||||
bwipe!
|
||||
|
||||
" ) in inline block comment must not be treated as enclosing brace
|
||||
new
|
||||
setl cindent sw=4
|
||||
let code5 =<< trim [CODE]
|
||||
some_func(arg1,
|
||||
/* ) */ arg2,
|
||||
arg3);
|
||||
[CODE]
|
||||
call setline(1, code5)
|
||||
call cursor(3, 1)
|
||||
normal ==
|
||||
call assert_equal(' arg3);', getline(3))
|
||||
bwipe!
|
||||
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
Reference in New Issue
Block a user