https://github.com/gedare updated https://github.com/llvm/llvm-project/pull/108332
>From c7b34d10bb8f937f9a11778c327f82cee8e60fe5 Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Thu, 20 Jun 2024 17:35:39 -0600 Subject: [PATCH 1/5] Format: add AlignAfterOpenBracketOptions Introduce new options to allow for control of AlwaysBreak and BlockIndent selectively for If conditional statements (as currently supported), other conditional statements (for/while/switch), and other statements. Fixes #67738. Fixes #79176. Fixes #80123. --- clang/docs/ClangFormatStyleOptions.rst | 60 +++++++++ clang/include/clang/Format/Format.h | 73 +++++++++++ clang/lib/Format/ContinuationIndenter.cpp | 44 +++++-- clang/lib/Format/Format.cpp | 26 ++++ clang/lib/Format/TokenAnnotator.cpp | 8 +- clang/unittests/Format/ConfigParseTest.cpp | 12 ++ clang/unittests/Format/FormatTest.cpp | 143 +++++++++++++++++++++ 7 files changed, 355 insertions(+), 11 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index bbb912eb10e94d..7ad59fa7a7be1f 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -246,6 +246,66 @@ the configuration (without a prefix: ``Auto``). +.. _AlignAfterOpenBracketBreak: + +**AlignAfterOpenBracketBreak** (``AlignAfterOpenBracketCustom``) :versionbadge:`clang-format 20` :ref:`¶ <AlignAfterOpenBracketBreak>` + Control of when ``AlignAfterOpenBracket`` breaks an opening bracket. + + If ``AlignAfterOpenBracket`` is set to ``AlwaysBreak`` or ``BlockIndent``, + use this to specify how different cases of breaking the opening brackets + should be handled. Otherwise, this is ignored. Setting any of these to + ``false`` will cause them to not break. At least one of these must be set + to ``true``, otherwise a default (backward compatible) breaking behavior + is used. This is ignored for ``Align`` and ``DontAlign``. + + .. code-block:: c++ + + # Example of usage: + AlignAfterOpenBracket: AlwaysBreak + AlignAfterOpenBracketBreak: + InIfConditionalStatements: true + InOtherConditionalStatements: false + Other: true + + Nested configuration flags: + + Precise control over breaking the opening bracket of + ``AlignAfterOpenBracket``. + + .. code-block:: c++ + + # Should be declared this way: + AlignAfterOpenBracketBreak: + InIfConditionalStatements: true + InOtherConditionalStatements: false + Other: true + + * ``bool InIfConditionalStatements`` Break inside if/else if statements. + + .. code-block:: c++ + + true: false: + if constexpr ( vs. if constexpr (a || + a || b) b) + + * ``bool InOtherConditionalStatements`` Break inside conditional statements not covered by preceding options. + (``for/while/switch...``). + + .. code-block:: c++ + + true: false: + while ( vs. while (a && + a && b ) { b) { + + * ``bool Other`` Break inside brackets not covered by preceding options. + + .. code-block:: c++ + + true: false: + someLongFunction( vs. someLongFunction(argument1, + argument1, argument2); argument2); + + .. _AlignArrayOfStructures: **AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`¶ <AlignArrayOfStructures>` diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 6f432d1d503154..6488de9d200512 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -106,6 +106,78 @@ struct FormatStyle { /// \version 3.8 BracketAlignmentStyle AlignAfterOpenBracket; + /// Precise control over breaking the opening bracket of + /// ``AlignAfterOpenBracket``. + /// \code + /// # Should be declared this way: + /// AlignAfterOpenBracketBreak: + /// InIfConditionalStatements: true + /// InOtherConditionalStatements: false + /// Other: true + /// \endcode + struct AlignAfterOpenBracketCustom { + /// Break inside if/else if statements. + /// \code + /// true: false: + /// if constexpr ( vs. if constexpr (a || + /// a || b) b) + /// \endcode + bool InIfConditionalStatements; + /// Break inside conditional statements not covered by preceding options. + /// (``for/while/switch...``). + /// \code + /// true: false: + /// while ( vs. while (a && + /// a && b ) { b) { + /// \endcode + bool InOtherConditionalStatements; + /// Break inside brackets not covered by preceding options. + /// \code + /// true: false: + /// someLongFunction( vs. someLongFunction(argument1, + /// argument1, argument2); argument2); + /// \endcode + bool Other; + + AlignAfterOpenBracketCustom() + : InIfConditionalStatements(false), InOtherConditionalStatements(false), + Other(false) {} + + AlignAfterOpenBracketCustom(bool InIfConditionalStatements, + bool InOtherConditionalStatements, bool Other) + : InIfConditionalStatements(InIfConditionalStatements), + InOtherConditionalStatements(InOtherConditionalStatements), + Other(Other) {} + + bool operator==(const AlignAfterOpenBracketCustom &R) const { + return InIfConditionalStatements == R.InIfConditionalStatements && + InOtherConditionalStatements == R.InOtherConditionalStatements && + Other == R.Other; + } + bool operator!=(const AlignAfterOpenBracketCustom &R) const { + return !(*this == R); + } + }; + + /// Control of when ``AlignAfterOpenBracket`` breaks an opening bracket. + /// + /// If ``AlignAfterOpenBracket`` is set to ``AlwaysBreak`` or ``BlockIndent``, + /// use this to specify how different cases of breaking the opening brackets + /// should be handled. Otherwise, this is ignored. Setting any of these to + /// ``false`` will cause them to not break. At least one of these must be set + /// to ``true``, otherwise a default (backward compatible) breaking behavior + /// is used. This is ignored for ``Align`` and ``DontAlign``. + /// \code + /// # Example of usage: + /// AlignAfterOpenBracket: AlwaysBreak + /// AlignAfterOpenBracketBreak: + /// InIfConditionalStatements: true + /// InOtherConditionalStatements: false + /// Other: true + /// \endcode + /// \version 20 + AlignAfterOpenBracketCustom AlignAfterOpenBracketBreak; + /// Different style for aligning array initializers. enum ArrayInitializerAlignmentStyle : int8_t { /// Align array column and left justify the columns e.g.: @@ -5198,6 +5270,7 @@ struct FormatStyle { bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignAfterOpenBracket == R.AlignAfterOpenBracket && + AlignAfterOpenBracketBreak == R.AlignAfterOpenBracketBreak && AlignArrayOfStructures == R.AlignArrayOfStructures && AlignConsecutiveAssignments == R.AlignConsecutiveAssignments && AlignConsecutiveBitFields == R.AlignConsecutiveBitFields && diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index c311deaa17bb0e..8f8a07f64dfce0 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -799,6 +799,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // parenthesis by disallowing any further line breaks if there is no line // break after the opening parenthesis. Don't break if it doesn't conserve // columns. + auto IsOtherConditional = [&](const FormatToken &Tok) { + return Tok.isOneOf(tok::kw_for, tok::kw_while, tok::kw_switch) || + (Style.isJavaScript() && Tok.is(Keywords.kw_await) && Tok.Previous && + Tok.Previous->is(tok::kw_for)); + }; auto IsOpeningBracket = [&](const FormatToken &Tok) { auto IsStartOfBracedList = [&]() { return Tok.is(tok::l_brace) && Tok.isNot(BK_Block) && @@ -811,10 +816,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, if (!Tok.Previous) return true; if (Tok.Previous->isIf()) - return Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak; - return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, - tok::kw_switch) && - !(Style.isJavaScript() && Tok.Previous->is(Keywords.kw_await)); + return Style.AlignAfterOpenBracketBreak.InIfConditionalStatements; + if (IsOtherConditional(*Tok.Previous)) + return Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements; + return !Tok.Previous->is(TT_CastRParen) && + Style.AlignAfterOpenBracketBreak.Other; }; auto IsFunctionCallParen = [](const FormatToken &Tok) { return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && @@ -851,10 +857,15 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, Tok.isOneOf(tok::ellipsis, Keywords.kw_await))) { return true; } - const auto *Previous = Tok.Previous; - if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen, - TT_LambdaDefinitionLParen) && - !IsFunctionCallParen(*Previous))) { + const auto *Previous = TokAfterLParen.Previous; + assert(Previous); // IsOpeningBracket(Previous) + if (Previous->Previous && (Previous->Previous->isIf() || + IsOtherConditional(*Previous->Previous))) { + return false; + } + if (!Previous->isOneOf(TT_FunctionDeclarationLParen, + TT_LambdaDefinitionLParen) && + !IsFunctionCallParen(*Previous)) { return true; } if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) @@ -1232,8 +1243,21 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, } if (PreviousNonComment && PreviousNonComment->is(tok::l_paren)) { - CurrentState.BreakBeforeClosingParen = - Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent; + CurrentState.BreakBeforeClosingParen = false; + if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) { + auto Previous = PreviousNonComment->Previous; + if (Previous && Previous->isIf()) { + CurrentState.BreakBeforeClosingParen = + Style.AlignAfterOpenBracketBreak.InIfConditionalStatements; + } else if (Previous && Previous->isOneOf(tok::kw_for, tok::kw_while, + tok::kw_switch)) { + CurrentState.BreakBeforeClosingParen = + Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements; + } else { + CurrentState.BreakBeforeClosingParen = + Style.AlignAfterOpenBracketBreak.Other; + } + } } if (CurrentState.AvoidBinPacking) { diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index f02bf95cfeed7e..98842c0afeed18 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -215,6 +215,16 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { } }; +template <> struct MappingTraits<FormatStyle::AlignAfterOpenBracketCustom> { + static void mapping(IO &IO, FormatStyle::AlignAfterOpenBracketCustom &Value) { + IO.mapOptional("InIfConditionalStatements", + Value.InIfConditionalStatements); + IO.mapOptional("InOtherConditionalStatements", + Value.InOtherConditionalStatements); + IO.mapOptional("Other", Value.Other); + } +}; + template <> struct ScalarEnumerationTraits< FormatStyle::BraceWrappingAfterControlStatementStyle> { @@ -944,6 +954,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); + IO.mapOptional("AlignAfterOpenBracketBreak", + Style.AlignAfterOpenBracketBreak); IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures); IO.mapOptional("AlignConsecutiveAssignments", Style.AlignConsecutiveAssignments); @@ -1189,6 +1201,18 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("WrapNamespaceBodyWithEmptyLines", Style.WrapNamespaceBodyWithEmptyLines); + // If AlignAfterOpenBracket was specified but AlignAfterOpenBracketBreak + // was not, initialize the latter for backwards compatibility. + if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak || + Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && + Style.AlignAfterOpenBracketBreak == + FormatStyle::AlignAfterOpenBracketCustom()) { + if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak) + Style.AlignAfterOpenBracketBreak.InIfConditionalStatements = true; + Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements = false; + Style.AlignAfterOpenBracketBreak.Other = true; + } + // If AlwaysBreakAfterDefinitionReturnType was specified but // BreakAfterReturnType was not, initialize the latter from the former for // backwards compatibility. @@ -1472,6 +1496,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { FormatStyle LLVMStyle; LLVMStyle.AccessModifierOffset = -2; LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; + LLVMStyle.AlignAfterOpenBracketBreak = {}; LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; LLVMStyle.AlignConsecutiveAssignments = {}; LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; @@ -1786,6 +1811,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.SpacesBeforeTrailingComments = 1; } else if (Language == FormatStyle::LK_JavaScript) { GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + GoogleStyle.AlignAfterOpenBracketBreak = {true, false, true}; GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; // TODO: still under discussion whether to switch to SLS_All. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a172df5291ae62..6d6a96722a8bd1 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -6165,7 +6165,13 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Next && Next->is(tok::l_paren)) return false; const FormatToken *Previous = Right.MatchingParen->Previous; - return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf())); + if (!Previous) + return true; + if (Previous->isOneOf(tok::kw_for, tok::kw_while, tok::kw_switch)) + return Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements; + if (Previous->isIf()) + return Style.AlignAfterOpenBracketBreak.InIfConditionalStatements; + return Style.AlignAfterOpenBracketBreak.Other; } if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) && diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 10788449a1a1d3..a94594529f8cdc 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -209,6 +209,11 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets); CHECK_PARSE_BOOL(VerilogBreakBetweenInstancePorts); + CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak, + InIfConditionalStatements); + CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak, + InOtherConditionalStatements); + CHECK_PARSE_NESTED_BOOL(AlignAfterOpenBracketBreak, Other); CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, Enabled); CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, AcrossEmptyLines); @@ -523,6 +528,13 @@ TEST(ConfigParseTest, ParsesConfiguration) { FormatStyle::BAS_DontAlign); CHECK_PARSE("AlignAfterOpenBracket: true", AlignAfterOpenBracket, FormatStyle::BAS_Align); + Style.AlignAfterOpenBracket = FormatStyle::BAS_Align; + Style.AlignAfterOpenBracketBreak = {}; + CHECK_PARSE("AlignAfterOpenBracket: AlwaysBreak", AlignAfterOpenBracketBreak, + FormatStyle::AlignAfterOpenBracketCustom(true, false, true)); + Style.AlignAfterOpenBracketBreak = {}; + CHECK_PARSE("AlignAfterOpenBracket: BlockIndent", AlignAfterOpenBracketBreak, + FormatStyle::AlignAfterOpenBracketCustom(false, false, true)); Style.AlignEscapedNewlines = FormatStyle::ENAS_Left; CHECK_PARSE("AlignEscapedNewlines: DontAlign", AlignEscapedNewlines, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 57f12221cdc7e6..9a95a80128ab2d 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5079,6 +5079,7 @@ TEST_F(FormatTest, BracedInitializerIndentWidth) { auto Style = getLLVMStyleWithColumns(60); Style.BinPackArguments = true; Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; Style.BracedInitializerIndentWidth = 6; // Non-initializing braces are unaffected by BracedInitializerIndentWidth. @@ -7339,6 +7340,7 @@ TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) { Style = getLLVMStyleWithColumns(20); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; Style.BinPackParameters = FormatStyle::BPPS_OnePerLine; + Style.AlignAfterOpenBracketBreak = {true, false, true}; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; Style.ContinuationIndentWidth = 2; verifyFormat("struct Foo {\n" @@ -8008,12 +8010,14 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) { // However, BAS_AlwaysBreak and BAS_BlockIndent should take precedence over // AllowAllArgumentsOnNextLine. Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat(StringRef("functionCall(\n" " paramA, paramB, paramC);\n" "void functionDecl(\n" " int A, int B, int C);"), Input, Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat("functionCall(\n" " paramA, paramB, paramC\n" ");\n" @@ -8026,6 +8030,7 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) { // first argument. Style.AllowAllArgumentsOnNextLine = true; Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat(StringRef("functionCall(\n" " paramA, paramB, paramC);\n" "void functionDecl(\n" @@ -8947,6 +8952,7 @@ TEST_F(FormatTest, FormatsOneParameterPerLineIfNecessary) { TEST_F(FormatTest, FormatsDeclarationBreakAlways) { FormatStyle BreakAlways = getGoogleStyle(); BreakAlways.BinPackParameters = FormatStyle::BPPS_AlwaysOnePerLine; + BreakAlways.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat("void f(int a,\n" " int b);", BreakAlways); @@ -8975,6 +8981,7 @@ TEST_F(FormatTest, FormatsDeclarationBreakAlways) { TEST_F(FormatTest, FormatsDefinitionBreakAlways) { FormatStyle BreakAlways = getGoogleStyle(); BreakAlways.BinPackParameters = FormatStyle::BPPS_AlwaysOnePerLine; + BreakAlways.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat("void f(int a,\n" " int b) {\n" " f(a, b);\n" @@ -9480,6 +9487,7 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { Style.ColumnLimit = 80; Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; Style.BinPackArguments = false; Style.BinPackParameters = FormatStyle::BPPS_OnePerLine; verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" @@ -9531,6 +9539,7 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; Style.BinPackArguments = false; Style.BinPackParameters = FormatStyle::BPPS_OnePerLine; verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" @@ -9638,6 +9647,127 @@ TEST_F(FormatTest, ParenthesesAndOperandAlignment) { Style); } +TEST_F(FormatTest, AlignAfterOpenBracketBreakConditionalStatements) { + FormatStyle Style = getLLVMStyle(); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.BinPackArguments = false; + Style.BinPackParameters = FormatStyle::BPPS_OnePerLine; + Style.AlignAfterOpenBracketBreak = {true, true, false}; + + verifyFormat( + "aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) &&\n" + " aaaaaaaaaaaaaaaa);", + Style); + + verifyFormat("void foo() {\n" + " if constexpr (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ") == 0) {\n" + " return;\n" + " } else if (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ") == 0) {\n" + " return;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " switch (\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n" + " default:\n" + " break;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " for (\n" + " aaaaaaaaaaaaaaaaaaaaaa = 0;\n" + " (aaaaaaaaaaaaaaaaaaaaaa->bbbbbbbbbbbbbb |\n" + " aaaaaaaaaaaaaaaaaaaaaa->ccccccccccccccccccccccc) == 0;\n" + " aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaa->next) {\n" + " ;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " while (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) == 0) " + "{\n" + " continue;\n" + " }\n" + "}", + Style); + + Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.BinPackArguments = false; + Style.BinPackParameters = FormatStyle::BPPS_OnePerLine; + Style.AlignAfterOpenBracketBreak = {true, true, false}; + + verifyFormat( + "aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) &&\n" + " aaaaaaaaaaaaaaaa);", + Style); + + verifyFormat("void foo() {\n" + " if constexpr (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ") == 0\n" + " ) {\n" + " return;\n" + " } else if (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ") == 0\n" + " ) {\n" + " return;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " switch (\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | " + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " ) {\n" + " default:\n" + " break;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " for (\n" + " aaaaaaaaaaaaaaaaaaaaaa = 0;\n" + " (aaaaaaaaaaaaaaaaaaaaaa->bbbbbbbbbbbbbb |\n" + " aaaaaaaaaaaaaaaaaaaaaa->ccccccccccccccccccccccc) == 0;\n" + " aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaa->next\n" + " ) {\n" + " ;\n" + " }\n" + "}", + Style); + + verifyFormat("void foo() {\n" + " while (\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |\n" + " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) == 0\n" + " ) {\n" + " continue;\n" + " }\n" + "}", + Style); +} + TEST_F(FormatTest, BreaksConditionalExpressions) { verifyFormat( "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa\n" @@ -11239,6 +11369,7 @@ TEST_F(FormatTest, WrapsTemplateParameters) { " y;", Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_None; verifyFormat("template <typename... a> struct s {};\n" "extern s<\n" @@ -11249,6 +11380,7 @@ TEST_F(FormatTest, WrapsTemplateParameters) { " y;", Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; verifyFormat("template <typename... a> struct t {};\n" "extern t<\n" @@ -14187,6 +14319,7 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { NoBinPacking); NoBinPacking.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + NoBinPacking.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat("static uint8 CddDp83848Reg[] = {\n" " CDDDP83848_BMCR_REGISTER,\n" " CDDDP83848_BMSR_REGISTER,\n" @@ -15831,12 +15964,14 @@ TEST_F(FormatTest, BreaksStringLiteralOperands) { // the first must be broken with a line break before it. FormatStyle Style = getLLVMStyleWithColumns(25); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat("someFunction(\n" " \"long long long \"\n" " \"long\",\n" " a);", "someFunction(\"long long long long\", a);", Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat("someFunction(\n" " \"long long long \"\n" " \"long\",\n" @@ -17620,6 +17755,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { Spaces.ColumnLimit = 80; Spaces.IndentWidth = 4; Spaces.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Spaces.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat("void foo( ) {\n" " size_t foo = (*(function))(\n" " Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, " @@ -17645,6 +17781,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { Spaces); Spaces.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Spaces.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat("void foo( ) {\n" " size_t foo = (*(function))(\n" " Foooo, Barrrrr, Foooo, Barrrr, FoooooooooLooooong, " @@ -22554,6 +22691,7 @@ TEST_F(FormatTest, ConstructorInitializerIndentWidth) { " aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}", Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; verifyFormat( "SomeLongTemplateVariableName<\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>", @@ -23808,6 +23946,7 @@ TEST_F(FormatTest, FormatsLambdas) { " }} {}", Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + Style.AlignAfterOpenBracketBreak = {true, false, true}; // FIXME: The following test should pass, but fails at the time of writing. #if 0 // As long as all the non-lambda arguments fit on a single line, AlwaysBreak @@ -26998,6 +27137,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndent) { Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat(Short, Style); verifyFormat( @@ -27122,6 +27262,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentIfStatement) { Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat("if (foo()) {\n" " return;\n" @@ -27184,6 +27325,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentForStatement) { Style); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; verifyFormat("for (int i = 0; i < 5; ++i) {\n" " doSomething();\n" @@ -27201,6 +27343,7 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentForStatement) { TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentInitializers) { auto Style = getLLVMStyleWithColumns(60); Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + Style.AlignAfterOpenBracketBreak = {false, false, true}; // Aggregate initialization. verifyFormat("int LooooooooooooooooooooooooongVariable[2] = {\n" " 10000000, 20000000\n" >From 37ab535cd44420d5e3c8ea4542e56d0bcd6e2bac Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Wed, 11 Sep 2024 22:48:12 -0600 Subject: [PATCH 2/5] Update release notes --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bf4dbf9a4dd266..057704d39119b1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1295,6 +1295,8 @@ clang-format - Adds ``WrapNamespaceBodyWithEmptyLines`` option. - Adds the ``IndentExportBlock`` option. - Adds ``PenaltyBreakBeforeMemberAccess`` option. +- Adds ``AlignAfterOpenBracketBreak`` sub-options for better control of + ``AlignAfterOpenBracket`` with ``AlwaysBreak`` or ``BlockIndent`` modes. libclang -------- >From d66f767d86ef35e8dbda3801a77a03c3a1d78f4e Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Tue, 28 Jan 2025 15:26:43 -0700 Subject: [PATCH 3/5] Handle nested blocks in template strings --- clang/lib/Format/ContinuationIndenter.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 8f8a07f64dfce0..d3fee317d97d8c 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -826,16 +826,16 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && Tok.Previous->is(tok::identifier); }; - auto IsInTemplateString = [this](const FormatToken &Tok) { + auto IsInTemplateString = [this](const FormatToken &Tok, bool NestBlocks) { if (!Style.isJavaScript()) return false; for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { if (Prev->is(TT_TemplateString) && Prev->opensScope()) return true; - if (Prev->opensScope() || - (Prev->is(TT_TemplateString) && Prev->closesScope())) { - break; - } + if (Prev->opensScope() && !NestBlocks) + return false; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) + return false; } return false; }; @@ -868,7 +868,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, !IsFunctionCallParen(*Previous)) { return true; } - if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) + if (IsOpeningBracket(Tok) || IsInTemplateString(Tok, true)) return true; const auto *Next = Tok.Next; return !Next || Next->isMemberAccess() || @@ -906,7 +906,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) && - !IsInTemplateString(Current)) { + !IsInTemplateString(Current, false)) { CurrentState.Indent = State.Column + Spaces; CurrentState.IsAligned = true; } >From 2545800adbbac018189d75a1a796c10cee7385a1 Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Tue, 28 Jan 2025 15:38:53 -0700 Subject: [PATCH 4/5] Format: address review comments on initial values --- clang/lib/Format/Format.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 98842c0afeed18..622b635cf300b2 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1496,7 +1496,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { FormatStyle LLVMStyle; LLVMStyle.AccessModifierOffset = -2; LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; - LLVMStyle.AlignAfterOpenBracketBreak = {}; + LLVMStyle.AlignAfterOpenBracketBreak = {false, false, false}; LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; LLVMStyle.AlignConsecutiveAssignments = {}; LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; >From 0258c48fbf94ffa6b3969cf0b21c3e62afe694cb Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Tue, 28 Jan 2025 15:42:11 -0700 Subject: [PATCH 5/5] Format.cpp: accept suggested change --- clang/lib/Format/Format.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 622b635cf300b2..55b19ae2274930 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1207,8 +1207,8 @@ template <> struct MappingTraits<FormatStyle> { Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && Style.AlignAfterOpenBracketBreak == FormatStyle::AlignAfterOpenBracketCustom()) { - if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak) - Style.AlignAfterOpenBracketBreak.InIfConditionalStatements = true; + Style.AlignAfterOpenBracketBreak.InIfConditionalStatements = + Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak; Style.AlignAfterOpenBracketBreak.InOtherConditionalStatements = false; Style.AlignAfterOpenBracketBreak.Other = true; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits