]> granicus.if.org Git - clang/commitdiff
clang-format: Format segments of builder-type calls one per line.
authorDaniel Jasper <djasper@google.com>
Tue, 27 Aug 2013 14:24:43 +0000 (14:24 +0000)
committerDaniel Jasper <djasper@google.com>
Tue, 27 Aug 2013 14:24:43 +0000 (14:24 +0000)
This fixes llvm.org/PR14818.

Before:
  return llvm::StringSwitch<Reference::Kind>(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<Reference::Kind>(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

lib/Format/ContinuationIndenter.cpp
lib/Format/ContinuationIndenter.h
lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTest.cpp

index ed5098bf48f353828531da6ac8222df7b8eea11e..199fc02204856075e2cccbe2eaed1b260a2c1639 100644 (file)
@@ -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) {
index e234c3e7efd0ab5ddc48452ab65f2b8ebd54056c..81d14ad0a2278fe841fdd0dd26e14b6b831a5d4a 100644 (file)
@@ -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;
   }
 };
index 150a9755e22e10acf930eb74ce49508ddfa471bb..62b0ba6adf2a967e6cf6ab8acbdccdb76d9d4209 100644 (file)
@@ -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);
   }
index c8dfb13d78a1e9f1bd6f12df90cc8cf9d1e9b59f..7f298555079a04f59b9682a3c2ba6833285472ed 100644 (file)
@@ -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;
   }
index 99a703a03df9ebac775b7419331884b28331bedc..1cc4389f3aa5e3f68e7b8c83fc7ed7bd3063fc60 100644 (file)
@@ -2837,9 +2837,10 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
       "return llvm::StringSwitch<Reference::Kind>(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) {