[cfe-commits] [PATCH] "<<" alignment for clang-format

Daniel Jasper djasper at google.com
Thu Dec 6 01:38:20 PST 2012


  Added a small fix for the initialization of the state with the first token.

Hi klimek,

http://llvm-reviews.chandlerc.com/D177

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D177?vs=437&id=447#toc

Files:
  lib/Format/Format.cpp
  unittests/Format/FormatTest.cpp

Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -92,16 +92,21 @@
   }
 
   void format() {
+    // Format first token and initialize indent.
     unsigned Indent = formatFirstToken();
+
+    // Initialize state dependent on indent.
     IndentState State;
-    State.Column = Indent + Line.Tokens[0].Tok.getLength();
+    State.Column = Indent;
     State.CtorInitializerOnNewLine = false;
     State.InCtorInitializer = false;
-    State.ConsumedTokens = 1;
-
-    //State.UsedIndent.push_back(Line.Level * 2);
+    State.ConsumedTokens = 0;
     State.Indent.push_back(Indent + 4);
     State.LastSpace.push_back(Indent);
+    State.LessLessPos.push_back(0);
+
+    // The first token has already been indented and thus consumed.
+    moveStateToNextToken(State);
 
     // Start iterating at 1 as we have correctly formatted of Token #0 above.
     for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
@@ -126,8 +131,19 @@
     /// indented.
     std::vector<unsigned> Indent;
 
+    /// \brief The position of the last space on each level.
+    ///
+    /// Used e.g. to break like:
+    /// functionCall(Parameter, otherCall(
+    ///                             OtherParameter));
     std::vector<unsigned> LastSpace;
 
+    /// \brief The position the first "<<" operator encountered on each level.
+    ///
+    /// Used to align "<<" operators. 0 if no such operator has been encountered
+    /// on a level.
+    std::vector<unsigned> LessLessPos;
+
     bool CtorInitializerOnNewLine;
     bool InCtorInitializer;
 
@@ -149,6 +165,12 @@
         if (Other.LastSpace[i] != LastSpace[i])
           return Other.LastSpace[i] > LastSpace[i];
       }
+      if (Other.LessLessPos.size() != LessLessPos.size())
+        return Other.LessLessPos.size() > LessLessPos.size();
+      for (int i = 0, e = LessLessPos.size(); i != e; ++i) {
+        if (Other.LessLessPos[i] != LessLessPos[i])
+          return Other.LessLessPos[i] > LessLessPos[i];
+      }
       return false;
     }
   };
@@ -171,6 +193,9 @@
       if (Current.Tok.is(tok::string_literal) &&
           Previous.Tok.is(tok::string_literal))
         State.Column = State.Column - Previous.Tok.getLength();
+      else if (Current.Tok.is(tok::lessless) &&
+               State.LessLessPos[ParenLevel] != 0)
+        State.Column = State.LessLessPos[ParenLevel];
       else if (Previous.Tok.is(tok::equal) && ParenLevel != 0)
         // Indent and extra 4 spaces after '=' as it continues an expression.
         // Don't do that on the top level, as we already indent 4 there.
@@ -181,7 +206,6 @@
       if (!DryRun)
         replaceWhitespace(Current, 1, State.Column);
 
-      State.Column += Current.Tok.getLength();
       State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
       if (Current.Tok.is(tok::colon) &&
           Annotations[Index].Type != TokenAnnotation::TT_ConditionalExpr) {
@@ -205,9 +229,9 @@
         State.InCtorInitializer = true;
       }
       // Top-level spaces are exempt as that mostly leads to better results.
+      State.Column += Spaces;
       if (Spaces > 0 && ParenLevel != 0)
-        State.LastSpace[ParenLevel] = State.Column + Spaces;
-      State.Column += Current.Tok.getLength() + Spaces;
+        State.LastSpace[ParenLevel] = State.Column;
     }
     moveStateToNextToken(State);
   }
@@ -217,21 +241,29 @@
   void moveStateToNextToken(IndentState &State) {
     unsigned Index = State.ConsumedTokens;
     const FormatToken &Current = Line.Tokens[Index];
+    unsigned ParenLevel = State.Indent.size() - 1;
+
+    State.Column += Current.Tok.getLength();
+
+    if (Current.Tok.is(tok::lessless) && State.LessLessPos[ParenLevel] == 0)
+      State.LessLessPos[ParenLevel] = State.Column - 2;
 
     // If we encounter an opening (, [ or <, we add a level to our stacks to
     // prepare for the following tokens.
     if (Current.Tok.is(tok::l_paren) || Current.Tok.is(tok::l_square) ||
         Annotations[Index].Type == TokenAnnotation::TT_TemplateOpener) {
       State.Indent.push_back(4 + State.LastSpace.back());
       State.LastSpace.push_back(State.LastSpace.back());
+      State.LessLessPos.push_back(0);
     }
 
     // If we encounter a closing ), ] or >, we can remove a level from our
     // stacks.
     if (Current.Tok.is(tok::r_paren) || Current.Tok.is(tok::r_square) ||
         Annotations[Index].Type == TokenAnnotation::TT_TemplateCloser) {
       State.Indent.pop_back();
       State.LastSpace.pop_back();
+      State.LessLessPos.pop_back();
     }
 
     ++State.ConsumedTokens;
@@ -687,6 +719,8 @@
       return false;
     if (isBinaryOperator(Left))
       return true;
+    if (Right.Tok.is(tok::lessless))
+      return true;
     return Right.Tok.is(tok::colon) || Left.Tok.is(tok::comma) ||
         Left.Tok.is(tok::semi) || Left.Tok.is(tok::equal) ||
         Left.Tok.is(tok::ampamp) || Left.Tok.is(tok::pipepipe) ||
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -386,6 +386,11 @@
   verifyFormat("int a = b * *c;");
 }
 
+TEST_F(FormatTest, LineStartsWithSpecialCharacter) {
+  verifyFormat("(a)->b();");
+  verifyFormat("--a;");
+}
+
 TEST_F(FormatTest, HandlesIncludeDirectives) {
   EXPECT_EQ("#include <string>\n", format("#include <string>\n"));
   EXPECT_EQ("#include \"a/b/string\"\n", format("#include \"a/b/string\"\n"));
@@ -434,5 +439,26 @@
 
 }
 
+TEST_F(FormatTest, AlignsPipes) {
+  verifyFormat(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+      "    << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+      "    << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
+  verifyFormat(
+      "aaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaa\n"
+      "                     << aaaaaaaaaaaaaaaaaaaa;");
+  verifyFormat(
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+      "                                 << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
+  verifyFormat(
+      "llvm::outs() << \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
+      "                \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
+      "             << \"ccccccccccccccccccccccccccccccccccccccccccccccccc\";");
+  verifyFormat(
+      "aaaaaaaa << (aaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+      "                                 << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+      "         << aaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
+}
+
 }  // end namespace tooling
 }  // end namespace clang
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D177.2.patch
Type: text/x-patch
Size: 6743 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121206/3b139798/attachment.bin>


More information about the cfe-commits mailing list