galenelias updated this revision to Diff 528118. galenelias added a comment.
Fixup up review comments. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D151761/new/ https://reviews.llvm.org/D151761 Files: clang/docs/ClangFormatStyleOptions.rst clang/docs/ReleaseNotes.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/WhitespaceManager.cpp clang/lib/Format/WhitespaceManager.h clang/unittests/Format/ConfigParseTest.cpp clang/unittests/Format/FormatTest.cpp
Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -19192,6 +19192,147 @@ BracedAlign); } +TEST_F(FormatTest, AlignConsecutiveShortCaseStatements) { + FormatStyle Alignment = getLLVMStyle(); + Alignment.AllowShortCaseLabelsOnASingleLine = true; + Alignment.AlignConsecutiveShortCaseStatements.Enabled = true; + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "default: return \"default\";\n" + "}", + Alignment); + + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "}", + "switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning:\n" + " return \"warning\";\n" + "}", + Alignment); + + // Verify comments and empty lines break the alignment. + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "// comment\n" + "case log::critical: return \"critical\";\n" + "default: return \"default\";\n" + "\n" + "case log::severe: return \"severe\";\n" + "}", + "switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "// comment\n" + "case log::critical: return \"critical\";\n" + "default: return \"default\";\n" + "\n" + "case log::severe: return \"severe\";\n" + "}", + Alignment); + + // Verify adjacent non-short case statements don't change the alignment, and + // properly break the set of consecutive statements. + verifyFormat("switch (level) {\n" + "case log::critical:\n" + " // comment\n" + " return \"critical\";\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "default:\n" + " // comment\n" + " return \"\";\n" + "case log::error: return \"error\";\n" + "case log::severe: return \"severe\";\n" + "case log::extra_critical:\n" + " // comment\n" + " return \"extra critical\";\n" + "}", + Alignment); + + Alignment.SpaceBeforeCaseColon = true; + verifyFormat("switch (level) {\n" + "case log::info : return \"info\";\n" + "case log::warning : return \"warning\";\n" + "default : return \"default\";\n" + "}", + Alignment); + Alignment.SpaceBeforeCaseColon = false; + + // Make sure we don't incorrectly align correctly across nested switch cases. + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "case log::other:\n" + " switch (sublevel) {\n" + " case log::info: return \"info\";\n" + " case log::warning: return \"warning\";\n" + " }\n" + " break;\n" + "case log::error: return \"error\";\n" + "default: return \"default\";\n" + "}", + "switch (level) {\n" + "case log::info: return \"info\";\n" + "case log::warning: return \"warning\";\n" + "case log::other: switch (sublevel) {\n" + " case log::info: return \"info\";\n" + " case log::warning: return \"warning\";\n" + "}\n" + "break;\n" + "case log::error: return \"error\";\n" + "default: return \"default\";\n" + "}", + Alignment); + + Alignment.AlignConsecutiveShortCaseStatements.AcrossEmptyLines = true; + + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "\n" + "case log::warning: return \"warning\";\n" + "}", + "switch (level) {\n" + "case log::info: return \"info\";\n" + "\n" + "case log::warning: return \"warning\";\n" + "}", + Alignment); + + Alignment.AlignConsecutiveShortCaseStatements.AcrossComments = true; + + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "\n" + "/* block comment */\n" + "\n" + "// line comment\n" + "case log::warning: return \"warning\";\n" + "}", + "switch (level) {\n" + "case log::info: return \"info\";\n" + "\n" + "/* block comment */\n" + "\n" + "// line comment\n" + "case log::warning: return \"warning\";\n" + "}", + Alignment); + + Alignment.AlignConsecutiveShortCaseStatements.AcrossEmptyLines = false; + + verifyFormat("switch (level) {\n" + "case log::info: return \"info\";\n" + "//\n" + "case log::warning: return \"warning\";\n" + "}", + Alignment); +} + TEST_F(FormatTest, AlignWithLineBreaks) { auto Style = getLLVMStyleWithColumns(120); Index: clang/unittests/Format/ConfigParseTest.cpp =================================================================== --- clang/unittests/Format/ConfigParseTest.cpp +++ clang/unittests/Format/ConfigParseTest.cpp @@ -317,6 +317,7 @@ CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveBitFields); CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveMacros); CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveDeclarations); + CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveShortCaseStatements); #undef CHECK_ALIGN_CONSECUTIVE Index: clang/lib/Format/WhitespaceManager.h =================================================================== --- clang/lib/Format/WhitespaceManager.h +++ clang/lib/Format/WhitespaceManager.h @@ -232,6 +232,9 @@ /// Align consecutive declarations over all \c Changes. void alignChainedConditionals(); + /// Align consecutive short case statements over all \c Changes. + void alignConsecutiveShortCaseStatements(); + /// Align trailing comments over all \c Changes. void alignTrailingComments(); Index: clang/lib/Format/WhitespaceManager.cpp =================================================================== --- clang/lib/Format/WhitespaceManager.cpp +++ clang/lib/Format/WhitespaceManager.cpp @@ -113,6 +113,7 @@ alignConsecutiveDeclarations(); alignConsecutiveBitFields(); alignConsecutiveAssignments(); + alignConsecutiveShortCaseStatements(); alignChainedConditionals(); alignTrailingComments(); alignEscapedNewlines(); @@ -281,7 +282,8 @@ template <typename F> static void AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, - unsigned Column, bool RightJustify, F &&Matches, + unsigned Column, bool RightJustify, bool IgnoreNestedScopes, + F &&Matches, SmallVector<WhitespaceManager::Change, 16> &Changes) { bool FoundMatchOnLine = false; int Shift = 0; @@ -309,7 +311,7 @@ SmallVector<unsigned, 16> ScopeStack; for (unsigned i = Start; i != End; ++i) { - if (ScopeStack.size() != 0 && + if (!IgnoreNestedScopes && ScopeStack.size() != 0 && Changes[i].indentAndNestingLevel() < Changes[ScopeStack.back()].indentAndNestingLevel()) { ScopeStack.pop_back(); @@ -322,8 +324,9 @@ Changes[PreviousNonComment].Tok->is(tok::comment)) { --PreviousNonComment; } - if (i != Start && Changes[i].indentAndNestingLevel() > - Changes[PreviousNonComment].indentAndNestingLevel()) { + if (!IgnoreNestedScopes && i != Start && + Changes[i].indentAndNestingLevel() > + Changes[PreviousNonComment].indentAndNestingLevel()) { ScopeStack.push_back(i); } @@ -498,12 +501,16 @@ // right-justified. It is used to align compound assignments like `+=` and `=`. // When RightJustify and ACS.PadOperators are true, operators in each block to // be aligned will be padded on the left to the same length before aligning. +// The special processing of nested scopes can be disabled by passing +// 'IgnoreNestedScopes', which is needed when aligning tokens which span scopes +// such as case labels. template <typename F> static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt, const FormatStyle::AlignConsecutiveStyle &ACS = {}, - bool RightJustify = false) { + bool RightJustify = false, + bool IgnoreNestedScopes = false) { // We arrange each line in 3 parts. The operator to be aligned (the anchor), // and text to its left and right. In the aligned text the width of each part // will be the maximum of that over the block that has been aligned. Maximum @@ -552,8 +559,8 @@ auto AlignCurrentSequence = [&] { if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) { AlignTokenSequence(Style, StartOfSequence, EndOfSequence, - WidthLeft + WidthAnchor, RightJustify, Matches, - Changes); + WidthLeft + WidthAnchor, RightJustify, + IgnoreNestedScopes, Matches, Changes); } WidthLeft = 0; WidthAnchor = 0; @@ -564,8 +571,10 @@ unsigned i = StartAt; for (unsigned e = Changes.size(); i != e; ++i) { - if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel) + if (!IgnoreNestedScopes && + Changes[i].indentAndNestingLevel() < IndentAndNestingLevel) { break; + } if (Changes[i].NewlinesBefore != 0) { CommasBeforeMatch = 0; @@ -597,10 +606,11 @@ if (Changes[i].Tok->is(tok::comma)) { ++CommasBeforeMatch; - } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) { + } else if (!IgnoreNestedScopes && + Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) { // Call AlignTokens recursively, skipping over this scope block. - unsigned StoppedAt = - AlignTokens(Style, Matches, Changes, i, ACS, RightJustify); + unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS, + RightJustify, IgnoreNestedScopes); i = StoppedAt - 1; continue; } @@ -859,6 +869,20 @@ Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields); } +void WhitespaceManager::alignConsecutiveShortCaseStatements() { + if (!Style.AlignConsecutiveShortCaseStatements.Enabled) + return; + + AlignTokens( + Style, + [&](Change const &C) { + return (C.Tok->SpacesRequiredBefore != 0 && C.Tok->Previous && + C.Tok->Previous->is(TT_CaseLabelColon)); + }, + Changes, /*StartAt=*/0, Style.AlignConsecutiveShortCaseStatements, + /*RightJustify=*/false, /*IgnoreNestedScopes=*/true); +} + void WhitespaceManager::alignConsecutiveDeclarations() { if (!Style.AlignConsecutiveDeclarations.Enabled) return; Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -846,6 +846,8 @@ IO.mapOptional("AlignConsecutiveDeclarations", Style.AlignConsecutiveDeclarations); IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); + IO.mapOptional("AlignConsecutiveShortCaseStatements", + Style.AlignConsecutiveShortCaseStatements); IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); IO.mapOptional("AlignOperands", Style.AlignOperands); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); @@ -1319,6 +1321,7 @@ LLVMStyle.AlignConsecutiveBitFields = {}; LLVMStyle.AlignConsecutiveDeclarations = {}; LLVMStyle.AlignConsecutiveMacros = {}; + LLVMStyle.AlignConsecutiveShortCaseStatements = {}; LLVMStyle.AlignTrailingComments = {}; LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -295,6 +295,17 @@ /// \endcode /// \version 3.8 AlignConsecutiveStyle AlignConsecutiveDeclarations; + /// Style of aligning consecutive short case labels. + /// Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``. + /// + /// ``Consecutive`` will result in formattings like: + /// \code + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// default: return ""; + /// \endcode + /// \version 17 + AlignConsecutiveStyle AlignConsecutiveShortCaseStatements; /// Different styles for aligning escaped newlines. enum EscapedNewlineAlignmentStyle : int8_t { @@ -4292,6 +4303,8 @@ AlignConsecutiveBitFields == R.AlignConsecutiveBitFields && AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations && AlignConsecutiveMacros == R.AlignConsecutiveMacros && + AlignConsecutiveShortCaseStatements == + R.AlignConsecutiveShortCaseStatements && AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && AlignTrailingComments == R.AlignTrailingComments && Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -657,6 +657,8 @@ - Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``. - Add ``BracedInitializerIndentWidth`` which can be used to configure the indentation level of the contents of braced init lists. +- Add ``AlignConsecutiveShortCaseStatements`` which can be used to align case + labels in conjunction with ``AllowShortCaseLabelsOnASingleLine``. libclang -------- Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -785,6 +785,131 @@ bbb >>= 2; +.. _AlignConsecutiveShortCaseStatements: + +**AlignConsecutiveShortCaseStatements** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 17` :ref:`¶ <AlignConsecutiveShortCaseStatements>` + Style of aligning consecutive short case labels. + Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``. + + ``Consecutive`` will result in formattings like: + + .. code-block:: c++ + + case log::info: return "info:"; + case log::warning: return "warning:"; + default: return ""; + + Nested configuration flags: + + Alignment options. + + They can also be read as a whole for compatibility. The choices are: + - None + - Consecutive + - AcrossEmptyLines + - AcrossComments + - AcrossEmptyLinesAndComments + + For example, to align across empty lines and not across comments, either + of these work. + + .. code-block:: c++ + + AlignConsecutiveMacros: AcrossEmptyLines + + AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false + + * ``bool Enabled`` Whether aligning is enabled. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + #define foo(x) (x * x) + #define bar(y, z) (y + z) + + int a = 1; + int somelongname = 2; + double c = 3; + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int aaaa = 12; + float b = 23; + std::string ccc; + + * ``bool AcrossEmptyLines`` Whether to align across empty lines. + + .. code-block:: c++ + + true: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + false: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + * ``bool AcrossComments`` Whether to align across comments. + + .. code-block:: c++ + + true: + int d = 3; + /* A comment. */ + double e = 4; + + false: + int d = 3; + /* A comment. */ + double e = 4; + + * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``. Whether compound assignments + like ``+=`` are aligned along with ``=``. + + .. code-block:: c++ + + true: + a &= 2; + bbb = 2; + + false: + a &= 2; + bbb = 2; + + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment + operators are left-padded to the same length as long ones in order to + put all assignment operators to the right of the left hand side. + + .. code-block:: c++ + + true: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + false: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + .. _AlignEscapedNewlines: **AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) :versionbadge:`clang-format 5` :ref:`¶ <AlignEscapedNewlines>`
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits