Typz updated this revision to Diff 100095.
Typz added a comment.
add new value to AlignOperands to support this mode.
fix some corner cases.
https://reviews.llvm.org/D32478
Files:
include/clang/Format/Format.h
lib/Format/ContinuationIndenter.cpp
lib/Format/ContinuationIndenter.h
lib/Format/Format.cpp
unittests/Format/FormatTest.cpp
unittests/Format/FormatTestJS.cpp
Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -102,7 +102,7 @@
verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
" aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
FormatStyle Style = getGoogleJSStyleWithColumns(80);
- Style.AlignOperands = true;
+ Style.AlignOperands = FormatStyle::OAS_Align;
verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
" aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
Style);
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -2503,6 +2503,9 @@
" > ccccc) {\n"
"}",
Style);
+ verifyFormat("return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " && bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;",
+ Style);
verifyFormat("return (a)\n"
" // comment\n"
" + b;",
@@ -2531,11 +2534,104 @@
Style.ColumnLimit = 60;
verifyFormat("zzzzzzzzzz\n"
- " = bbbbbbbbbbbbbbbbb\n"
+ " = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
" >> aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaa);",
Style);
}
+TEST_F(FormatTest, ExpressionIndentationStrictAlign) {
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
+ Style.AlignOperands = FormatStyle::OAS_StrictAlign;
+
+ verifyFormat(
+ "bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
+ " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
+ " && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " > ccccccccccccccccccccccccccccccccccccccccc;",
+ Style);
+ verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " == bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}",
+ Style);
+ verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " == bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}",
+ Style);
+ verifyFormat("if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}",
+ Style);
+ verifyFormat("if () {\n"
+ "} else if (aaaaa\n"
+ " && bbbbb // break\n"
+ " > ccccc) {\n"
+ "}",
+ Style);
+ verifyFormat("return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " && bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;",
+ Style);
+ verifyFormat("return (a)\n"
+ " // comment\n"
+ " + b;",
+ Style);
+ verifyFormat(
+ "int aaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
+ " + cc;",
+ Style);
+
+ verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " = aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
+ Style);
+
+ verifyFormat("return boost::fusion::at_c<0>(iiii).second\n"
+ " == boost::fusion::at_c<1>(iiii).second;",
+ Style);
+
+ Style.ColumnLimit = 60;
+ verifyFormat("zzzzzzzzzzzzz\n"
+ " = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
+ " >> aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaa);",
+ Style);
+
+ // Forced by comments.
+ Style.ColumnLimit = 80;
+ verifyFormat(
+ "unsigned ContentSize\n"
+ " = sizeof(int16_t) // DWARF ARange version number\n"
+ " + sizeof(int32_t) // Offset of CU in the .debug_info section\n"
+ " + sizeof(int8_t) // Pointer Size (in bytes)\n"
+ " + sizeof(int8_t); // Segment Size (in bytes)",
+ Style);
+
+ Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
+ verifyFormat(
+ "unsigned ContentSize =\n"
+ " sizeof(int16_t) // DWARF ARange version number\n"
+ " + sizeof(int32_t) // Offset of CU in the .debug_info section\n"
+ " + sizeof(int8_t) // Pointer Size (in bytes)\n"
+ " + sizeof(int8_t); // Segment Size (in bytes)",
+ Style);
+
+ Style.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
+ verifyFormat(
+ "unsigned ContentSize =\n"
+ " sizeof(int16_t) // DWARF ARange version number\n"
+ " + sizeof(int32_t) // Offset of CU in the .debug_info section\n"
+ " + sizeof(int8_t) // Pointer Size (in bytes)\n"
+ " + sizeof(int8_t); // Segment Size (in bytes)",
+ Style);
+}
+
TEST_F(FormatTest, EnforcedOperatorWraps) {
// Here we'd like to wrap after the || operators, but a comment is forcing an
// earlier wrap.
@@ -2547,7 +2643,7 @@
TEST_F(FormatTest, NoOperandAlignment) {
FormatStyle Style = getLLVMStyle();
- Style.AlignOperands = false;
+ Style.AlignOperands = FormatStyle::OAS_DontAlign;
verifyFormat("aaaaaaaaaaaaaa(aaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
@@ -3529,17 +3625,17 @@
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
- Style.AlignOperands = false;
+ Style.AlignOperands = FormatStyle::OAS_DontAlign;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
- Style.AlignOperands = true;
+ Style.AlignOperands = FormatStyle::OAS_Align;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
- Style.AlignOperands = false;
+ Style.AlignOperands = FormatStyle::OAS_DontAlign;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
@@ -8665,7 +8761,6 @@
FormatStyle Style = {};
Style.Language = FormatStyle::LK_Cpp;
CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);
- CHECK_PARSE_BOOL(AlignOperands);
CHECK_PARSE_BOOL(AlignTrailingComments);
CHECK_PARSE_BOOL(AlignConsecutiveAssignments);
CHECK_PARSE_BOOL(AlignConsecutiveDeclarations);
@@ -8787,6 +8882,16 @@
CHECK_PARSE("AlignAfterOpenBracket: true", AlignAfterOpenBracket,
FormatStyle::BAS_Align);
+ Style.AlignOperands = FormatStyle::OAS_Align;
+ CHECK_PARSE("AlignOperands: DontAlign", AlignOperands,
+ FormatStyle::OAS_DontAlign);
+ CHECK_PARSE("AlignOperands: Align", AlignOperands, FormatStyle::OAS_Align);
+ CHECK_PARSE("AlignOperands: StrictAlign", AlignOperands,
+ FormatStyle::OAS_StrictAlign);
+ // For backward compatibility:
+ CHECK_PARSE("AlignOperands: false", AlignOperands, FormatStyle::OAS_DontAlign);
+ CHECK_PARSE("AlignOperands: true", AlignOperands, FormatStyle::OAS_Align);
+
Style.UseTab = FormatStyle::UT_ForIndentation;
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);
CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation);
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -171,6 +171,18 @@
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
+ IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
+ IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
+ IO.enumCase(Value, "StrictAlign", FormatStyle::OAS_StrictAlign);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "true", FormatStyle::OAS_Align);
+ IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
@@ -500,7 +512,7 @@
LLVMStyle.AccessModifierOffset = -2;
LLVMStyle.AlignEscapedNewlinesLeft = false;
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
- LLVMStyle.AlignOperands = true;
+ LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = false;
LLVMStyle.AlignConsecutiveDeclarations = false;
@@ -609,7 +621,7 @@
if (Language == FormatStyle::LK_Java) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
- GoogleStyle.AlignOperands = false;
+ GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
GoogleStyle.AlignTrailingComments = false;
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
@@ -620,7 +632,7 @@
GoogleStyle.SpacesBeforeTrailingComments = 1;
} else if (Language == FormatStyle::LK_JavaScript) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
- GoogleStyle.AlignOperands = false;
+ GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.BreakBeforeTernaryOperators = false;
@@ -696,7 +708,7 @@
FormatStyle Style = getLLVMStyle();
Style.AccessModifierOffset = -4;
Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
- Style.AlignOperands = false;
+ Style.AlignOperands = FormatStyle::OAS_DontAlign;
Style.AlignTrailingComments = false;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Index: lib/Format/ContinuationIndenter.h
===================================================================
--- lib/Format/ContinuationIndenter.h
+++ lib/Format/ContinuationIndenter.h
@@ -154,7 +154,8 @@
NoLineBreakInOperand(false), LastOperatorWrapped(true),
ContainsLineBreak(false), ContainsUnwrappedBuilder(false),
AlignColons(true), ObjCSelectorNameFound(false),
- HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
+ HasMultipleNestedBlocks(false), NestedBlockInlined(false),
+ UnindentOperator(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@@ -264,6 +265,10 @@
// "function" in JavaScript) is not wrapped to a new line.
bool NestedBlockInlined : 1;
+ /// \brief Indicates the indent should be reduced by the length of the
+ /// operator.
+ bool UnindentOperator : 1;
+
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
return Indent < Other.Indent;
@@ -301,6 +306,8 @@
return ContainsUnwrappedBuilder;
if (NestedBlockInlined != Other.NestedBlockInlined)
return NestedBlockInlined;
+ if (UnindentOperator != Other.UnindentOperator)
+ return UnindentOperator;
return false;
}
};
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -437,7 +437,9 @@
// does not help.
bool HasTwoOperands =
P->OperatorIndex == 0 && !P->NextOperator && !P->is(TT_ConditionalExpr);
- if ((!BreakBeforeOperator && !(HasTwoOperands && Style.AlignOperands)) ||
+ if ((!BreakBeforeOperator && !(HasTwoOperands &&
+ Style.AlignOperands !=
+ FormatStyle::OAS_DontAlign)) ||
(!State.Stack.back().LastOperatorWrapped && BreakBeforeOperator))
State.Stack.back().NoLineBreakInOperand = true;
}
@@ -752,6 +754,9 @@
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment))
return ContinuationIndent;
+ if (Current.isBinaryOperator() && State.Stack.back().UnindentOperator)
+ return State.Stack.back().Indent - Current.Tok.getLength()
+ - Current.SpacesRequiredBefore;
if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment &&
PreviousNonComment->isNot(tok::r_brace))
// Ensure that we fall back to the continuation indent width instead of
@@ -907,30 +912,41 @@
(Previous && (Previous->opensScope() ||
Previous->isOneOf(tok::semi, tok::kw_return) ||
(Previous->getPrecedence() == prec::Assignment &&
- Style.AlignOperands) ||
+ Style.AlignOperands != FormatStyle::OAS_DontAlign) ||
Previous->is(TT_ObjCMethodExpr)));
for (SmallVectorImpl<prec::Level>::const_reverse_iterator
I = Current.FakeLParens.rbegin(),
E = Current.FakeLParens.rend();
I != E; ++I) {
ParenState NewParenState = State.Stack.back();
NewParenState.ContainsLineBreak = false;
NewParenState.LastOperatorWrapped = true;
+ NewParenState.UnindentOperator = false;
NewParenState.NoLineBreak =
NewParenState.NoLineBreak || State.Stack.back().NoLineBreakInOperand;
// Indent from 'LastSpace' unless these are fake parentheses encapsulating
// a builder type call after 'return' or, if the alignment after opening
// brackets is disabled.
if (!Current.isTrailingComment() &&
- (Style.AlignOperands || *I < prec::Assignment) &&
+ (Style.AlignOperands != FormatStyle::OAS_DontAlign ||
+ *I < prec::Assignment) &&
(!Previous || Previous->isNot(tok::kw_return) ||
(Style.Language != FormatStyle::LK_Java && *I > 0)) &&
(Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign ||
- *I != prec::Comma || Current.NestingLevel == 0))
+ *I != prec::Comma || Current.NestingLevel == 0)) {
NewParenState.Indent =
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
+ }
+
+ // If BreakBeforeBinaryOperators is set, un-indent a bit to account for
+ // the operator and keep the operands aligned
+ if (Style.AlignOperands == FormatStyle::OAS_StrictAlign &&
+ Previous &&
+ (Previous->getPrecedence() == prec::Assignment ||
+ Previous->is(tok::kw_return)))
+ NewParenState.UnindentOperator = true;
// Do not indent relative to the fake parentheses inserted for "." or "->".
// This is a special case to make the following to statements consistent:
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -115,16 +115,44 @@
/// \endcode
bool AlignEscapedNewlinesLeft;
+ enum OperandAlignmentStyle {
+ /// Do not align operands of binary and ternary expressions.
+ /// The wrapped lines are indented ``ContinuationIndentWidth`` spaces from
+ /// the start of the line.
+ OAS_DontAlign,
+
+ /// Horizontally align operands of binary and ternary expressions.
+ ///
+ /// Specifically, this aligns operands of a single expression that needs
+ /// to be split over multiple lines, e.g.:
+ /// \code
+ /// int aaa = bbbbbbbbbbbbbbb +
+ /// ccccccccccccccc;
+ /// \endcode
+ ///
+ /// When ``BreakBeforeBinaryOperators`` is set, the wrapped operator is
+ /// aligned with the operand on the first line.
+ /// \code
+ /// int aaa = bbbbbbbbbbbbbbb
+ /// + ccccccccccccccc;
+ /// \endcode
+ OAS_Align,
+
+ /// Horizontally align operands of binary and ternary expressions.
+ ///
+ /// This is similar to ``AO_Align``, except when
+ /// ``BreakBeforeBinaryOperators`` is set, the wrapped operands are
+ /// aligned with the operand on the first line.
+ /// \code
+ /// int aaa = bbbbbbbbbbbbbbb
+ /// + ccccccccccccccc;
+ /// \endcode
+ OAS_StrictAlign,
+ };
+
/// \brief If ``true``, horizontally align operands of binary and ternary
/// expressions.
- ///
- /// Specifically, this aligns operands of a single expression that needs to be
- /// split over multiple lines, e.g.:
- /// \code
- /// int aaa = bbbbbbbbbbbbbbb +
- /// ccccccccccccccc;
- /// \endcode
- bool AlignOperands;
+ OperandAlignmentStyle AlignOperands;
/// \brief If ``true``, aligns trailing comments.
/// \code
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits