From 3219e43c9467e47be9b1a9e32b3ed42a50f6b280 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Tue, 2 Dec 2014 13:24:51 +0000 Subject: [PATCH] clang-format: Add option to suppress operator alignment. With alignment: int aaaaaa = aa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccccccc; Without alignment: int aaaaaa = aa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccccccc; This fixes llvm.org/PR21666. llvm-svn: 223117 --- clang/docs/ClangFormatStyleOptions.rst | 18 ++++++++- clang/include/clang/Format/Format.h | 5 +++ clang/lib/Format/ContinuationIndenter.cpp | 12 ++++-- clang/lib/Format/Format.cpp | 4 ++ clang/unittests/Format/FormatTest.cpp | 63 ++++++++++++++++++++++++++++++- clang/unittests/Format/FormatTestJava.cpp | 2 +- 6 files changed, 96 insertions(+), 8 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index cef3f24..af9181a 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -150,10 +150,24 @@ the configuration (without a prefix: ``Auto``). **AccessModifierOffset** (``int``) The extra indent or outdent of access modifiers, e.g. ``public:``. +**AlignAfterOpenBracket** (``bool``) + If ``true``, horizontally aligns arguments after an open bracket. + + This applies to round brackets (parentheses), angle brackets and square + brackets. This will result in formattings like + \code + someLongFunction(argument1, + argument2); + \endcode + **AlignEscapedNewlinesLeft** (``bool``) If ``true``, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column. +**AlignOperands** (``bool``) + If ``true``, horizontally align operands of binary and ternary + expressions. + **AlignTrailingComments** (``bool``) If ``true``, aligns trailing comments. @@ -179,6 +193,8 @@ the configuration (without a prefix: ``Auto``). Never merge functions into a single line. * ``SFS_Inline`` (in configuration: ``Inline``) Only merge functions defined inside a class. + * ``SFS_Empty`` (in configuration: ``Empty``) + Only merge empty functions. * ``SFS_All`` (in configuration: ``All``) Merge all functions fitting on a single line. @@ -292,7 +308,7 @@ the configuration (without a prefix: ``Auto``). **DerivePointerAlignment** (``bool``) If ``true``, analyze the formatted file for the most common - alignment of & and \*. ``PointerAlignment`` is then used only as fallback. + alignment of & and *. ``PointerAlignment`` is then used only as fallback. **DisableFormat** (``bool``) Disables formatting at all. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 41e6985..60c54ab 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -240,6 +240,10 @@ struct FormatStyle { /// \endcode bool AlignAfterOpenBracket; + /// \brief If \c true, horizontally align operands of binary and ternary + /// expressions. + bool AlignOperands; + /// \brief If \c true, aligns trailing comments. bool AlignTrailingComments; @@ -407,6 +411,7 @@ struct FormatStyle { bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignAfterOpenBracket == R.AlignAfterOpenBracket && + AlignOperands == R.AlignOperands && AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft && AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 5338170..e053d4c 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -178,9 +178,6 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { // expression itself as otherwise, the line breaks seem superfluous. // We need special cases for ">>" which we have split into two ">" while // lexing in order to make template parsing easier. - // - // FIXME: We'll need something similar for styles that break before binary - // operators. bool IsComparison = (Previous.getPrecedence() == prec::Relational || Previous.getPrecedence() == prec::Equality) && Previous.Previous && @@ -193,8 +190,13 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { Previous.getPrecedence() != prec::Assignment && State.Stack.back().BreakBeforeParameter) return true; + } else { + if (Current.is(TT_BinaryOperator) && Previous.EndsBinaryExpression && + State.Stack.back().BreakBeforeParameter) + return true; } + // Same as above, but for the first "<<" operator. if (Current.is(tok::lessless) && Current.isNot(TT_OverloadedOperator) && State.Stack.back().BreakBeforeParameter && @@ -712,7 +714,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, // is special cased. bool SkipFirstExtraIndent = (Previous && (Previous->opensScope() || Previous->is(tok::kw_return) || - Previous->getPrecedence() == prec::Assignment || + (Previous->getPrecedence() == prec::Assignment && + Style.AlignOperands) || Previous->is(TT_ObjCMethodExpr))); for (SmallVectorImpl::const_reverse_iterator I = Current.FakeLParens.rbegin(), @@ -725,6 +728,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, // a builder type call after 'return' or, if the alignment after opening // brackets is disabled. if (!Current.isTrailingComment() && + (Style.AlignOperands || *I < prec::Assignment) && (!Previous || Previous->isNot(tok::kw_return) || (Style.Language != FormatStyle::LK_Java && *I > 0)) && (Style.AlignAfterOpenBracket || *I != prec::Comma || diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9fbab27..cf8e5d3 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -173,6 +173,7 @@ template <> struct MappingTraits { IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft); + IO.mapOptional("AlignOperands", Style.AlignOperands); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); @@ -327,6 +328,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.AccessModifierOffset = -2; LLVMStyle.AlignEscapedNewlinesLeft = false; LLVMStyle.AlignAfterOpenBracket = true; + LLVMStyle.AlignOperands = true; LLVMStyle.AlignTrailingComments = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; @@ -415,6 +417,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { if (Language == FormatStyle::LK_Java) { GoogleStyle.AlignAfterOpenBracket = false; + GoogleStyle.AlignOperands = false; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; GoogleStyle.ColumnLimit = 100; @@ -468,6 +471,7 @@ FormatStyle getWebKitStyle() { FormatStyle Style = getLLVMStyle(); Style.AccessModifierOffset = -4; Style.AlignAfterOpenBracket = false; + Style.AlignOperands = false; Style.AlignTrailingComments = false; Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index cdc1c9e..148c2f9 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3289,6 +3289,10 @@ TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) { " // comment\n" " + b;", Style); + verifyFormat("int aaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " + cc;", + Style); // Forced by comments. verifyFormat( @@ -3309,13 +3313,39 @@ TEST_F(FormatTest, ExpressionIndentationBreakingBeforeOperators) { Style); } +TEST_F(FormatTest, NoOperandAlignment) { + FormatStyle Style = getLLVMStyle(); + Style.AlignOperands = false; + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + verifyFormat( + "bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " == aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " > ccccccccccccccccccccccccccccccccccccccccc;", + Style); + + verifyFormat("int aaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " + cc;", + Style); + verifyFormat("int a = aa\n" + " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" + " * cccccccccccccccccccccccccccccccccccc;", + Style); +} + TEST_F(FormatTest, BreakingBeforeNonAssigmentOperators) { FormatStyle Style = getLLVMStyle(); Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; verifyFormat("int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;", Style); - + " + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;", + Style); } TEST_F(FormatTest, ConstructorInitializers) { @@ -4083,6 +4113,28 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { Style); } +TEST_F(FormatTest, ParenthesesAndOperandAlignment) { + FormatStyle Style = getLLVMStyleWithColumns(40); + verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n" + " bbbbbbbbbbbbbbbbbbbbbb);", + Style); + Style.AlignAfterOpenBracket = true; + Style.AlignOperands = false; + verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n" + " bbbbbbbbbbbbbbbbbbbbbb);", + Style); + Style.AlignAfterOpenBracket = false; + Style.AlignOperands = true; + verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n" + " bbbbbbbbbbbbbbbbbbbbbb);", + Style); + Style.AlignAfterOpenBracket = false; + Style.AlignOperands = false; + verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n" + " bbbbbbbbbbbbbbbbbbbbbb);", + Style); +} + TEST_F(FormatTest, BreaksConditionalExpressions) { verifyFormat( "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa\n" @@ -8579,7 +8631,9 @@ TEST_F(FormatTest, GetsCorrectBasedOnStyle) { TEST_F(FormatTest, ParsesConfigurationBools) { FormatStyle Style = {}; Style.Language = FormatStyle::LK_Cpp; + CHECK_PARSE_BOOL(AlignAfterOpenBracket); CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft); + CHECK_PARSE_BOOL(AlignOperands); CHECK_PARSE_BOOL(AlignTrailingComments); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine); @@ -9187,6 +9241,11 @@ TEST_F(FormatTest, FormatsWithWebKitStyle) { "double b; // align comments.", Style); + // Do not align operands. + EXPECT_EQ("ASSERT(aaaa\n" + " || bbbb);", + format("ASSERT ( aaaa\n||bbbb);", Style)); + // Accept input's line breaks. EXPECT_EQ("if (aaaaaaaaaaaaaaa\n" " || bbbbbbbbbbbbbbb) {\n" diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index 95d1961..ad80d13 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -291,7 +291,7 @@ TEST_F(FormatTestJava, Generics) { TEST_F(FormatTestJava, StringConcatenation) { verifyFormat("String someString = \"abc\"\n" - " + \"cde\";"); + " + \"cde\";"); } TEST_F(FormatTestJava, TryCatchFinally) { -- 2.7.4