]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0447: cindent does not ignore comments v9.2.0447
authormagnus-rattlehead <magnus-rattlehead@users.noreply.github.com>
Tue, 5 May 2026 20:35:32 +0000 (20:35 +0000)
committerChristian Brabandt <cb@256bit.org>
Tue, 5 May 2026 21:14:33 +0000 (21:14 +0000)
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:  #4
fixes:  #648
fixes:  #19578
closes: #19581
closes: #20111

Signed-off-by: magnus-rattlehead <guranjakustivi@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/version9.txt
src/cindent.c
src/search.c
src/testdir/test_cindent.vim
src/version.c
src/vim.h

index 114bdf7dacd2d2eb8b9b9e89031b10a40d4241af..a1b9afce713e036af31d9eb5a898ad1d54f581b8 100644 (file)
@@ -1,4 +1,4 @@
-*version9.txt* For Vim version 9.2.  Last change: 2026 May 02
+*version9.txt* For Vim version 9.2.  Last change: 2026 May 05
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -52625,6 +52625,7 @@ Other ~
 - Added the "u" flag to 'shortmess' to silence undo/redo messages: |shm-u|
 - |:command-completion-customlist| can return a list of dictionaries with
   kind/menu/info/abbr for the popup menu.
+- |C-indenting| detects comments better.
 
 Platform specific ~
 -----------------
index ddd268176b72f6d959b406ee2d403a9b553f27d7..94c01db7e80dbc30f505ba9beb88ec4bc30d2fbf 100644 (file)
@@ -1153,7 +1153,7 @@ find_match_char(int c, int ind_maxparen)  // XXX
     cursor_save = curwin->w_cursor;
     ind_maxp_wk = ind_maxparen;
 retry:
-    if ((trypos = findmatchlimit(NULL, c, 0, ind_maxp_wk)) != NULL)
+    if ((trypos = findmatchlimit(NULL, c, FM_SKIPCOMM, ind_maxp_wk)) != NULL)
     {
        // check if the ( is in a // comment
        if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
@@ -1396,7 +1396,7 @@ cin_iswhileofdo (char_u *p, linenr_T lnum)        // XXX
            ++p;
            ++curwin->w_cursor.col;
        }
-       if ((trypos = findmatchlimit(NULL, 0, 0,
+       if ((trypos = findmatchlimit(NULL, 0, FM_SKIPCOMM,
                                              curbuf->b_ind_maxparen)) != NULL
                && *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
            retval = TRUE;
@@ -1732,7 +1732,7 @@ 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;
@@ -2547,7 +2547,7 @@ get_c_indent(void)
                line = ml_get_curline();
                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
index bb85873dc0f05103e9a3390ecfbaf664f60c561d..12977dc8fafba616879d193e56cb48bff8855f81 100644 (file)
@@ -2165,7 +2165,7 @@ find_mps_values(
  * 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!)
+ *       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
@@ -2201,6 +2201,8 @@ findmatchlimit(
     int                comment_col = MAXCOL;   // start of / / comment
     int                lispcomm = FALSE;       // inside of Lisp-style comment
     int                lisp = curbuf->b_p_lisp; // engage Lisp-specific hacks ;)
+    int                skip_comments = (flags & FM_SKIPCOMM) != 0;
+    int                in_block_comment = FALSE; // inside /* */ block comment
 
     pos = curwin->w_cursor;
     pos.coladd = 0;
@@ -2429,10 +2431,14 @@ findmatchlimit(
     CLEAR_POS(&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)
     {
@@ -2460,11 +2466,15 @@ findmatchlimit(
                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
            {
@@ -2495,7 +2505,7 @@ findmatchlimit(
                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
@@ -2507,6 +2517,37 @@ findmatchlimit(
            }
        }
 
+       // 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.
         */
@@ -2750,6 +2791,11 @@ findmatchlimit(
                    && check_prevcol(linep, pos.col - 1, '#', NULL))
                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 == TRUE)
index 4884dbb304d4adfa83260957db4837ae75bb33c6..f050d82f8c8b94f24906c8870ec1a28947b6731b 100644 (file)
@@ -5526,5 +5526,85 @@ def Test_find_brace_backwards()
   bwipe!
 enddef
 
+" Brackets inside comments must not affect C indent calculation (FM_SKIPCOMM)
+def Test_cindent_comment_brackets()
+  # stray } in inline block comment must not confuse enclosing-brace search
+  new
+  setl cindent sw=4
+  var code =<< trim [CODE]
+  int foo() {
+      /* } */
+      int bar;
+  }
+  [CODE]
+  setline(1, code)
+  cursor(3, 1)
+  normal ==
+  assert_equal('    int bar;', getline(3))
+  bwipe!
+
+  # stray } in // line comment: same
+  new
+  setl cindent sw=4
+  var code2 =<< trim [CODE]
+  int foo() {
+      // }
+      int bar;
+  }
+  [CODE]
+  setline(1, code2)
+  cursor(3, 1)
+  normal ==
+  assert_equal('    int bar;', getline(3))
+  bwipe!
+
+  # stray } on continuation line inside multi-line block comment
+  new
+  setl cindent sw=4
+  var code3 =<< trim [CODE]
+  int foo() {
+      /*
+         }
+      */
+      int bar;
+  }
+  [CODE]
+  setline(1, code3)
+  cursor(5, 1)
+  normal ==
+  assert_equal('    int bar;', getline(5))
+  bwipe!
+
+  # { in inline block comment must not be treated as enclosing brace
+  new
+  setl cindent sw=4
+  var code4 =<< trim [CODE]
+  int foo() {
+      /* { */
+      int bar;
+  }
+  [CODE]
+  setline(1, code4)
+  cursor(3, 1)
+  normal ==
+  assert_equal('    int bar;', getline(3))
+  bwipe!
+
+  # ) in inline block comment must not be treated as enclosing brace
+  new
+  setl cindent sw=4
+  var code5 =<< trim [CODE]
+  some_func(arg1,
+      /* ) */ arg2,
+      arg3);
+  [CODE]
+  setline(1, code5)
+  cursor(3, 1)
+  normal ==
+  assert_equal('    arg3);', getline(3))
+  bwipe!
+
+enddef
+
 
 " vim: shiftwidth=2 sts=2 expandtab
index 2f0af9ba1143fbb191f2c9686ffe70d87a82813c..78efc6c77729fce86880aa9b0639a8afa2000bc2 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    447,
 /**/
     446,
 /**/
index 37183f130ae1e0ea2e7f0e720fdcf77c87c9303a..8949e867deff3cc76526c700db1173772ce518a0 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -1095,7 +1095,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define FM_BACKWARD    0x01    // search backwards
 #define FM_FORWARD     0x02    // search forwards
 #define FM_BLOCKSTOP   0x04    // stop at start/end of block
-#define FM_SKIPCOMM    0x08    // skip comments
+#define FM_SKIPCOMM    0x08    // skip comments (cursor must start outside)
 
 // Values for action argument for do_buffer() and close_buffer()
 #define DOBUF_GOTO     0       // go to specified buffer