bmharper updated this revision to Diff 72444.
bmharper added a comment.

This revision merges NestingLevel and IndentLevel into an std::pair, as 
suggested by @djasper.
IMO this makes the code slightly harder to read, because you lose the unique 
variable names "IndentLevel" and "NestingLevel". Those are now replaced by 
.first and .second, respectively. In addition, NestingLevel is no longer equal 
to the original NestingLevel that gets passed in, because it needs to be 
tweaked slightly to better work with the recursive technique we use for 
alignment scope.
However, the approach presented here certainly does work, and it's actually not 
too much of a code change from the previous patch.


https://reviews.llvm.org/D21279

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

Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9250,12 +9250,11 @@
                "};",
                Alignment);
 
-  // FIXME: Should align all three assignments
   verifyFormat(
       "int i      = 1;\n"
       "SomeType a = SomeFunction(looooooooooooooooooooooongParameterA,\n"
       "                          loooooooooooooooooooooongParameterB);\n"
-      "int j = 2;",
+      "int j      = 2;",
       Alignment);
 
   verifyFormat("template <typename T, typename T_0 = very_long_type_name_0,\n"
@@ -9337,7 +9336,52 @@
                    "unsigned oneTwoThree = 123;\n"
                    "int oneTwo = 12;",
                    Alignment));
+  // Function prototype alignment
+  verifyFormat("int    a();\n"
+               "double b();",
+               Alignment);
+  verifyFormat("int    a(int x);\n"
+               "double b();",
+               Alignment);
+  unsigned OldColumnLimit = Alignment.ColumnLimit;
+  // We need to set ColumnLimit to zero, in order to stress nested alignments,
+  // otherwise the function parameters will be re-flowed onto a single line.
+  Alignment.ColumnLimit = 0;
+  EXPECT_EQ("int    a(int   x,\n"
+            "         float y);\n"
+            "double b(int    x,\n"
+            "         double y);",
+            format("int a(int x,\n"
+                   " float y);\n"
+                   "double b(int x,\n"
+                   " double y);",
+                   Alignment));
+  // This ensures that function parameters of function declarations are
+  // correctly indented when their owning functions are indented.
+  // The failure case here is for 'double y' to not be indented enough.
+  // This is the "split function parameter alignment" issue mentioned in
+  // WhitespaceManager.cpp
+  EXPECT_EQ("double a(int x);\n"
+            "int    b(int    x,\n"
+            "         double y);",
+            format("double a(int x);\n"
+                   "int b(int x,\n"
+                   " double y);",
+                   Alignment));
+  Alignment.ColumnLimit = OldColumnLimit;
+  // Ensure function pointers don't screw up recursive alignment
+  verifyFormat("int    a(int x, void (*fp)(int y));\n"
+               "double b();",
+               Alignment);
   Alignment.AlignConsecutiveAssignments = true;
+  // Ensure recursive alignment is broken by function braces, so that the
+  // "a = 1" does not align with subsequent assignments inside the function
+  // body.
+  verifyFormat("int func(int a = 1) {\n"
+               "  int b  = 2;\n"
+               "  int cc = 3;\n"
+               "}",
+               Alignment);
   verifyFormat("float      something = 2000;\n"
                "double     another   = 911;\n"
                "int        i = 1, j = 10;\n"
@@ -9347,6 +9391,28 @@
   verifyFormat("int      oneTwoThree = {0}; // comment\n"
                "unsigned oneTwo      = 0;   // comment",
                Alignment);
+  // Make sure that scope is correctly tracked, in the absence of braces
+  verifyFormat("for (int i = 0; i < n; i++)\n"
+               "  j = i;\n"
+               "double x = 1;\n",
+               Alignment);
+  verifyFormat("if (int i = 0)\n"
+               "  j = i;\n"
+               "double x = 1;\n",
+               Alignment);
+  // Ensure operator[] and operator() are comprehended
+  verifyFormat("struct test {\n"
+               "  long long int foo();\n"
+               "  int           operator[](int a);\n"
+               "  double        bar();\n"
+               "};\n",
+               Alignment);
+  verifyFormat("struct test {\n"
+               "  long long int foo();\n"
+               "  int           operator()(int a);\n"
+               "  double        bar();\n"
+               "};\n",
+               Alignment);
   EXPECT_EQ("void SomeFunction(int parameter = 0) {\n"
             "  int const i   = 1;\n"
             "  int *     j   = 2;\n"
@@ -9448,17 +9514,16 @@
                Alignment);
   Alignment.AlignConsecutiveAssignments = false;
 
-  // FIXME: Should align all three declarations
   verifyFormat(
       "int      i = 1;\n"
       "SomeType a = SomeFunction(looooooooooooooooooooooongParameterA,\n"
       "                          loooooooooooooooooooooongParameterB);\n"
-      "int j = 2;",
+      "int      j = 2;",
       Alignment);
 
   // Test interactions with ColumnLimit and AlignConsecutiveAssignments:
   // We expect declarations and assignments to align, as long as it doesn't
-  // exceed the column limit, starting a new alignemnt sequence whenever it
+  // exceed the column limit, starting a new alignment sequence whenever it
   // happens.
   Alignment.AlignConsecutiveAssignments = true;
   Alignment.ColumnLimit = 30;
Index: lib/Format/WhitespaceManager.h
===================================================================
--- lib/Format/WhitespaceManager.h
+++ lib/Format/WhitespaceManager.h
@@ -106,11 +106,11 @@
     /// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
     /// trailing comments and escaped newlines.
     Change(bool CreateReplacement, SourceRange OriginalWhitespaceRange,
-           unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
-           unsigned NewlinesBefore, StringRef PreviousLinePostfix,
-           StringRef CurrentLinePrefix, tok::TokenKind Kind,
-           bool ContinuesPPDirective, bool IsStartOfDeclName,
-           bool IsInsideToken);
+           unsigned IndentLevel, unsigned NestingLevel, int Spaces,
+           unsigned StartOfTokenColumn, unsigned NewlinesBefore,
+           StringRef PreviousLinePostfix, StringRef CurrentLinePrefix,
+           tok::TokenKind Kind, TokenType Type, bool ContinuesPPDirective,
+           bool IsStartOfDeclName, bool IsInsideToken);
 
     bool CreateReplacement;
     // Changes might be in the middle of a token, so we cannot just keep the
@@ -125,13 +125,19 @@
     // FIXME: Currently this is not set correctly for breaks inside comments, as
     // the \c BreakableToken is still doing its own alignment.
     tok::TokenKind Kind;
+    // Same comment applies as for Kind
+    TokenType Type;
     bool ContinuesPPDirective;
     bool IsStartOfDeclName;
 
-    // The number of nested blocks the token is in. This is used to add tabs
+    // A combination of nesting level and indent level.
+    // The nesting level of this token, i.e. the number of surrounding (),
+    // [], {} or <>. Note that the value stored here is slightly different
+    // to the NestingLevel passed in. See propagateIndentLevels() for details.
+    // The second element in the pair, the indent level, is used to add tabs
     // only for the indentation, and not for alignment, when
     // UseTab = US_ForIndentation.
-    unsigned IndentLevel;
+    std::pair<unsigned, unsigned> NestingAndIndentLevel;
 
     // The number of spaces in front of the token or broken part of the token.
     // This will be adapted when aligning tokens.
@@ -170,6 +176,10 @@
   /// \c EscapedNewlineColumn for the first tokens or token parts in a line.
   void calculateLineBreakInformation();
 
+  /// \brief Propagate IndentLevel from the first token on a line, to all of
+  /// the tokens on that line.
+  void propagateIndentLevels();
+
   /// \brief Align consecutive assignments over all \c Changes.
   void alignConsecutiveAssignments();
 
@@ -202,6 +212,10 @@
   void appendIndentText(std::string &Text, unsigned IndentLevel,
                         unsigned Spaces, unsigned WhitespaceStartColumn);
 
+  /// \brief Determine whether this token is considered as the start of a
+  /// declaration name.
+  static bool IsStartOfDeclName(const FormatToken &Tok);
+
   SmallVector<Change, 16> Changes;
   const SourceManager &SourceMgr;
   tooling::Replacements Replaces;
Index: lib/Format/WhitespaceManager.cpp
===================================================================
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -27,19 +27,21 @@
 
 WhitespaceManager::Change::Change(
     bool CreateReplacement, SourceRange OriginalWhitespaceRange,
-    unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
-    unsigned NewlinesBefore, StringRef PreviousLinePostfix,
-    StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective,
+    unsigned IndentLevel, unsigned NestingLevel, int Spaces,
+    unsigned StartOfTokenColumn, unsigned NewlinesBefore,
+    StringRef PreviousLinePostfix, StringRef CurrentLinePrefix,
+    tok::TokenKind Kind, TokenType Type, bool ContinuesPPDirective,
     bool IsStartOfDeclName, bool IsInsideToken)
     : CreateReplacement(CreateReplacement),
       OriginalWhitespaceRange(OriginalWhitespaceRange),
       StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
       PreviousLinePostfix(PreviousLinePostfix),
-      CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
+      CurrentLinePrefix(CurrentLinePrefix), Kind(Kind), Type(Type),
       ContinuesPPDirective(ContinuesPPDirective),
-      IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel),
-      Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false),
-      TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
+      IsStartOfDeclName(IsStartOfDeclName),
+      NestingAndIndentLevel(NestingLevel, IndentLevel), Spaces(Spaces),
+      IsInsideToken(IsInsideToken), IsTrailingComment(false), TokenLength(0),
+      PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
       StartOfBlockComment(nullptr), IndentationOffset(0) {}
 
 void WhitespaceManager::reset() {
@@ -56,22 +58,21 @@
   Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
   Changes.push_back(
       Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel,
-             Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(),
-             InPPDirective && !Tok.IsFirst,
-             Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
-             /*IsInsideToken=*/false));
+             Tok.NestingLevel, Spaces, StartOfTokenColumn, Newlines, "", "",
+             Tok.Tok.getKind(), Tok.Type, InPPDirective && !Tok.IsFirst,
+             IsStartOfDeclName(Tok), /*IsInsideToken=*/false));
 }
 
 void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
                                             bool InPPDirective) {
   if (Tok.Finalized)
     return;
   Changes.push_back(Change(
       /*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0,
+      Tok.NestingLevel,
       /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
-      Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
-      Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
-      /*IsInsideToken=*/false));
+      Tok.Tok.getKind(), Tok.Type, InPPDirective && !Tok.IsFirst,
+      IsStartOfDeclName(Tok), /*IsInsideToken=*/false));
 }
 
 void WhitespaceManager::replaceWhitespaceInToken(
@@ -81,20 +82,21 @@
   if (Tok.Finalized)
     return;
   SourceLocation Start = Tok.getStartOfNonWhitespace().getLocWithOffset(Offset);
-  Changes.push_back(Change(
-      true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
-      IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix,
-      CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown,
-      InPPDirective && !Tok.IsFirst,
-      Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
-      /*IsInsideToken=*/Newlines == 0));
+  Changes.push_back(
+      Change(true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
+             IndentLevel, Tok.NestingLevel, Spaces, std::max(0, Spaces),
+             Newlines, PreviousPostfix, CurrentPrefix,
+             Tok.is(TT_LineComment) ? tok::comment : tok::unknown, Tok.Type,
+             InPPDirective && !Tok.IsFirst, IsStartOfDeclName(Tok),
+             /*IsInsideToken=*/Newlines == 0));
 }
 
 const tooling::Replacements &WhitespaceManager::generateReplacements() {
   if (Changes.empty())
     return Replaces;
 
   std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
+  propagateIndentLevels();
   calculateLineBreakInformation();
   alignConsecutiveDeclarations();
   alignConsecutiveAssignments();
@@ -160,59 +162,146 @@
   }
 }
 
+struct TokenTypeAndLevel {
+  TokenType Type;
+  std::pair<unsigned, unsigned> NestingAndIndentLevel;
+};
+
+// Upon entry, IndentLevel is only set on the first token of the line.
+// Here we propagate IndentLevel to every token on the line.
+// In addition, we tweak the NestingLevel slightly, so that it works naturally
+// with the way we recursively process scope depths when
+// performing alignment.
+void WhitespaceManager::propagateIndentLevels() {
+  unsigned IndentLevel =
+      Changes.size() > 0 ? Changes[0].NestingAndIndentLevel.second : 0;
+  for (auto &Change : Changes) {
+    if (Change.NewlinesBefore != 0)
+      IndentLevel = Change.NestingAndIndentLevel.second;
+    Change.NestingAndIndentLevel.second = IndentLevel;
+
+    // NestingLevel is raised on the opening paren/square, and remains raised
+    // until AFTER the closing paren/square. This means that with a statement
+    // like:
+    //
+    // for (int i = 0; ...)
+    //   int x = 1;.
+    //
+    // The "int x = 1" line is going to have the same NestingLevel as
+    // the tokens inside the parentheses of the "for" statement.
+    // In order to break this continuity, we force the closing paren/square to
+    // reduce it's nesting level.
+    // If we don't do this, then "x = 1" ends up getting aligned to "i = 1"
+    if (Change.Kind == tok::r_paren || Change.Kind == tok::r_square)
+      Change.NestingAndIndentLevel.first--;
+  }
+}
+
 // Align a single sequence of tokens, see AlignTokens below.
 template <typename F>
 static void
 AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,
                    SmallVector<WhitespaceManager::Change, 16> &Changes) {
   bool FoundMatchOnLine = false;
   int Shift = 0;
+
+  // ScopeStack keeps track of the current scope depth.
+  // We only run the "Matches" function on tokens from the outer-most scope.
+  // However, we do need to adjust some special tokens within the entire
+  // Start..End range, regardless of their scope. This special rule applies
+  // only to function parameters which are split across multiple lines, and
+  // who's function names have been shifted for declaration alignment's sake.
+  // See "split function parameter alignment" in FormatTest.cpp for an example.
+  SmallVector<TokenTypeAndLevel, 16> ScopeStack;
+
   for (unsigned i = Start; i != End; ++i) {
-    if (Changes[i].NewlinesBefore > 0) {
-      FoundMatchOnLine = false;
+    if (ScopeStack.size() != 0 &&
+        Changes[i].NestingAndIndentLevel <
+            ScopeStack.back().NestingAndIndentLevel)
+      ScopeStack.pop_back();
+
+    if (i != Start) {
+      if (Changes[i].NestingAndIndentLevel >
+          Changes[i - 1].NestingAndIndentLevel) {
+        ScopeStack.push_back(
+            {Changes[i - 1].Type, Changes[i].NestingAndIndentLevel});
+        if (i > Start + 1 && Changes[i - 2].Type == TT_FunctionDeclarationName)
+          ScopeStack.back().Type = Changes[i - 2].Type;
+      }
+    }
+
+    bool InsideNestedScope = ScopeStack.size() != 0;
+
+    if (Changes[i].NewlinesBefore > 0 && !InsideNestedScope) {
       Shift = 0;
+      FoundMatchOnLine = false;
     }
 
     // If this is the first matching token to be aligned, remember by how many
     // spaces it has to be shifted, so the rest of the changes on the line are
     // shifted by the same amount
-    if (!FoundMatchOnLine && Matches(Changes[i])) {
+    if (!FoundMatchOnLine && !InsideNestedScope && Matches(Changes[i])) {
       FoundMatchOnLine = true;
       Shift = Column - Changes[i].StartOfTokenColumn;
       Changes[i].Spaces += Shift;
     }
 
+    // This is for function parameters that are split across multiple lines,
+    // as mentioned in the ScopeStack comment.
+    if (InsideNestedScope && Changes[i].NewlinesBefore > 0 &&
+        ScopeStack.back().Type == TT_FunctionDeclarationName)
+      Changes[i].Spaces += Shift;
+
     assert(Shift >= 0);
     Changes[i].StartOfTokenColumn += Shift;
     if (i + 1 != Changes.size())
       Changes[i + 1].PreviousEndOfTokenColumn += Shift;
   }
 }
 
-// Walk through all of the changes and find sequences of matching tokens to
-// align. To do so, keep track of the lines and whether or not a matching token
-// was found on a line. If a matching token is found, extend the current
-// sequence. If the current line cannot be part of a sequence, e.g. because
-// there is an empty line before it or it contains only non-matching tokens,
-// finalize the previous sequence.
+// Walk through a subset of the changes, starting at StartAt, and find
+// sequences of matching tokens to align. To do so, keep track of the lines and
+// whether or not a matching token was found on a line. If a matching token is
+// found, extend the current sequence. If the current line cannot be part of a
+// sequence, e.g. because there is an empty line before it or it contains only
+// non-matching tokens, finalize the previous sequence.
+// The value returned is the token on which we stopped, either because we
+// exhausted all items inside Changes, or because we hit a scope level higher
+// than our initial scope.
+// This function is recursive. Each invocation processes only the scope level
+// equal to the initial level, which is the level of Changes[StartAt].
+// If we encounter a scope level greater than the initial level, then we call
+// ourselves recursively, thereby avoiding the pollution of the current state
+// with the alignment requirements of the nested sub-level. This recursive
+// behavior is necessary for aligning function prototypes that have one or more
+// arguments.
+// If this function encounters a scope level less than the initial level,
+// it exits.
+// There is a non-obvious subtlety in the recursive behavior: Even though we
+// defer processing of nested levels to recursive invocations of this
+// function, when it comes time to align a sequence of tokens, we run the
+// alignment on the entire sequence, including the nested levels.
+// When doing so, most of the nested tokens are skipped, because their
+// alignment was already handled by the recursive invocations of this function.
+// However, the special exception is that we do NOT skip function parameters
+// that are split across multiple lines. See the test case in FormatTest.cpp
+// that mentions "split function parameter alignment" for an example of this.
 template <typename F>
-static void AlignTokens(const FormatStyle &Style, F &&Matches,
-                        SmallVector<WhitespaceManager::Change, 16> &Changes) {
+static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
+                            SmallVector<WhitespaceManager::Change, 16> &Changes,
+                            unsigned StartAt) {
   unsigned MinColumn = 0;
   unsigned MaxColumn = UINT_MAX;
 
   // Line number of the start and the end of the current token sequence.
   unsigned StartOfSequence = 0;
   unsigned EndOfSequence = 0;
 
-  // Keep track of the nesting level of matching tokens, i.e. the number of
-  // surrounding (), [], or {}. We will only align a sequence of matching
-  // token that share the same scope depth.
-  //
-  // FIXME: This could use FormatToken::NestingLevel information, but there is
-  // an outstanding issue wrt the brace scopes.
-  unsigned NestingLevelOfLastMatch = 0;
-  unsigned NestingLevel = 0;
+  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
+  // abort when we hit any token in a higher scope than the starting one.
+  auto NestingAndIndentLevel = StartAt < Changes.size()
+                                   ? Changes[StartAt].NestingAndIndentLevel
+                                   : std::pair<unsigned, unsigned>(0, 0);
 
   // Keep track of the number of commas before the matching tokens, we will only
   // align a sequence of matching tokens if they are preceded by the same number
@@ -240,7 +329,11 @@
     EndOfSequence = 0;
   };
 
-  for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
+  unsigned i = StartAt;
+  for (unsigned e = Changes.size();
+       i != e && Changes[i].NestingAndIndentLevel >= NestingAndIndentLevel;
+       ++i) {
+
     if (Changes[i].NewlinesBefore != 0) {
       CommasBeforeMatch = 0;
       EndOfSequence = i;
@@ -254,31 +347,23 @@
 
     if (Changes[i].Kind == tok::comma) {
       ++CommasBeforeMatch;
-    } else if (Changes[i].Kind == tok::r_brace ||
-               Changes[i].Kind == tok::r_paren ||
-               Changes[i].Kind == tok::r_square) {
-      --NestingLevel;
-    } else if (Changes[i].Kind == tok::l_brace ||
-               Changes[i].Kind == tok::l_paren ||
-               Changes[i].Kind == tok::l_square) {
-      // We want sequences to skip over child scopes if possible, but not the
-      // other way around.
-      NestingLevelOfLastMatch = std::min(NestingLevelOfLastMatch, NestingLevel);
-      ++NestingLevel;
+    } else if (Changes[i].NestingAndIndentLevel != NestingAndIndentLevel) {
+      // Call AlignTokens recursively, skipping over this scope block.
+      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i);
+      i = StoppedAt - 1;
+      continue;
     }
 
     if (!Matches(Changes[i]))
       continue;
 
     // If there is more than one matching token per line, or if the number of
     // preceding commas, or the scope depth, do not match anymore, end the
     // sequence.
-    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch ||
-        NestingLevel != NestingLevelOfLastMatch)
+    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
       AlignCurrentSequence();
 
     CommasBeforeLastMatch = CommasBeforeMatch;
-    NestingLevelOfLastMatch = NestingLevel;
     FoundMatchOnLine = true;
 
     if (StartOfSequence == 0)
@@ -301,27 +386,27 @@
     MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
   }
 
-  EndOfSequence = Changes.size();
+  unsigned StoppedAt = i;
+  EndOfSequence = i;
   AlignCurrentSequence();
+  return StoppedAt;
 }
 
 void WhitespaceManager::alignConsecutiveAssignments() {
   if (!Style.AlignConsecutiveAssignments)
     return;
 
-  AlignTokens(Style,
-              [&](const Change &C) {
-                // Do not align on equal signs that are first on a line.
-                if (C.NewlinesBefore > 0)
-                  return false;
+  AlignTokens(Style, [&](const Change &C) {
+    // Do not align on equal signs that are first on a line.
+    if (C.NewlinesBefore > 0)
+      return false;
 
-                // Do not align on equal signs that are last on a line.
-                if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
-                  return false;
+    // Do not align on equal signs that are last on a line.
+    if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+      return false;
 
-                return C.Kind == tok::equal;
-              },
-              Changes);
+    return C.Kind == tok::equal;
+  }, Changes, 0);
 }
 
 void WhitespaceManager::alignConsecutiveDeclarations() {
@@ -334,9 +419,8 @@
   //   const char* const* v1;
   //   float const* v2;
   //   SomeVeryLongType const& v3;
-
   AlignTokens(Style, [](Change const &C) { return C.IsStartOfDeclName; },
-              Changes);
+              Changes, 0);
 }
 
 void WhitespaceManager::alignTrailingComments() {
@@ -372,8 +456,7 @@
       unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
           Changes[i].OriginalWhitespaceRange.getEnd());
       for (unsigned j = i + 1; j != e; ++j) {
-        if (Changes[j].Kind == tok::comment ||
-            Changes[j].Kind == tok::unknown)
+        if (Changes[j].Kind == tok::comment || Changes[j].Kind == tok::unknown)
           // Skip over comments and unknown tokens. "unknown tokens are used for
           // the continuation of multiline comments.
           continue;
@@ -486,16 +569,16 @@
                           C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn);
       else
         appendNewlineText(ReplacementText, C.NewlinesBefore);
-      appendIndentText(ReplacementText, C.IndentLevel, std::max(0, C.Spaces),
+      appendIndentText(ReplacementText, C.NestingAndIndentLevel.second,
+                       std::max(0, C.Spaces),
                        C.StartOfTokenColumn - std::max(0, C.Spaces));
       ReplacementText.append(C.CurrentLinePrefix);
       storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
     }
   }
 }
 
-void WhitespaceManager::storeReplacement(SourceRange Range,
-                                         StringRef Text) {
+void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
   unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
                               SourceMgr.getFileOffset(Range.getBegin());
   // Don't create a replacement, if it does not change anything.
@@ -574,5 +657,10 @@
   }
 }
 
+bool WhitespaceManager::IsStartOfDeclName(const FormatToken &Tok) {
+  return Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName) ||
+         Tok.is(tok::kw_operator);
+}
+
 } // namespace format
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to