diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2699,6 +2699,25 @@ to the preferences found in the file. ``PointerAlignment`` is then used only as fallback. +.. _DesignatedInitializerIndentWidth: + +**DesignatedInitializerIndentWidth** (``Integer``) :ref:`¶ ` + The number of columns to use to indent designated initializers that start + on a new line. When set to -1 (default), ``ContinuationIndentWidth`` is used. + + .. code-block:: c++ + + AlignAfterOpenBracket: AlwaysBreak + DesignatedInitializerIndentWidth: 2 + + void f() { + auto s = SomeStruct{ + .foo = "foo", + .bar = "bar", + .baz = "baz", + }; + } + .. _DisableFormat: **DisableFormat** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ ` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -316,6 +316,8 @@ Compared to ``NextLine`` style, ``NextLineOnly`` style will not try to put the initializers on the current line first, instead, it will try to put the initializers on the next line only. +- Add ``DesignatedInitializerIndentWidth`` which can be used to configure + the indentation level of designated initializers. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2020,6 +2020,22 @@ /// \version 3.7 bool DerivePointerAlignment; + /// The number of columns to use to indent designated initializers that start + /// on a new line. When set to -1 (default), ``ContinuationIndentWidth`` is + /// used. \code + /// AlignAfterOpenBracket: AlwaysBreak + /// DesignatedInitializerIndentWidth: 2 + /// + /// void f() { + /// auto s = SomeStruct{ + /// .foo = "foo", + /// .bar = "bar", + /// .baz = "baz", + /// }; + /// } + /// \endcode + int DesignatedInitializerIndentWidth; + /// Disables formatting completely. /// \version 3.7 bool DisableFormat; @@ -4236,6 +4252,8 @@ ContinuationIndentWidth == R.ContinuationIndentWidth && Cpp11BracedListStyle == R.Cpp11BracedListStyle && DerivePointerAlignment == R.DerivePointerAlignment && + DesignatedInitializerIndentWidth == + R.DesignatedInitializerIndentWidth && DisableFormat == R.DisableFormat && EmptyLineAfterAccessModifier == R.EmptyLineAfterAccessModifier && EmptyLineBeforeAccessModifier == R.EmptyLineBeforeAccessModifier && diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1656,13 +1656,20 @@ CurrentState.NestedBlockIndent); if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || opensProtoMessageField(Current, Style)) { + const FormatToken *NextNoComment = Current.getNextNonComment(); if (Current.opensBlockOrBlockTypeList(Style)) { NewIndent = Style.IndentWidth + std::min(State.Column, CurrentState.NestedBlockIndent); + } else if (NextNoComment && + NextNoComment->is(TT_DesignatedInitializerPeriod)) { + const auto DesignatedInitializerIndentWidth = + Style.DesignatedInitializerIndentWidth < 0 + ? Style.ContinuationIndentWidth + : Style.DesignatedInitializerIndentWidth; + NewIndent = CurrentState.LastSpace + DesignatedInitializerIndentWidth; } else { NewIndent = CurrentState.LastSpace + Style.ContinuationIndentWidth; } - const FormatToken *NextNoComment = Current.getNextNonComment(); bool EndsInComma = Current.MatchingParen && Current.MatchingParen->Previous && Current.MatchingParen->Previous->is(tok::comma); diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -902,6 +902,8 @@ IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); + IO.mapOptional("DesignatedInitializerIndentWidth", + Style.DesignatedInitializerIndentWidth); IO.mapOptional("DisableFormat", Style.DisableFormat); IO.mapOptional("EmptyLineAfterAccessModifier", Style.EmptyLineAfterAccessModifier); @@ -1367,6 +1369,7 @@ LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; LLVMStyle.DerivePointerAlignment = false; + LLVMStyle.DesignatedInitializerIndentWidth = -1; LLVMStyle.DisableFormat = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -245,6 +245,10 @@ SpacesBeforeTrailingComments, 1234u); CHECK_PARSE("IndentWidth: 32", IndentWidth, 32u); CHECK_PARSE("ContinuationIndentWidth: 11", ContinuationIndentWidth, 11u); + CHECK_PARSE("DesignatedInitializerIndentWidth: 34", + DesignatedInitializerIndentWidth, 34); + CHECK_PARSE("DesignatedInitializerIndentWidth: -1", + DesignatedInitializerIndentWidth, -1); CHECK_PARSE("CommentPragmas: '// abc$'", CommentPragmas, "// abc$"); Style.QualifierAlignment = FormatStyle::QAS_Right; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -4820,6 +4820,34 @@ " [3] = cccccccccccccccccccccccccccccccccccccc,\n" " [4] = dddddddddddddddddddddddddddddddddddddd,\n" " [5] = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee};"); + + auto Style = getLLVMStyleWithColumns(60); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + verifyFormat("auto s = SomeStruct{\n" + " .xxxxxxxxxxxxxxxxxx = 1,\n" + " .yyyyyyyyyyyyyyyyyy = 2,\n" + " .zzzzzzzzzzzzzzzzzz = 3};\n", + Style); + Style.DesignatedInitializerIndentWidth = 2; + verifyFormat("auto s = SomeStruct{\n" + " .xxxxxxxxxxxxxxxxxx = 1,\n" + " .yyyyyyyyyyyyyyyyyy = 2,\n" + " .zzzzzzzzzzzzzzzzzz = 3};\n", + Style); + verifyFormat("auto s = someFunctionCall(\n" + " aaaaaaaa, bbbbbbbb,\n" + " SomeStruct{\n" + " .xxxxxxxxxxxxxxxxxx = 1,\n" + " .yyyyyyyyyyyyyyyyyy = 2,\n" + " .zzzzzzzzzzzzzzzzzz = 3});\n", + Style); + Style.ContinuationIndentWidth = 8; + Style.DesignatedInitializerIndentWidth = -1; // Use ContinuationIndentWidth. + verifyFormat("auto s = SomeStruct{\n" + " .xxxxxxxxxxxxxxxxxx = 1,\n" + " .yyyyyyyyyyyyyyyyyy = 2,\n" + " .zzzzzzzzzzzzzzzzzz = 3};\n", + Style); } TEST_F(FormatTest, NestedStaticInitializers) {