bbb >>= 2;
+.. _AlignConsecutiveShortCaseStatements:
+
+**AlignConsecutiveShortCaseStatements** (``ShortCaseStatementsAlignmentStyle``) :versionbadge:`clang-format 17` :ref:`¶ <AlignConsecutiveShortCaseStatements>`
+ Style of aligning consecutive short case labels.
+ Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``.
+
+
+ .. code-block:: yaml
+
+ # Example of usage:
+ AlignConsecutiveShortCaseStatements:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: true
+ AlignCaseColons: false
+
+ Nested configuration flags:
+
+ Alignment options.
+
+ * ``bool Enabled`` Whether aligning is enabled.
+
+ .. code-block:: c++
+
+ true:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+ default: return "";
+ }
+
+ false:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+ default: return "";
+ }
+
+ * ``bool AcrossEmptyLines`` Whether to align across empty lines.
+
+ .. code-block:: c++
+
+ true:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+
+ default: return "";
+ }
+
+ false:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+
+ default: return "";
+ }
+
+ * ``bool AcrossComments`` Whether to align across comments.
+
+ .. code-block:: c++
+
+ true:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+ /* A comment. */
+ default: return "";
+ }
+
+ false:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+ /* A comment. */
+ default: return "";
+ }
+
+ * ``bool AlignCaseColons`` Whether aligned case labels are aligned on the colon, or on the
+ , or on the tokens after the colon.
+
+ .. code-block:: c++
+
+ true:
+ switch (level) {
+ case log::info : return "info:";
+ case log::warning: return "warning:";
+ default : return "";
+ }
+
+ false:
+ switch (level) {
+ case log::info: return "info:";
+ case log::warning: return "warning:";
+ default: return "";
+ }
+
+
.. _AlignEscapedNewlines:
**AlignEscapedNewlines** (``EscapedNewlineAlignmentStyle``) :versionbadge:`clang-format 5` :ref:`¶ <AlignEscapedNewlines>`
- Add ``KeepEmptyLinesAtEOF`` to keep empty lines at end of file.
- Add ``RemoveParentheses`` to remove redundant parentheses.
- Add ``TypeNames`` to treat listed non-keyword identifiers as type names.
+- Add ``AlignConsecutiveShortCaseStatements`` which can be used to align case
+ labels in conjunction with ``AllowShortCaseLabelsOnASingleLine``.
libclang
--------
/// \version 3.8
AlignConsecutiveStyle AlignConsecutiveDeclarations;
+ /// Alignment options.
+ ///
+ struct ShortCaseStatementsAlignmentStyle {
+ /// Whether aligning is enabled.
+ /// \code
+ /// true:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ /// default: return "";
+ /// }
+ ///
+ /// false:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ /// default: return "";
+ /// }
+ /// \endcode
+ bool Enabled;
+ /// Whether to align across empty lines.
+ /// \code
+ /// true:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ ///
+ /// default: return "";
+ /// }
+ ///
+ /// false:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ ///
+ /// default: return "";
+ /// }
+ /// \endcode
+ bool AcrossEmptyLines;
+ /// Whether to align across comments.
+ /// \code
+ /// true:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ /// /* A comment. */
+ /// default: return "";
+ /// }
+ ///
+ /// false:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ /// /* A comment. */
+ /// default: return "";
+ /// }
+ /// \endcode
+ bool AcrossComments;
+ /// Whether aligned case labels are aligned on the colon, or on the
+ /// , or on the tokens after the colon.
+ /// \code
+ /// true:
+ /// switch (level) {
+ /// case log::info : return "info:";
+ /// case log::warning: return "warning:";
+ /// default : return "";
+ /// }
+ ///
+ /// false:
+ /// switch (level) {
+ /// case log::info: return "info:";
+ /// case log::warning: return "warning:";
+ /// default: return "";
+ /// }
+ /// \endcode
+ bool AlignCaseColons;
+ bool operator==(const ShortCaseStatementsAlignmentStyle &R) const {
+ return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
+ AcrossComments == R.AcrossComments &&
+ AlignCaseColons == R.AlignCaseColons;
+ }
+ };
+
+ /// Style of aligning consecutive short case labels.
+ /// Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``.
+ ///
+ /// \code{.yaml}
+ /// # Example of usage:
+ /// AlignConsecutiveShortCaseStatements:
+ /// Enabled: true
+ /// AcrossEmptyLines: true
+ /// AcrossComments: true
+ /// AlignCaseColons: false
+ /// \endcode
+ /// \version 17
+ ShortCaseStatementsAlignmentStyle AlignConsecutiveShortCaseStatements;
+
/// Different styles for aligning escaped newlines.
enum EscapedNewlineAlignmentStyle : int8_t {
/// Don't align escaped newlines.
AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
AlignConsecutiveMacros == R.AlignConsecutiveMacros &&
+ AlignConsecutiveShortCaseStatements ==
+ R.AlignConsecutiveShortCaseStatements &&
AlignEscapedNewlines == R.AlignEscapedNewlines &&
AlignOperands == R.AlignOperands &&
AlignTrailingComments == R.AlignTrailingComments &&
};
template <>
+struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
+ static void mapping(IO &IO,
+ FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
+ IO.mapOptional("Enabled", Value.Enabled);
+ IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
+ IO.mapOptional("AcrossComments", Value.AcrossComments);
+ IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
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);
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
LLVMStyle.AlignConsecutiveMacros = {};
+ LLVMStyle.AlignConsecutiveShortCaseStatements = {};
LLVMStyle.AlignTrailingComments = {};
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveMacros();
+ alignConsecutiveShortCaseStatements();
alignConsecutiveDeclarations();
alignConsecutiveBitFields();
alignConsecutiveAssignments();
//
// We need to adjust the StartOfTokenColumn of each Change that is on a line
// containing any matching token to be aligned and located after such token.
-static void AlignMacroSequence(
+static void AlignMatchingTokenSequence(
unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,
- unsigned &MaxColumn, bool &FoundMatchOnLine,
- std::function<bool(const WhitespaceManager::Change &C)> AlignMacrosMatches,
+ std::function<bool(const WhitespaceManager::Change &C)> Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
-
- FoundMatchOnLine = false;
+ bool FoundMatchOnLine = false;
int Shift = 0;
for (unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
// If this is the first matching token to be aligned, remember by how many
// spaces it has to be shifted, so the rest of the changes on the line are
- // shifted by the same amount
- if (!FoundMatchOnLine && AlignMacrosMatches(Changes[I])) {
+ // shifted by the same amount.
+ if (!FoundMatchOnLine && Matches(Changes[I])) {
FoundMatchOnLine = true;
Shift = MinColumn - Changes[I].StartOfTokenColumn;
Changes[I].Spaces += Shift;
}
MinColumn = 0;
- MaxColumn = UINT_MAX;
StartOfSequence = 0;
EndOfSequence = 0;
}
};
unsigned MinColumn = 0;
- unsigned MaxColumn = UINT_MAX;
// Start and end of the token sequence we're processing.
unsigned StartOfSequence = 0;
!(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
if (EmptyLineBreak || NoMatchBreak) {
- AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
- FoundMatchOnLine, AlignMacrosMatches, Changes);
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ AlignMacrosMatches, Changes);
}
// A new line starts, re-initialize line status tracking bools.
StartOfSequence = I;
unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
- int LineLengthAfter = -Changes[I].Spaces;
- for (unsigned j = I; j != E && Changes[j].NewlinesBefore == 0; ++j)
- LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
- unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
-
MinColumn = std::max(MinColumn, ChangeMinColumn);
- MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
EndOfSequence = I;
- AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
- FoundMatchOnLine, AlignMacrosMatches, Changes);
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ AlignMacrosMatches, Changes);
}
void WhitespaceManager::alignConsecutiveAssignments() {
Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
}
+void WhitespaceManager::alignConsecutiveShortCaseStatements() {
+ if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
+ !Style.AllowShortCaseLabelsOnASingleLine) {
+ return;
+ }
+
+ auto Matches = [&](const Change &C) {
+ if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons)
+ return C.Tok->is(TT_CaseLabelColon);
+
+ // Ignore 'IsInsideToken' to allow matching trailing comments which
+ // need to be reflowed as that causes the token to appear in two
+ // different changes, which will cause incorrect alignment as we'll
+ // reflow early due to detecting multiple aligning tokens per line.
+ return !C.IsInsideToken && C.Tok->Previous &&
+ C.Tok->Previous->is(TT_CaseLabelColon);
+ };
+
+ unsigned MinColumn = 0;
+
+ // Empty case statements don't break the alignment, but don't necessarily
+ // match our predicate, so we need to track their column so they can push out
+ // our alignment.
+ unsigned MinEmptyCaseColumn = 0;
+
+ // Start and end of the token sequence we're processing.
+ unsigned StartOfSequence = 0;
+ unsigned EndOfSequence = 0;
+
+ // Whether a matching token has been found on the current line.
+ bool FoundMatchOnLine = false;
+
+ bool LineIsComment = true;
+ bool LineIsEmptyCase = false;
+
+ unsigned I = 0;
+ for (unsigned E = Changes.size(); I != E; ++I) {
+ if (Changes[I].NewlinesBefore != 0) {
+ // Whether to break the alignment sequence because of an empty line.
+ bool EmptyLineBreak =
+ (Changes[I].NewlinesBefore > 1) &&
+ !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
+
+ // Whether to break the alignment sequence because of a line without a
+ // match.
+ bool NoMatchBreak =
+ !FoundMatchOnLine &&
+ !(LineIsComment &&
+ Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
+ !LineIsEmptyCase;
+
+ if (EmptyLineBreak || NoMatchBreak) {
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ Matches, Changes);
+ MinEmptyCaseColumn = 0;
+ }
+
+ // A new line starts, re-initialize line status tracking bools.
+ FoundMatchOnLine = false;
+ LineIsComment = true;
+ LineIsEmptyCase = false;
+ }
+
+ if (Changes[I].Tok->isNot(tok::comment))
+ LineIsComment = false;
+
+ if (Changes[I].Tok->is(TT_CaseLabelColon)) {
+ LineIsEmptyCase =
+ !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
+
+ if (LineIsEmptyCase) {
+ if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
+ MinEmptyCaseColumn =
+ std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
+ } else {
+ MinEmptyCaseColumn =
+ std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
+ }
+ }
+ }
+
+ if (!Matches(Changes[I]))
+ continue;
+
+ if (LineIsEmptyCase)
+ continue;
+
+ FoundMatchOnLine = true;
+
+ if (StartOfSequence == 0)
+ StartOfSequence = I;
+
+ EndOfSequence = I + 1;
+
+ MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
+
+ // Allow empty case statements to push out our alignment.
+ MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
+ }
+
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches,
+ Changes);
+}
+
void WhitespaceManager::alignConsecutiveDeclarations() {
if (!Style.AlignConsecutiveDeclarations.Enabled)
return;
/// 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();
CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);
CHECK_PARSE_BOOL(VerilogBreakBetweenInstancePorts);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, Enabled);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements,
+ AcrossEmptyLines);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, AcrossComments);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveShortCaseStatements, AlignCaseColons);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum);
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);
+
+ // Empty case statements push out the alignment, but non-short case labels
+ // don't.
+ verifyFormat("switch (level) {\n"
+ "case log::info: return \"info\";\n"
+ "case log::critical:\n"
+ "case log::warning:\n"
+ "case log::severe: return \"severe\";\n"
+ "case log::extra_severe:\n"
+ " // comment\n"
+ " return \"extra_severe\";\n"
+ "}",
+ Alignment);
+
+ // Verify comments and empty lines break the alignment.
+ verifyNoChange("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);
+
+ // Empty case statements don't break the alignment, and potentially push it
+ // out.
+ verifyFormat("switch (level) {\n"
+ "case log::info: return \"info\";\n"
+ "case log::warning:\n"
+ "case log::critical:\n"
+ "default: return \"default\";\n"
+ "}",
+ Alignment);
+
+ // Implicit fallthrough cases can be aligned with either a comment or
+ // [[fallthrough]]
+ verifyFormat("switch (level) {\n"
+ "case log::info: return \"info\";\n"
+ "case log::warning: // fallthrough\n"
+ "case log::error: return \"error\";\n"
+ "case log::critical: /*fallthrough*/\n"
+ "case log::severe: return \"severe\";\n"
+ "case log::diag: [[fallthrough]];\n"
+ "default: return \"default\";\n"
+ "}",
+ Alignment);
+
+ // Verify trailing comment that needs a reflow also gets aligned properly.
+ verifyFormat("switch (level) {\n"
+ "case log::info: return \"info\";\n"
+ "case log::warning: // fallthrough\n"
+ "case log::error: return \"error\";\n"
+ "}",
+ "switch (level) {\n"
+ "case log::info: return \"info\";\n"
+ "case log::warning: //fallthrough\n"
+ "case log::error: return \"error\";\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;
+
+ verifyNoChange("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);
+
+ Alignment.AlignConsecutiveShortCaseStatements.AlignCaseColons = true;
+
+ verifyFormat("switch (level) {\n"
+ "case log::info : return \"info\";\n"
+ "case log::warning: return \"warning\";\n"
+ "default : return \"default\";\n"
+ "}",
+ Alignment);
+
+ // With AlignCaseColons, empty case statements don't break alignment of
+ // consecutive case statements (and are aligned).
+ verifyFormat("switch (level) {\n"
+ "case log::info : return \"info\";\n"
+ "case log::warning :\n"
+ "case log::critical:\n"
+ "default : return \"default\";\n"
+ "}",
+ Alignment);
+
+ // Final non-short case labels shouldn't have their colon aligned
+ verifyFormat("switch (level) {\n"
+ "case log::info : return \"info\";\n"
+ "case log::warning :\n"
+ "case log::critical:\n"
+ "case log::severe : return \"severe\";\n"
+ "default:\n"
+ " // comment\n"
+ " return \"default\";\n"
+ "}",
+ Alignment);
+
+ // Verify adjacent non-short case statements break the set of consecutive
+ // alignments and aren't aligned with adjacent non-short case statements if
+ // AlignCaseColons is set.
+ 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"
+ "case log::error :\n"
+ "default : return \"default\";\n"
+ "}",
+ Alignment);
+}
+
TEST_F(FormatTest, AlignWithLineBreaks) {
auto Style = getLLVMStyleWithColumns(120);