patch 9.1.1626: cindent: does not handle compound literals

Commit: 
https://github.com/vim/vim/commit/5ba6e41d37ec29fc8360a4f06d4e95c63eb013ab
Author: Anttoni Erkkilä <anttoni.erkk...@protonmail.com>
Date:   Tue Aug 12 21:59:06 2025 +0200

    patch 9.1.1626: cindent: does not handle compound literals
    
    Problem:  C-indent does not handle compound literals
              (@44100hertz, @Jorenar)
    Solution: Detect and handle compound literal and structure
              initialization (Anttoni Erkkilä)
    
    match '=' or "return" optionally followed by &, (typecast), {
    Fixes also initialization which begins with multiple opening braces.
    
    fixes: #2090
    fixes: #12491
    closes: #17865
    
    Signed-off-by: Anttoni Erkkilä <anttoni.erkk...@protonmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 1052e7e51..fb278f0ab 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2025 Aug 08
+*version9.txt*  For Vim version 9.1.  Last change: 2025 Aug 12
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41736,6 +41736,7 @@ Others: ~
 - |gv| works in operator pending mode and does not abort
 - The close button shown in the non-GUI 'tabline' will only be visible if the
   'mouse' option contains either "a" or any of the flags "n", "v", or "i".
+- |C-indenting| handles compound literals.
 
                                                        *added-9.2*
 Added ~
diff --git a/src/cindent.c b/src/cindent.c
index e1f744676..3dea1079e 100644
--- a/src/cindent.c
+++ b/src/cindent.c
@@ -690,10 +690,9 @@ cin_islabel(void)          // XXX
 /*
  * Return TRUE if string "s" ends with the string "find", possibly followed by
  * white space and comments.  Skip strings and comments.
- * Ignore "ignore" after "find" if it's not NULL.
  */
     static int
-cin_ends_in(char_u *s, char_u *find, char_u *ignore)
+cin_ends_in(char_u *s, char_u *find)
 {
     char_u     *p = s;
     char_u     *r;
@@ -705,8 +704,6 @@ cin_ends_in(char_u *s, char_u *find, char_u *ignore)
        if (STRNCMP(p, find, len) == 0)
        {
            r = skipwhite(p + len);
-           if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
-               r = skipwhite(r + STRLEN(ignore));
            if (cin_nocode(r))
                return TRUE;
        }
@@ -717,9 +714,77 @@ cin_ends_in(char_u *s, char_u *find, char_u *ignore)
 }
 
 /*
- * Recognize structure initialization and enumerations:
+ * Strings can be concatenated with comments between:
+ * "string0" |*comment*| "string1"
+ */
+    static char_u *
+cin_skip_comment_and_string(char_u *s)
+{
+    char_u *r = NULL, *p = s;
+    do
+    {
+       r = p;
+       p = cin_skipcomment(p);
+       if (*p)
+           p = skip_string(p);
+    } while (p != r);
+    return p;
+}
+
+/*
+ * Recognize structure or compound literal initialization:
+ * =|return [&][(typecast)] [{]
+ * The number of opening braces is arbitrary.
+ */
+    static int
+cin_is_compound_init(char_u *s)
+{
+    char_u *p = s, *r = NULL;
+
+    while (*p)
+    {
+       if (*p == '=')
+           p = r = cin_skipcomment(p + 1);
+       else if (!STRNCMP(p, "return", 6) && !vim_isIDc(p[6])
+               && (p == s || (p > s && !vim_isIDc(p[-1]))))
+           p = r = cin_skipcomment(p + 6);
+       else
+           p = cin_skip_comment_and_string(p + 1);
+    }
+    if (!r)
+       return FALSE;
+    p = r; // p points now after '=' or "return"
+
+    if (cin_nocode(p))
+       return TRUE;
+
+    if (*p == '&')
+       p = cin_skipcomment(p + 1);
+
+    if (*p == '(') // skip a typecast
+    {
+       int open_count = 1;
+       do
+       {
+           p = cin_skip_comment_and_string(p + 1);
+           if (cin_nocode(p))
+               return TRUE;
+           open_count += (*p == '(') - (*p == ')');
+       } while (open_count);
+       p = cin_skipcomment(p + 1);
+       if (cin_nocode(p))
+           return TRUE;
+    }
+
+    while (*p == '{')
+       p = cin_skipcomment(p + 1);
+    return cin_nocode(p);
+}
+
+/*
+ * Recognize enumerations:
  * "[typedef] [static|public|protected|private] enum"
- * "[typedef] [static|public|protected|private] = {"
+ * Call another function to recognize structure initialization.
  */
     static int
 cin_isinit(void)
@@ -753,10 +818,7 @@ cin_isinit(void)
     if (cin_starts_with(s, "enum"))
        return TRUE;
 
-    if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
-       return TRUE;
-
-    return FALSE;
+    return cin_is_compound_init(s);
 }
 
 // Maximum number of lines to search back for a "namespace" line.
@@ -1634,7 +1696,7 @@ get_baseclass_amount(int col)
        if (find_last_paren(ml_get_curline(), '(', ')')
                && (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
            amount = get_indent_lnum(trypos->lnum); // XXX
-       if (!cin_ends_in(ml_get_curline(), (char_u *)",", NULL))
+       if (!cin_ends_in(ml_get_curline(), (char_u *)","))
            amount += curbuf->b_ind_cpp_baseclass;
     }
     else
@@ -2505,7 +2567,7 @@ get_c_indent(void)
                    cur_amount = MAXCOL;
                    l = ml_get(our_paren_pos.lnum);
                    if (curbuf->b_ind_unclosed_wrapped
-                                      && cin_ends_in(l, (char_u *)"(", NULL))
+                                      && cin_ends_in(l, (char_u *)"("))
                    {
                        // look for opening unmatched paren, indent one level
                        // for each additional level
@@ -3702,8 +3764,8 @@ term_again:
            && !cin_nocode(theline)
            && vim_strchr(theline, '{') == NULL
            && vim_strchr(theline, '}') == NULL
-           && !cin_ends_in(theline, (char_u *)":", NULL)
-           && !cin_ends_in(theline, (char_u *)",", NULL)
+           && !cin_ends_in(theline, (char_u *)":")
+           && !cin_ends_in(theline, (char_u *)",")
            && cin_isfuncdecl(NULL, cur_curpos.lnum + 1,
                              cur_curpos.lnum + 1)
            && !cin_isterminated(theline, FALSE, TRUE))
@@ -3764,7 +3826,7 @@ term_again:
        // } foo,
        //   bar;
        n = 0;
-       if (cin_ends_in(l, (char_u *)",", NULL)
+       if (cin_ends_in(l, (char_u *)",")
                     || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\'))
        {
            // take us back to opening paren
@@ -3812,14 +3874,14 @@ term_again:
        // comments) align at column 0.  For example:
        // char *string_array[] = { "foo",
        //     / * x * / "b};ar" }; / * foobar * /
-       if (cin_ends_in(l, (char_u *)"};", NULL))
+       if (cin_ends_in(l, (char_u *)"};"))
            break;
 
        // If the previous line ends on '[' we are probably in an
        // array constant:
        // something = [
        //     234,  <- extra indent
-       if (cin_ends_in(l, (char_u *)"[", NULL))
+       if (cin_ends_in(l, (char_u *)"["))
        {
            amount = get_indent() + ind_continuation;
            break;
@@ -3840,7 +3902,7 @@ term_again:
                    break;
            }
            if (curwin->w_cursor.lnum > 0
-                           && cin_ends_in(look, (char_u *)"}", NULL))
+                           && cin_ends_in(look, (char_u *)"}"))
                break;
 
            curwin->w_cursor = curpos_save;
@@ -3860,10 +3922,10 @@ term_again:
        // int foo,
        //     bar;
        // indent_to_0 here;
-       if (cin_ends_in(l, (char_u *)";", NULL))
+       if (cin_ends_in(l, (char_u *)";"))
        {
            l = ml_get(curwin->w_cursor.lnum - 1);
-           if (cin_ends_in(l, (char_u *)",", NULL)
+           if (cin_ends_in(l, (char_u *)",")
                    || (*l != NUL && l[STRLEN(l) - 1] == '\'))
                break;
            l = ml_get_curline();
diff --git a/src/testdir/test_indent.vim b/src/testdir/test_indent.vim
index e20694792..52d7be139 100644
--- a/src/testdir/test_indent.vim
+++ b/src/testdir/test_indent.vim
@@ -119,6 +119,31 @@ func Test_userlabel_indent()
   close!
 endfunc
 
+" Test that struct members are aligned
+func Test_struct_indent()
+  new
+  call setline(1, ['struct a a = {', '1,', '1,'])
+  normal gg=G
+  call assert_equal(getline(2), getline(3))
+
+  call setline(1, 'a = (struct a) {')
+  normal gg=G
+  call assert_equal(getline(2), getline(3))
+
+  call setline(1, 'void *ptr = &(static struct a) {{')
+  normal gg=G
+  call assert_equal(getline(2), getline(3))
+
+  call setline(1, 'a = (macro(arg1, "str)))")) {')
+  normal gg=G
+  call assert_equal(getline(2), getline(3))
+
+  call setline(1, 'return (struct a) {')
+  normal gg=G
+  call assert_equal(getline(2), getline(3))
+  close!
+endfunc
+
 " Test for 'copyindent'
 func Test_copyindent()
   new
diff --git a/src/version.c b/src/version.c
index d68e63d11..071eca3f0 100644
--- a/src/version.c
+++ b/src/version.c
@@ -719,6 +719,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1626,
 /**/
     1625,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1ulvOh-00B50y-Mn%40256bit.org.

Raspunde prin e-mail lui