sstwcw updated this revision to Diff 408295.
sstwcw edited the summary of this revision.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D119599/new/
https://reviews.llvm.org/D119599
Files:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/WhitespaceManager.cpp
clang/unittests/Format/FormatTest.cpp
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -16392,6 +16392,157 @@
Alignment));
}
+TEST_F(FormatTest, AlignCompoundAssignments) {
+ FormatStyle Alignment = getLLVMStyle();
+ Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+ Alignment.AlignConsecutiveAssignmentsOptions.AlignCompound = true;
+ Alignment.AlignConsecutiveAssignmentsOptions.PadOperators = false;
+ verifyFormat("aa <= 5;\n"
+ "a = 5;\n"
+ "bcd = 5;\n"
+ "ghtyf = 5;\n"
+ "dvfvdb = 5;\n"
+ "a = 5;\n"
+ "vdsvsv = 5;\n"
+ "sfdbddfbdfbb = 5;\n"
+ "dvsdsv = 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ verifyFormat("aa <= 5;\n"
+ "a &= 5;\n"
+ "bcd *= 5;\n"
+ "ghtyf += 5;\n"
+ "dvfvdb -= 5;\n"
+ "a /= 5;\n"
+ "vdsvsv %= 5;\n"
+ "sfdbddfbdfbb ^= 5;\n"
+ "dvsdsv |= 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ verifyFormat("a &= 5;\n"
+ "bcd *= 5;\n"
+ "ghtyf >>= 5;\n"
+ "dvfvdb -= 5;\n"
+ "a /= 5;\n"
+ "aa <= 5;\n"
+ "vdsvsv %= 5;\n"
+ "sfdbddfbdfbb ^= 5;\n"
+ "dvsdsv <<= 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ Alignment.AlignConsecutiveAssignmentsOptions.PadOperators = true;
+ verifyFormat("aa <= 5;\n"
+ "a = 5;\n"
+ "bcd = 5;\n"
+ "ghtyf = 5;\n"
+ "dvfvdb = 5;\n"
+ "a = 5;\n"
+ "vdsvsv = 5;\n"
+ "sfdbddfbdfbb = 5;\n"
+ "dvsdsv = 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ verifyFormat("aa <= 5;\n"
+ "a &= 5;\n"
+ "bcd *= 5;\n"
+ "ghtyf += 5;\n"
+ "dvfvdb -= 5;\n"
+ "a /= 5;\n"
+ "vdsvsv %= 5;\n"
+ "sfdbddfbdfbb ^= 5;\n"
+ "dvsdsv |= 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ verifyFormat("a &= 5;\n"
+ "bcd *= 5;\n"
+ "ghtyf >>= 5;\n"
+ "dvfvdb -= 5;\n"
+ "a /= 5;\n"
+ "aa <= 5;\n"
+ "vdsvsv %= 5;\n"
+ "sfdbddfbdfbb ^= 5;\n"
+ "dvsdsv <<= 5;\n"
+ "int dsvvdvsdvvv = 123;",
+ Alignment);
+ Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossEmptyLines;
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ Alignment.AlignConsecutiveAssignments = FormatStyle::ACS_AcrossComments;
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ Alignment.AlignConsecutiveAssignments =
+ FormatStyle::ACS_AcrossEmptyLinesAndComments;
+ EXPECT_EQ("int a += 5;\n"
+ "int one >>= 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ format("int a += 5;\n"
+ "int one >>= 1;\n"
+ "\n"
+ "int oneTwoThree = 123;\n",
+ Alignment));
+ EXPECT_EQ("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree <<= 123;\n",
+ format("int a += 5;\n"
+ "int one = 1;\n"
+ "//\n"
+ "int oneTwoThree <<= 123;\n",
+ Alignment));
+}
+
TEST_F(FormatTest, AlignConsecutiveAssignments) {
FormatStyle Alignment = getLLVMStyle();
Alignment.AlignConsecutiveMacros = FormatStyle::ACS_Consecutive;
@@ -16410,7 +16561,8 @@
verifyFormat("int a = method();\n"
"int oneTwoThree = 133;",
Alignment);
- verifyFormat("a &= 5;\n"
+ verifyFormat("aa <= 5;\n"
+ "a &= 5;\n"
"bcd *= 5;\n"
"ghtyf += 5;\n"
"dvfvdb -= 5;\n"
@@ -19297,6 +19449,8 @@
CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);
CHECK_PARSE_BOOL(UseCRLF);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveAssignmentsOptions, AlignCompound);
+ CHECK_PARSE_NESTED_BOOL(AlignConsecutiveAssignmentsOptions, PadOperators);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum);
Index: clang/lib/Format/WhitespaceManager.cpp
===================================================================
--- clang/lib/Format/WhitespaceManager.cpp
+++ clang/lib/Format/WhitespaceManager.cpp
@@ -267,10 +267,14 @@
}
// Align a single sequence of tokens, see AlignTokens below.
+// Column - The token for which Matches returns true is moved to this
+// column.
+// RightJustify - Whether it is the token's right end or left end that
+// gets moved to that column.
template <typename F>
static void
AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
- unsigned Column, F &&Matches,
+ unsigned Column, bool RightJustify, F &&Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
bool FoundMatchOnLine = false;
int Shift = 0;
@@ -329,7 +333,8 @@
// shifted by the same amount
if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
FoundMatchOnLine = true;
- Shift = Column - Changes[i].StartOfTokenColumn;
+ Shift = Column - RightJustify * Changes[i].TokenLength -
+ Changes[i].StartOfTokenColumn;
Changes[i].Spaces += Shift;
// FIXME: This is a workaround that should be removed when we fix
// http://llvm.org/PR53699. An assertion later below verifies this.
@@ -456,13 +461,35 @@
// However, the special exception is that we do NOT skip function parameters
// that are split across multiple lines. See the test case in FormatTest.cpp
// that mentions "split function parameter alignment" for an example of this.
+// When the parameter RightJustify is true, the operator will be
+// right-justified. It is used to align compound assignments like `+=`
+// and `=`.
+// When RightJustify and PadAnchors are true, operators in each block to
+// be aligned will be padded on the left to the same length before
+// aligning.
template <typename F>
static unsigned AlignTokens(
const FormatStyle &Style, F &&Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt,
- const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
- unsigned MinColumn = 0;
- unsigned MaxColumn = UINT_MAX;
+ const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None,
+ bool RightJustify = false, bool PadAnchors = 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 widths of each part so far.
+ // When RightJustify is true and PadAnchors is false, the part from
+ // start of line to the right end of the anchor. Otherwise, only the
+ // part to the left of the anchor. Including the space that exists on
+ // its left from the start. Not including the padding added on the
+ // left to right-justify the anchor.
+ unsigned WidthLeft = 0;
+ // The operator to be aligned when RightJustify is true and PadAnchors
+ // is false. 0 otherwise.
+ unsigned WidthAnchor = 0;
+ // Width to the right of the anchor. Plus width of the anchor when
+ // RightJustify is false.
+ unsigned WidthRight = 0;
// Line number of the start and the end of the current token sequence.
unsigned StartOfSequence = 0;
@@ -495,10 +522,12 @@
// containing any matching token to be aligned and located after such token.
auto AlignCurrentSequence = [&] {
if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
- AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
- Matches, Changes);
- MinColumn = 0;
- MaxColumn = UINT_MAX;
+ AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
+ WidthLeft + WidthAnchor, RightJustify, Matches,
+ Changes);
+ WidthLeft = 0;
+ WidthAnchor = 0;
+ WidthRight = 0;
StartOfSequence = 0;
EndOfSequence = 0;
};
@@ -563,29 +592,44 @@
if (StartOfSequence == 0)
StartOfSequence = i;
- unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
- int LineLengthAfter = Changes[i].TokenLength;
+ unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
+ unsigned ChangeWidthAnchor = 0;
+ unsigned ChangeWidthRight = 0;
+ if (RightJustify) {
+ if (PadAnchors)
+ ChangeWidthAnchor = Changes[i].TokenLength;
+ else
+ ChangeWidthLeft += Changes[i].TokenLength;
+ } else
+ ChangeWidthRight = Changes[i].TokenLength;
for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
- LineLengthAfter += Changes[j].Spaces;
+ ChangeWidthRight += Changes[j].Spaces;
// Changes are generally 1:1 with the tokens, but a change could also be
// inside of a token, in which case it's counted more than once: once for
// the whitespace surrounding the token (!IsInsideToken) and once for
// each whitespace change within it (IsInsideToken).
// Therefore, changes inside of a token should only count the space.
if (!Changes[j].IsInsideToken)
- LineLengthAfter += Changes[j].TokenLength;
+ ChangeWidthRight += Changes[j].TokenLength;
}
- unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
// If we are restricted by the maximum column width, end the sequence.
- if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
- CommasBeforeLastMatch != CommasBeforeMatch) {
+ unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
+ unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
+ unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
+ // `ColumnLimit == 0` means there is no column limit.
+ if (Style.ColumnLimit != 0 &&
+ Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
AlignCurrentSequence();
StartOfSequence = i;
+ WidthLeft = ChangeWidthLeft;
+ WidthAnchor = ChangeWidthAnchor;
+ WidthRight = ChangeWidthRight;
+ } else {
+ WidthLeft = NewLeft;
+ WidthAnchor = NewAnchor;
+ WidthRight = NewRight;
}
-
- MinColumn = std::max(MinColumn, ChangeMinColumn);
- MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
EndOfSequence = i;
@@ -760,9 +804,13 @@
if (Previous && Previous->is(tok::kw_operator))
return false;
- return C.Tok->is(tok::equal);
+ return Style.AlignConsecutiveAssignmentsOptions.AlignCompound
+ ? C.Tok->getPrecedence() == prec::Assignment
+ : C.Tok->is(tok::equal);
},
- Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments);
+ Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments,
+ /*RightJustify=*/true,
+ /*PadAnchors=*/Style.AlignConsecutiveAssignmentsOptions.PadOperators);
}
void WhitespaceManager::alignConsecutiveBitFields() {
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -152,6 +152,15 @@
}
};
+template <>
+struct MappingTraits<FormatStyle::AlignConsecutiveAssignmentsOptionsT> {
+ static void mapping(IO &IO,
+ FormatStyle::AlignConsecutiveAssignmentsOptionsT &Value) {
+ IO.mapOptional("AlignCompound", Value.AlignCompound);
+ IO.mapOptional("PadOperators", Value.PadOperators);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::ACS_None);
@@ -600,13 +609,15 @@
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
- IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
IO.mapOptional("AlignConsecutiveAssignments",
Style.AlignConsecutiveAssignments);
+ IO.mapOptional("AlignConsecutiveAssignmentsOptions",
+ Style.AlignConsecutiveAssignmentsOptions);
IO.mapOptional("AlignConsecutiveBitFields",
Style.AlignConsecutiveBitFields);
IO.mapOptional("AlignConsecutiveDeclarations",
Style.AlignConsecutiveDeclarations);
+ IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -1138,6 +1149,8 @@
LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+ LLVMStyle.AlignConsecutiveAssignmentsOptions = {/*AlignCompound=*/false,
+ /*PadOperators=*/true};
LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -148,6 +148,39 @@
ACS_AcrossEmptyLinesAndComments
};
+ ///
+ struct AlignConsecutiveAssignmentsOptionsT {
+ /// Whether compound assignments like ``+=``'s are aligned along
+ /// with ``=``'s.
+ /// \code
+ /// true:
+ /// a &= 2;
+ /// bbb = 2;
+ ///
+ /// false:
+ /// a &= 2;
+ /// bbb = 2;
+ /// \endcode
+ bool AlignCompound;
+ /// 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
+ /// true:
+ /// a >>= 2;
+ /// bbb = 2;
+ ///
+ /// false:
+ /// a >>= 2;
+ /// bbb = 2;
+ /// \endcode
+ bool PadOperators;
+ };
+ /// Options for aligning consecutive assignments. They only take effect
+ /// when ``AlignConsecutiveAssignments`` is not ``None``.
+ /// \version 15
+ AlignConsecutiveAssignmentsOptionsT AlignConsecutiveAssignmentsOptions;
+
/// Style of aligning consecutive macro definitions.
///
/// ``Consecutive`` will result in formattings like:
@@ -3920,6 +3953,10 @@
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
AlignArrayOfStructures == R.AlignArrayOfStructures &&
AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
+ AlignConsecutiveAssignmentsOptions.AlignCompound ==
+ R.AlignConsecutiveAssignmentsOptions.AlignCompound &&
+ AlignConsecutiveAssignmentsOptions.PadOperators ==
+ R.AlignConsecutiveAssignmentsOptions.PadOperators &&
AlignConsecutiveBitFields == R.AlignConsecutiveBitFields &&
AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
AlignConsecutiveMacros == R.AlignConsecutiveMacros &&
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -340,6 +340,41 @@
/* A comment. */
double e = 4;
+**AlignConsecutiveAssignmentsOptions** (``AlignConsecutiveAssignmentsOptionsT``) :versionbadge:`clang-format 15`
+ Options for aligning consecutive assignments. They only take effect
+ when ``AlignConsecutiveAssignments`` is not ``None``.
+
+ Nested configuration flags:
+
+
+ * ``bool AlignCompound`` Whether compound assignments like ``+=``'s are aligned along
+ with ``=``'s.
+
+ .. code-block:: c++
+
+ true:
+ a &= 2;
+ bbb = 2;
+
+ false:
+ a &= 2;
+ bbb = 2;
+
+ * ``bool PadOperators`` 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;
+
+ false:
+ a >>= 2;
+ bbb = 2;
+
+
**AlignConsecutiveBitFields** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 11`
Style of aligning consecutive bit field.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits