From: Daniel Jasper Date: Tue, 27 Aug 2013 14:24:43 +0000 (+0000) Subject: clang-format: Format segments of builder-type calls one per line. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3fef0fe26da19685bdec6a1bd844505f604d593;p=clang clang-format: Format segments of builder-type calls one per line. This fixes llvm.org/PR14818. Before: return llvm::StringSwitch(name) .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR) .StartsWith(".eh_frame", ORDER_EH_FRAME) .StartsWith(".init", ORDER_INIT).StartsWith(".fini", ORDER_FINI) .StartsWith(".hash", ORDER_HASH).Default(ORDER_TEXT); After: return llvm::StringSwitch(name) .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR) .StartsWith(".eh_frame", ORDER_EH_FRAME) .StartsWith(".init", ORDER_INIT) .StartsWith(".fini", ORDER_FINI) .StartsWith(".hash", ORDER_HASH) .Default(ORDER_TEXT); git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189353 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index ed5098bf48..199fc02204 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -47,6 +47,12 @@ static bool startsBinaryExpression(const FormatToken &Tok) { return false; } +// Returns \c true if \c Tok is the "." or "->" of a call and starts the next +// segment of a builder type call. +static bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) { + return Tok.isMemberAccess() && Tok.Previous && Tok.Previous->closesScope(); +} + ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style, SourceManager &SourceMgr, const AnnotatedLine &Line, @@ -99,6 +105,8 @@ bool ContinuationIndenter::canBreak(const LineState &State) { // As they hide "DoSomething" and are generally bad for readability. if (Previous.opensScope() && State.LowestLevelOnLine < State.StartOfLineLevel) return false; + if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder) + return false; return !State.Stack.back().NoLineBreak; } @@ -178,6 +186,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { Line.MightBeFunctionDecl && State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0) return true; + if (startsSegmentOfBuilderTypeCall(Current) && + State.Stack.back().CallContinuation != 0) + return true; return false; } @@ -232,8 +243,7 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, } else if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess != 0) { State.Column = State.Stack.back().FirstLessLess; - } else if (Current.isOneOf(tok::period, tok::arrow) && - Current.Type != TT_DesignatedInitializerPeriod) { + } else if (Current.isMemberAccess()) { if (State.Stack.back().CallContinuation == 0) { State.Column = ContinuationIndent; State.Stack.back().CallContinuation = State.Column; @@ -299,8 +309,7 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, if (!Current.isTrailingComment()) State.Stack.back().LastSpace = State.Column; - if (Current.isOneOf(tok::arrow, tok::period) && - Current.Type != TT_DesignatedInitializerPeriod) + if (Current.isMemberAccess()) State.Stack.back().LastSpace += Current.CodePointCount; State.StartOfLineLevel = State.ParenLevel; State.LowestLevelOnLine = State.ParenLevel; @@ -369,6 +378,8 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, if (Previous.is(tok::comma) && !Current.isTrailingComment() && State.Stack.back().AvoidBinPacking) State.Stack.back().NoLineBreak = true; + if (startsSegmentOfBuilderTypeCall(Current)) + State.Stack.back().ContainsUnwrappedBuilder = true; State.Column += Spaces; if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for)) @@ -401,8 +412,7 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, bool HasTrailingCall = false; if (Previous.MatchingParen) { const FormatToken *Next = Previous.MatchingParen->getNextNonComment(); - if (Next && Next->isOneOf(tok::period, tok::arrow)) - HasTrailingCall = true; + HasTrailingCall = Next && Next->isMemberAccess(); } if (HasMultipleParameters || (HasTrailingCall && @@ -431,7 +441,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, if (!Current.opensScope() && !Current.closesScope()) State.LowestLevelOnLine = std::min(State.LowestLevelOnLine, State.ParenLevel); - if (Current.isOneOf(tok::period, tok::arrow)) + if (Current.isMemberAccess()) State.Stack.back().StartOfFunctionCall = Current.LastInChainOfCalls ? 0 : State.Column + Current.CodePointCount; if (Current.Type == TT_CtorInitializerColon) { diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h index e234c3e7ef..81d14ad0a2 100644 --- a/lib/Format/ContinuationIndenter.h +++ b/lib/Format/ContinuationIndenter.h @@ -108,7 +108,8 @@ struct ParenState { AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false), NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0), StartOfArraySubscripts(0), NestedNameSpecifierContinuation(0), - CallContinuation(0), VariablePos(0), ContainsLineBreak(false) {} + CallContinuation(0), VariablePos(0), ContainsLineBreak(false), + ContainsUnwrappedBuilder(0) {} /// \brief The position to which a specific parenthesis level needs to be /// indented. @@ -178,6 +179,10 @@ struct ParenState { /// parenthesis. bool ContainsLineBreak; + /// \brief \c true if this \c ParenState contains multiple segments of a + /// builder-type call on one line. + bool ContainsUnwrappedBuilder; + bool operator<(const ParenState &Other) const { if (Indent != Other.Indent) return Indent < Other.Indent; @@ -207,6 +212,8 @@ struct ParenState { return VariablePos < Other.VariablePos; if (ContainsLineBreak != Other.ContainsLineBreak) return ContainsLineBreak < Other.ContainsLineBreak; + if (ContainsUnwrappedBuilder != Other.ContainsUnwrappedBuilder) + return ContainsUnwrappedBuilder < Other.ContainsUnwrappedBuilder; return false; } }; diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index 150a9755e2..62b0ba6adf 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -257,6 +257,12 @@ struct FormatToken { Type == TT_TemplateCloser; } + /// \brief Returns \c true if this is a "." or "->" accessing a member. + bool isMemberAccess() const { + return isOneOf(tok::arrow, tok::period) && + Type != TT_DesignatedInitializerPeriod; + } + bool isUnaryOperator() const { switch (Tok.getKind()) { case tok::plus: @@ -272,10 +278,12 @@ struct FormatToken { return false; } } + bool isBinaryOperator() const { // Comma is a binary operator, but does not behave as such wrt. formatting. return getPrecedence() > prec::Comma; } + bool isTrailingComment() const { return is(tok::comment) && (!Next || Next->NewlinesBefore > 0); } diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index c8dfb13d78..7f29855507 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1100,10 +1100,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, Left.Type == TT_InheritanceColon) return 2; - if (Right.isOneOf(tok::arrow, tok::period) && - Right.Type != TT_DesignatedInitializerPeriod) { - if (Left.isOneOf(tok::r_paren, tok::r_square) && Left.MatchingParen && - Left.MatchingParen->ParameterCount > 0) + if (Right.isMemberAccess()) { + if (Left.isOneOf(tok::r_paren, tok::r_square)) return 20; // Should be smaller than breaking at a nested comma. return 150; } diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 99a703a03d..1cc4389f3a 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -2837,9 +2837,10 @@ TEST_F(FormatTest, FormatsBuilderPattern) { "return llvm::StringSwitch(name)\n" " .StartsWith(\".eh_frame_hdr\", ORDER_EH_FRAMEHDR)\n" " .StartsWith(\".eh_frame\", ORDER_EH_FRAME)\n" - " .StartsWith(\".init\", ORDER_INIT).StartsWith(\".fini\", " - "ORDER_FINI)\n" - " .StartsWith(\".hash\", ORDER_HASH).Default(ORDER_TEXT);\n"); + " .StartsWith(\".init\", ORDER_INIT)\n" + " .StartsWith(\".fini\", ORDER_FINI)\n" + " .StartsWith(\".hash\", ORDER_HASH)\n" + " .Default(ORDER_TEXT);\n"); verifyFormat("return aaaaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa() <\n" " aaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa();"); @@ -2868,6 +2869,21 @@ TEST_F(FormatTest, FormatsBuilderPattern) { " this, &HandlerHolderClass::EventHandlerCBD))\n" " ->OnEvent6(NewPermanentCallback(\n" " this, &HandlerHolderClass::EventHandlerCBE)));"); + + verifyFormat( + "aaaaaaaaaaa().aaaaaaaaaaa().aaaaaaaaaaa().aaaaaaaaaaa().aaaaaaaaaaa();"); + verifyFormat("aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa();"); + verifyFormat("aaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa();"); + verifyFormat("aaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa()\n" + " .aaaaaaaaaaaaaaa();"); } TEST_F(FormatTest, BreaksAccordingToOperatorPrecedence) {