"<<" alignment for clang-format.

Also, small fix for handling the first token correctly.

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169488 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 6494c3d..0809686 100644
--- a/lib/Format/Format.cpp
+++ b/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.FirstLessLess.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> FirstLessLess;
+
     bool CtorInitializerOnNewLine;
     bool InCtorInitializer;
 
@@ -149,6 +165,12 @@
         if (Other.LastSpace[i] != LastSpace[i])
           return Other.LastSpace[i] > LastSpace[i];
       }
+      if (Other.FirstLessLess.size() != FirstLessLess.size())
+        return Other.FirstLessLess.size() > FirstLessLess.size();
+      for (int i = 0, e = FirstLessLess.size(); i != e; ++i) {
+        if (Other.FirstLessLess[i] != FirstLessLess[i])
+          return Other.FirstLessLess[i] > FirstLessLess[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.FirstLessLess[ParenLevel] != 0)
+        State.Column = State.FirstLessLess[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,6 +241,12 @@
   void moveStateToNextToken(IndentState &State) {
     unsigned Index = State.ConsumedTokens;
     const FormatToken &Current = Line.Tokens[Index];
+    unsigned ParenLevel = State.Indent.size() - 1;
+
+    if (Current.Tok.is(tok::lessless) && State.FirstLessLess[ParenLevel] == 0)
+      State.FirstLessLess[ParenLevel] = State.Column;
+
+    State.Column += Current.Tok.getLength();
 
     // If we encounter an opening (, [ or <, we add a level to our stacks to
     // prepare for the following tokens.
@@ -224,6 +254,7 @@
         Annotations[Index].Type == TokenAnnotation::TT_TemplateOpener) {
       State.Indent.push_back(4 + State.LastSpace.back());
       State.LastSpace.push_back(State.LastSpace.back());
+      State.FirstLessLess.push_back(0);
     }
 
     // If we encounter a closing ), ] or >, we can remove a level from our
@@ -232,6 +263,7 @@
         Annotations[Index].Type == TokenAnnotation::TT_TemplateCloser) {
       State.Indent.pop_back();
       State.LastSpace.pop_back();
+      State.FirstLessLess.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) ||
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 05a6d33..7628b34 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/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