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,24 @@ to the preferences found in the file. ``PointerAlignment`` is then used only as fallback. +.. _DesignatedInitializerIndentWidth: + +**DesignatedInitializerIndentWidth** (``Unsigned``) + The number of columns to use to indent designated initializers that start on a new line. + + .. 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,17 @@ /// \version 3.7 bool DerivePointerAlignment; + /// The number of columns to use to indent designated initializers that start on a new line. + /// \code + /// void f() { + /// auto s = SomeStruct{ + /// .foo = "foo", + /// .bar = "bar", + /// .baz = "baz", + /// }; + /// } + unsigned DesignatedInitializerIndentWidth; + /// Disables formatting completely. /// \version 3.7 bool DisableFormat; @@ -4236,6 +4247,7 @@ 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,15 @@ 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->is(TT_DesignatedInitializerPeriod)) { + NewIndent = CurrentState.LastSpace + Style.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,7 @@ 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 +1368,7 @@ LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; LLVMStyle.DerivePointerAlignment = false; + LLVMStyle.DesignatedInitializerIndentWidth = 4; LLVMStyle.DisableFormat = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; 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,25 @@ " [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); } TEST_F(FormatTest, NestedStaticInitializers) {