r194179 - clang-format: Separate line-merging logic into its own class.

Daniel Jasper djasper at google.com
Wed Nov 6 15:12:09 PST 2013


Author: djasper
Date: Wed Nov  6 17:12:09 2013
New Revision: 194179

URL: http://llvm.org/viewvc/llvm-project?rev=194179&view=rev
Log:
clang-format: Separate line-merging logic into its own class.

No functional changes (intended).

Modified:
    cfe/trunk/lib/Format/Format.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=194179&r1=194178&r2=194179&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed Nov  6 17:12:09 2013
@@ -370,6 +370,158 @@ private:
   ContinuationIndenter *Indenter;
 };
 
+class LineJoiner {
+public:
+  LineJoiner(const FormatStyle &Style) : Style(Style) {}
+
+  /// \brief Calculates how many lines can be merged into 1 starting at \p I.
+  unsigned
+  tryFitMultipleLinesInOne(unsigned Indent,
+                           SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
+                           SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
+    // We can never merge stuff if there are trailing line comments.
+    AnnotatedLine *TheLine = *I;
+    if (TheLine->Last->Type == TT_LineComment)
+      return 0;
+
+    if (Indent > Style.ColumnLimit)
+      return 0;
+
+    unsigned Limit = Style.ColumnLimit - Indent;
+    // If we already exceed the column limit, we set 'Limit' to 0. The different
+    // tryMerge..() functions can then decide whether to still do merging.
+    Limit = TheLine->Last->TotalLength > Limit
+                ? 0
+                : Limit - TheLine->Last->TotalLength;
+
+    if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)
+      return 0;
+
+    if (TheLine->Last->is(tok::l_brace)) {
+      return tryMergeSimpleBlock(I, E, Limit);
+    } else if (Style.AllowShortIfStatementsOnASingleLine &&
+               TheLine->First->is(tok::kw_if)) {
+      return tryMergeSimpleControlStatement(I, E, Limit);
+    } else if (Style.AllowShortLoopsOnASingleLine &&
+               TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
+      return tryMergeSimpleControlStatement(I, E, Limit);
+    } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||
+                                          TheLine->First->IsFirst)) {
+      return tryMergeSimplePPDirective(I, E, Limit);
+    }
+    return 0;
+  }
+
+private:
+  unsigned
+  tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
+                            SmallVectorImpl<AnnotatedLine *>::const_iterator E,
+                            unsigned Limit) {
+    if (Limit == 0)
+      return 0;
+    if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)
+      return 0;
+    if (I + 2 != E && (*(I + 2))->InPPDirective &&
+        !(*(I + 2))->First->HasUnescapedNewline)
+      return 0;
+    if (1 + (*(I + 1))->Last->TotalLength > Limit)
+      return 0;
+    return 1;
+  }
+
+  unsigned tryMergeSimpleControlStatement(
+      SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
+      SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
+    if (Limit == 0)
+      return 0;
+    if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&
+        (*(I + 1))->First->is(tok::l_brace))
+      return 0;
+    if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||
+        ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))
+      return 0;
+    AnnotatedLine &Line = **I;
+    if (Line.Last->isNot(tok::r_paren))
+      return 0;
+    if (1 + (*(I + 1))->Last->TotalLength > Limit)
+      return 0;
+    if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
+                                   tok::kw_while) ||
+        (*(I + 1))->First->Type == TT_LineComment)
+      return 0;
+    // Only inline simple if's (no nested if or else).
+    if (I + 2 != E && Line.First->is(tok::kw_if) &&
+        (*(I + 2))->First->is(tok::kw_else))
+      return 0;
+    return 1;
+  }
+
+  unsigned
+  tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
+                      SmallVectorImpl<AnnotatedLine *>::const_iterator E,
+                      unsigned Limit) {
+    // No merging if the brace already is on the next line.
+    if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
+      return 0;
+
+    // First, check that the current line allows merging. This is the case if
+    // we're not in a control flow statement and the last token is an opening
+    // brace.
+    AnnotatedLine &Line = **I;
+    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
+                            tok::kw_else, tok::kw_try, tok::kw_catch,
+                            tok::kw_for,
+                            // This gets rid of all ObjC @ keywords and methods.
+                            tok::at, tok::minus, tok::plus))
+      return 0;
+
+    FormatToken *Tok = (*(I + 1))->First;
+    if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
+        (Tok->getNextNonComment() == NULL ||
+         Tok->getNextNonComment()->is(tok::semi))) {
+      // We merge empty blocks even if the line exceeds the column limit.
+      Tok->SpacesRequiredBefore = 0;
+      Tok->CanBreakBefore = true;
+      return 1;
+    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
+      // Check that we still have three lines and they fit into the limit.
+      if (I + 2 == E || (*(I + 2))->Type == LT_Invalid)
+        return 0;
+
+      if (!nextTwoLinesFitInto(I, Limit))
+        return 0;
+
+      // Second, check that the next line does not contain any braces - if it
+      // does, readability declines when putting it into a single line.
+      if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)
+        return 0;
+      do {
+        if (Tok->isOneOf(tok::l_brace, tok::r_brace))
+          return 0;
+        Tok = Tok->Next;
+      } while (Tok != NULL);
+
+      // Last, check that the third line contains a single closing brace.
+      Tok = (*(I + 2))->First;
+      if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
+          Tok->MustBreakBefore)
+        return 0;
+
+      return 2;
+    }
+    return 0;
+  }
+
+  bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
+                           unsigned Limit) {
+    return 1 + (*(I + 1))->Last->TotalLength + 1 +
+               (*(I + 2))->Last->TotalLength <=
+           Limit;
+  }
+
+  const FormatStyle &Style;
+};
+
 class UnwrappedLineFormatter {
 public:
   UnwrappedLineFormatter(SourceManager &SourceMgr,
@@ -378,9 +530,9 @@ public:
                          WhitespaceManager *Whitespaces,
                          const FormatStyle &Style)
       : SourceMgr(SourceMgr), Ranges(Ranges), Indenter(Indenter),
-        Whitespaces(Whitespaces), Style(Style) {}
+        Whitespaces(Whitespaces), Style(Style), Joiner(Style) {}
 
-  unsigned format(SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
+  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
                   int AdditionalIndent = 0) {
     assert(!Lines.empty());
     unsigned Penalty = 0;
@@ -390,8 +542,8 @@ public:
     bool PreviousLineWasTouched = false;
     const AnnotatedLine *PreviousLine = NULL;
     bool FormatPPDirective = false;
-    for (SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin(),
-                                                    E = Lines.end();
+    for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
+                                                          E = Lines.end();
          I != E; ++I) {
       const AnnotatedLine &TheLine = **I;
       const FormatToken *FirstTok = TheLine.First;
@@ -411,8 +563,13 @@ public:
       unsigned Indent = getIndent(IndentForLevel, TheLine.Level);
       if (static_cast<int>(Indent) + Offset >= 0)
         Indent += Offset;
-      if (!DryRun)
-        tryFitMultipleLinesInOne(Indent, I, E);
+      unsigned MergedLines = Joiner.tryFitMultipleLinesInOne(Indent, I, E);
+      if (!DryRun) {
+        for (unsigned i = 0; i < MergedLines; ++i) {
+          join(**(I + i), **(I + i + 1));
+        }
+      }
+      I += MergedLines;
 
       bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0;
       if (TheLine.First->is(tok::eof)) {
@@ -591,151 +748,6 @@ private:
     return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
   }
 
-  /// \brief Tries to merge lines into one.
-  ///
-  /// This will change \c Line and \c AnnotatedLine to contain the merged line,
-  /// if possible; note that \c I will be incremented when lines are merged.
-  void tryFitMultipleLinesInOne(unsigned Indent,
-                                SmallVectorImpl<AnnotatedLine *>::iterator &I,
-                                SmallVectorImpl<AnnotatedLine *>::iterator E) {
-    // We can never merge stuff if there are trailing line comments.
-    AnnotatedLine *TheLine = *I;
-    if (TheLine->Last->Type == TT_LineComment)
-      return;
-
-    if (Indent > Style.ColumnLimit)
-      return;
-
-    unsigned Limit = Style.ColumnLimit - Indent;
-    // If we already exceed the column limit, we set 'Limit' to 0. The different
-    // tryMerge..() functions can then decide whether to still do merging.
-    Limit = TheLine->Last->TotalLength > Limit
-                ? 0
-                : Limit - TheLine->Last->TotalLength;
-
-    if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)
-      return;
-
-    if (TheLine->Last->is(tok::l_brace)) {
-      tryMergeSimpleBlock(I, E, Limit);
-    } else if (Style.AllowShortIfStatementsOnASingleLine &&
-               TheLine->First->is(tok::kw_if)) {
-      tryMergeSimpleControlStatement(I, E, Limit);
-    } else if (Style.AllowShortLoopsOnASingleLine &&
-               TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
-      tryMergeSimpleControlStatement(I, E, Limit);
-    } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||
-                                          TheLine->First->IsFirst)) {
-      tryMergeSimplePPDirective(I, E, Limit);
-    }
-  }
-
-  void tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::iterator &I,
-                                 SmallVectorImpl<AnnotatedLine *>::iterator E,
-                                 unsigned Limit) {
-    if (Limit == 0)
-      return;
-    AnnotatedLine &Line = **I;
-    if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)
-      return;
-    if (I + 2 != E && (*(I + 2))->InPPDirective &&
-        !(*(I + 2))->First->HasUnescapedNewline)
-      return;
-    if (1 + (*(I + 1))->Last->TotalLength > Limit)
-      return;
-    join(Line, **(++I));
-  }
-
-  void
-  tryMergeSimpleControlStatement(SmallVectorImpl<AnnotatedLine *>::iterator &I,
-                                 SmallVectorImpl<AnnotatedLine *>::iterator E,
-                                 unsigned Limit) {
-    if (Limit == 0)
-      return;
-    if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&
-        (*(I + 1))->First->is(tok::l_brace))
-      return;
-    if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||
-        ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))
-      return;
-    AnnotatedLine &Line = **I;
-    if (Line.Last->isNot(tok::r_paren))
-      return;
-    if (1 + (*(I + 1))->Last->TotalLength > Limit)
-      return;
-    if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
-                                   tok::kw_while) ||
-        (*(I + 1))->First->Type == TT_LineComment)
-      return;
-    // Only inline simple if's (no nested if or else).
-    if (I + 2 != E && Line.First->is(tok::kw_if) &&
-        (*(I + 2))->First->is(tok::kw_else))
-      return;
-    join(Line, **(++I));
-  }
-
-  void tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::iterator &I,
-                           SmallVectorImpl<AnnotatedLine *>::iterator E,
-                           unsigned Limit) {
-    // No merging if the brace already is on the next line.
-    if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
-      return;
-
-    // First, check that the current line allows merging. This is the case if
-    // we're not in a control flow statement and the last token is an opening
-    // brace.
-    AnnotatedLine &Line = **I;
-    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
-                            tok::kw_else, tok::kw_try, tok::kw_catch,
-                            tok::kw_for,
-                            // This gets rid of all ObjC @ keywords and methods.
-                            tok::at, tok::minus, tok::plus))
-      return;
-
-    FormatToken *Tok = (*(I + 1))->First;
-    if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
-        (Tok->getNextNonComment() == NULL ||
-         Tok->getNextNonComment()->is(tok::semi))) {
-      // We merge empty blocks even if the line exceeds the column limit.
-      Tok->SpacesRequiredBefore = 0;
-      Tok->CanBreakBefore = true;
-      join(Line, **(I + 1));
-      I += 1;
-    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
-      // Check that we still have three lines and they fit into the limit.
-      if (I + 2 == E || (*(I + 2))->Type == LT_Invalid ||
-          !nextTwoLinesFitInto(I, Limit))
-        return;
-
-      // Second, check that the next line does not contain any braces - if it
-      // does, readability declines when putting it into a single line.
-      if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)
-        return;
-      do {
-        if (Tok->isOneOf(tok::l_brace, tok::r_brace))
-          return;
-        Tok = Tok->Next;
-      } while (Tok != NULL);
-
-      // Last, check that the third line contains a single closing brace.
-      Tok = (*(I + 2))->First;
-      if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
-          Tok->MustBreakBefore)
-        return;
-
-      join(Line, **(I + 1));
-      join(Line, **(I + 2));
-      I += 2;
-    }
-  }
-
-  bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::iterator I,
-                           unsigned Limit) {
-    return 1 + (*(I + 1))->Last->TotalLength + 1 +
-               (*(I + 2))->Last->TotalLength <=
-           Limit;
-  }
-
   void join(AnnotatedLine &A, const AnnotatedLine &B) {
     assert(!A.Last->Next);
     assert(!B.First->Previous);
@@ -969,6 +981,7 @@ private:
   ContinuationIndenter *Indenter;
   WhitespaceManager *Whitespaces;
   FormatStyle Style;
+  LineJoiner Joiner;
 
   llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
 };





More information about the cfe-commits mailing list