<div dir="ltr">Generally makes sense to fix the patch description if the content of the patch changes significantly ;-).</div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 11, 2015 at 10:21 AM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: klimek<br>
Date: Mon May 11 03:21:35 2015<br>
New Revision: 236974<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=236974&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=236974&view=rev</a><br>
Log:<br>
Refactor the formatter of clang-format.<br>
<br>
Pull various parts of the UnwrappedLineFormatter into their own<br>
abstractions. NFC.<br>
<br>
There are two things left for subsequent changes (to keep this<br>
reasonably small)<br>
- the UnwrappedLineFormatter now has a bad name<br>
- the UnwrappedLineFormatter::format function is still too large<br>
<br>
Modified:<br>
    cfe/trunk/lib/Format/Format.cpp<br>
    cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp<br>
    cfe/trunk/lib/Format/UnwrappedLineFormatter.h<br>
<br>
Modified: cfe/trunk/lib/Format/Format.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=236974&r1=236973&r2=236974&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=236974&r1=236973&r2=236974&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/Format.cpp (original)<br>
+++ cfe/trunk/lib/Format/Format.cpp Mon May 11 03:21:35 2015<br>
@@ -1269,9 +1269,9 @@ public:<br>
     ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,<br>
                                   Whitespaces, Encoding,<br>
                                   BinPackInconclusiveFunctions);<br>
-    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style,<br>
-                                     Tokens.getKeywords(), IncompleteFormat);<br>
-    Formatter.format(AnnotatedLines, /*DryRun=*/false);<br>
+    UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),<br>
+                           IncompleteFormat)<br>
+        .format(AnnotatedLines);<br>
     return Whitespaces.generateReplacements();<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=236974&r1=236973&r2=236974&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=236974&r1=236973&r2=236974&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp (original)<br>
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp Mon May 11 03:21:35 2015<br>
@@ -151,8 +151,8 @@ private:<br>
       return 0;<br>
     if (1 + I[1]->Last->TotalLength > Limit)<br>
       return 0;<br>
-    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,<br>
-                             tok::kw_while, TT_LineComment))<br>
+    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while,<br>
+                             TT_LineComment))<br>
       return 0;<br>
     // Only inline simple if's (no nested if or else).<br>
     if (I + 2 != E && Line.First->is(tok::kw_if) &&<br>
@@ -161,9 +161,10 @@ private:<br>
     return 1;<br>
   }<br>
<br>
-  unsigned tryMergeShortCaseLabels(<br>
-      SmallVectorImpl<AnnotatedLine *>::const_iterator I,<br>
-      SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {<br>
+  unsigned<br>
+  tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I,<br>
+                          SmallVectorImpl<AnnotatedLine *>::const_iterator E,<br>
+                          unsigned Limit) {<br>
     if (Limit == 0 || I + 1 == E ||<br>
         I[1]->First->isOneOf(tok::kw_case, tok::kw_default))<br>
       return 0;<br>
@@ -307,40 +308,346 @@ private:<br>
   const AdditionalKeywords &Keywords;<br>
 };<br>
<br>
-class NoColumnLimitFormatter {<br>
+static void markFinalized(FormatToken *Tok) {<br>
+  for (; Tok; Tok = Tok->Next) {<br>
+    Tok->Finalized = true;<br>
+    for (AnnotatedLine *Child : Tok->Children)<br>
+      markFinalized(Child->First);<br>
+  }<br>
+}<br>
+<br>
+#ifndef NDEBUG<br>
+static void printLineState(const LineState &State) {<br>
+  llvm::dbgs() << "State: ";<br>
+  for (const ParenState &P : State.Stack) {<br>
+    llvm::dbgs() << P.Indent << "|" << P.LastSpace << "|" << P.NestedBlockIndent<br>
+                 << " ";<br>
+  }<br>
+  llvm::dbgs() << State.NextToken->TokenText << "\n";<br>
+}<br>
+#endif<br>
+<br>
+/// \brief Base class for classes that format one \c AnnotatedLine.<br>
+class LineFormatter {<br>
+public:<br>
+  LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces,<br>
+                const FormatStyle &Style,<br>
+                UnwrappedLineFormatter *BlockFormatter)<br>
+      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),<br>
+        BlockFormatter(BlockFormatter) {}<br>
+  virtual ~LineFormatter() {}<br>
+<br>
+  /// \brief Formats an \c AnnotatedLine and returns the penalty.<br>
+  ///<br>
+  /// If \p DryRun is \c false, directly applies the changes.<br>
+  virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
+                              bool DryRun) = 0;<br>
+<br>
+protected:<br>
+  /// \brief If the \p State's next token is an r_brace closing a nested block,<br>
+  /// format the nested block before it.<br>
+  ///<br>
+  /// Returns \c true if all children could be placed successfully and adapts<br>
+  /// \p Penalty as well as \p State. If \p DryRun is false, also directly<br>
+  /// creates changes using \c Whitespaces.<br>
+  ///<br>
+  /// The crucial idea here is that children always get formatted upon<br>
+  /// encountering the closing brace right after the nested block. Now, if we<br>
+  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is<br>
+  /// \c false), the entire block has to be kept on the same line (which is only<br>
+  /// possible if it fits on the line, only contains a single statement, etc.<br>
+  ///<br>
+  /// If \p NewLine is true, we format the nested block on separate lines, i.e.<br>
+  /// break after the "{", format all lines with correct indentation and the put<br>
+  /// the closing "}" on yet another new line.<br>
+  ///<br>
+  /// This enables us to keep the simple structure of the<br>
+  /// \c UnwrappedLineFormatter, where we only have two options for each token:<br>
+  /// break or don't break.<br>
+  bool formatChildren(LineState &State, bool NewLine, bool DryRun,<br>
+                      unsigned &Penalty) {<br>
+    const FormatToken *LBrace = State.NextToken->getPreviousNonComment();<br>
+    FormatToken &Previous = *State.NextToken->Previous;<br>
+    if (!LBrace || LBrace->isNot(tok::l_brace) ||<br>
+        LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)<br>
+      // The previous token does not open a block. Nothing to do. We don't<br>
+      // assert so that we can simply call this function for all tokens.<br>
+      return true;<br>
+<br>
+    if (NewLine) {<br>
+      int AdditionalIndent = State.Stack.back().Indent -<br>
+                             Previous.Children[0]->Level * Style.IndentWidth;<br>
+<br>
+      Penalty +=<br>
+          BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,<br>
+                                 /*FixBadIndentation=*/true);<br>
+      return true;<br>
+    }<br>
+<br>
+    if (Previous.Children[0]->First->MustBreakBefore)<br>
+      return false;<br>
+<br>
+    // Cannot merge multiple statements into a single line.<br>
+    if (Previous.Children.size() > 1)<br>
+      return false;<br>
+<br>
+    // Cannot merge into one line if this line ends on a comment.<br>
+    if (Previous.is(tok::comment))<br>
+      return false;<br>
+<br>
+    // We can't put the closing "}" on a line with a trailing comment.<br>
+    if (Previous.Children[0]->Last->isTrailingComment())<br>
+      return false;<br>
+<br>
+    // If the child line exceeds the column limit, we wouldn't want to merge it.<br>
+    // We add +2 for the trailing " }".<br>
+    if (Style.ColumnLimit > 0 &&<br>
+        Previous.Children[0]->Last->TotalLength + State.Column + 2 ><br>
+            Style.ColumnLimit)<br>
+      return false;<br>
+<br>
+    if (!DryRun) {<br>
+      Whitespaces->replaceWhitespace(<br>
+          *Previous.Children[0]->First,<br>
+          /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,<br>
+          /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);<br>
+    }<br>
+    Penalty += formatLine(*Previous.Children[0], State.Column + 1, DryRun);<br>
+<br>
+    State.Column += 1 + Previous.Children[0]->Last->TotalLength;<br>
+    return true;<br>
+  }<br>
+<br>
+  ContinuationIndenter *Indenter;<br>
+<br>
+private:<br>
+  WhitespaceManager *Whitespaces;<br>
+  const FormatStyle &Style;<br>
+  UnwrappedLineFormatter *BlockFormatter;<br>
+};<br>
+<br>
+/// \brief Formatter that keeps the existing line breaks.<br>
+class NoColumnLimitLineFormatter : public LineFormatter {<br>
 public:<br>
-  NoColumnLimitFormatter(ContinuationIndenter *Indenter,<br>
-                         UnwrappedLineFormatter *Formatter)<br>
-      : Indenter(Indenter), Formatter(Formatter) {}<br>
-<br>
-  /// \brief Formats the line starting at \p State, simply keeping all of the<br>
-  /// input's line breaking decisions.<br>
-  void format(unsigned FirstIndent, const AnnotatedLine *Line) {<br>
+  NoColumnLimitLineFormatter(ContinuationIndenter *Indenter,<br>
+                             WhitespaceManager *Whitespaces,<br>
+                             const FormatStyle &Style,<br>
+                             UnwrappedLineFormatter *BlockFormatter)<br>
+      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}<br>
+<br>
+  /// \brief Formats the line, simply keeping all of the input's line breaking<br>
+  /// decisions.<br>
+  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
+                      bool DryRun) override {<br>
+    assert(!DryRun);<br>
     LineState State =<br>
-        Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);<br>
+        Indenter->getInitialState(FirstIndent, &Line, /*DryRun=*/false);<br>
     while (State.NextToken) {<br>
       bool Newline =<br>
           Indenter->mustBreak(State) ||<br>
           (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);<br>
       unsigned Penalty = 0;<br>
-      Formatter->formatChildren(State, Newline, /*DryRun=*/false, Penalty);<br>
+      formatChildren(State, Newline, /*DryRun=*/false, Penalty);<br>
       Indenter->addTokenToState(State, Newline, /*DryRun=*/false);<br>
     }<br>
+    return 0;<br>
   }<br>
+};<br>
<br>
-private:<br>
-  ContinuationIndenter *Indenter;<br>
-  UnwrappedLineFormatter *Formatter;<br>
+/// \brief Formatter that puts all tokens into a single line without breaks.<br>
+class NoLineBreakFormatter : public LineFormatter {<br>
+public:<br>
+  NoLineBreakFormatter(ContinuationIndenter *Indenter,<br>
+                       WhitespaceManager *Whitespaces, const FormatStyle &Style,<br>
+                       UnwrappedLineFormatter *BlockFormatter)<br>
+      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}<br>
+<br>
+  /// \brief Puts all tokens into a single line.<br>
+  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
+                      bool DryRun) {<br>
+    unsigned Penalty = 0;<br>
+    LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);<br>
+    while (State.NextToken) {<br>
+      formatChildren(State, /*Newline=*/false, DryRun, Penalty);<br>
+      Indenter->addTokenToState(State, /*Newline=*/false, DryRun);<br>
+    }<br>
+    return Penalty;<br>
+  }<br>
 };<br>
<br>
+/// \brief Finds the best way to break lines.<br>
+class OptimizingLineFormatter : public LineFormatter {<br>
+public:<br>
+  OptimizingLineFormatter(ContinuationIndenter *Indenter,<br>
+                          WhitespaceManager *Whitespaces,<br>
+                          const FormatStyle &Style,<br>
+                          UnwrappedLineFormatter *BlockFormatter)<br>
+      : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {}<br>
+<br>
+  /// \brief Formats the line by finding the best line breaks with line lengths<br>
+  /// below the column limit.<br>
+  unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,<br>
+                      bool DryRun) {<br>
+    LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);<br>
+<br>
+    // If the ObjC method declaration does not fit on a line, we should format<br>
+    // it with one arg per line.<br>
+    if (State.Line->Type == LT_ObjCMethodDecl)<br>
+      State.Stack.back().BreakBeforeParameter = true;<br>
<br>
-static void markFinalized(FormatToken *Tok) {<br>
-  for (; Tok; Tok = Tok->Next) {<br>
-    Tok->Finalized = true;<br>
-    for (AnnotatedLine *Child : Tok->Children)<br>
-      markFinalized(Child->First);<br>
+    // Find best solution in solution space.<br>
+    return analyzeSolutionSpace(State, DryRun);<br>
+  }<br>
+<br>
+private:<br>
+  struct CompareLineStatePointers {<br>
+    bool operator()(LineState *obj1, LineState *obj2) const {<br>
+      return *obj1 < *obj2;<br>
+    }<br>
+  };<br>
+<br>
+  /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.<br>
+  ///<br>
+  /// In case of equal penalties, we want to prefer states that were inserted<br>
+  /// first. During state generation we make sure that we insert states first<br>
+  /// that break the line as late as possible.<br>
+  typedef std::pair<unsigned, unsigned> OrderedPenalty;<br>
+<br>
+  /// \brief An edge in the solution space from \c Previous->State to \c State,<br>
+  /// inserting a newline dependent on the \c NewLine.<br>
+  struct StateNode {<br>
+    StateNode(const LineState &State, bool NewLine, StateNode *Previous)<br>
+        : State(State), NewLine(NewLine), Previous(Previous) {}<br>
+    LineState State;<br>
+    bool NewLine;<br>
+    StateNode *Previous;<br>
+  };<br>
+<br>
+  /// \brief An item in the prioritized BFS search queue. The \c StateNode's<br>
+  /// \c State has the given \c OrderedPenalty.<br>
+  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;<br>
+<br>
+  /// \brief The BFS queue type.<br>
+  typedef std::priority_queue<QueueItem, std::vector<QueueItem>,<br>
+                              std::greater<QueueItem>> QueueType;<br>
+<br>
+  /// \brief Analyze the entire solution space starting from \p InitialState.<br>
+  ///<br>
+  /// This implements a variant of Dijkstra's algorithm on the graph that spans<br>
+  /// the solution space (\c LineStates are the nodes). The algorithm tries to<br>
+  /// find the shortest path (the one with lowest penalty) from \p InitialState<br>
+  /// to a state where all tokens are placed. Returns the penalty.<br>
+  ///<br>
+  /// If \p DryRun is \c false, directly applies the changes.<br>
+  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) {<br>
+    std::set<LineState *, CompareLineStatePointers> Seen;<br>
+<br>
+    // Increasing count of \c StateNode items we have created. This is used to<br>
+    // create a deterministic order independent of the container.<br>
+    unsigned Count = 0;<br>
+    QueueType Queue;<br>
+<br>
+    // Insert start element into queue.<br>
+    StateNode *Node =<br>
+        new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);<br>
+    Queue.push(QueueItem(OrderedPenalty(0, Count), Node));<br>
+    ++Count;<br>
+<br>
+    unsigned Penalty = 0;<br>
+<br>
+    // While not empty, take first element and follow edges.<br>
+    while (!Queue.empty()) {<br>
+      Penalty = Queue.top().first.first;<br>
+      StateNode *Node = Queue.top().second;<br>
+      if (!Node->State.NextToken) {<br>
+        DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");<br>
+        break;<br>
+      }<br>
+      Queue.pop();<br>
+<br>
+      // Cut off the analysis of certain solutions if the analysis gets too<br>
+      // complex. See description of IgnoreStackForComparison.<br>
+      if (Count > 10000)<br>
+        Node->State.IgnoreStackForComparison = true;<br>
+<br>
+      if (!Seen.insert(&Node->State).second)<br>
+        // State already examined with lower penalty.<br>
+        continue;<br>
+<br>
+      FormatDecision LastFormat = Node->State.NextToken->Decision;<br>
+      if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)<br>
+        addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);<br>
+      if (LastFormat == FD_Unformatted || LastFormat == FD_Break)<br>
+        addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);<br>
+    }<br>
+<br>
+    if (Queue.empty()) {<br>
+      // We were unable to find a solution, do nothing.<br>
+      // FIXME: Add diagnostic?<br>
+      DEBUG(llvm::dbgs() << "Could not find a solution.\n");<br>
+      return 0;<br>
+    }<br>
+<br>
+    // Reconstruct the solution.<br>
+    if (!DryRun)<br>
+      reconstructPath(InitialState, Queue.top().second);<br>
+<br>
+    DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");<br>
+    DEBUG(llvm::dbgs() << "---\n");<br>
+<br>
+    return Penalty;<br>
+  }<br>
+<br>
+  /// \brief Add the following state to the analysis queue \c Queue.<br>
+  ///<br>
+  /// Assume the current state is \p PreviousNode and has been reached with a<br>
+  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.<br>
+  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,<br>
+                           bool NewLine, unsigned *Count, QueueType *Queue) {<br>
+    if (NewLine && !Indenter->canBreak(PreviousNode->State))<br>
+      return;<br>
+    if (!NewLine && Indenter->mustBreak(PreviousNode->State))<br>
+      return;<br>
+<br>
+    StateNode *Node = new (Allocator.Allocate())<br>
+        StateNode(PreviousNode->State, NewLine, PreviousNode);<br>
+    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))<br>
+      return;<br>
+<br>
+    Penalty += Indenter->addTokenToState(Node->State, NewLine, true);<br>
+<br>
+    Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));<br>
+    ++(*Count);<br>
+  }<br>
+<br>
+  /// \brief Applies the best formatting by reconstructing the path in the<br>
+  /// solution space that leads to \c Best.<br>
+  void reconstructPath(LineState &State, StateNode *Best) {<br>
+    std::deque<StateNode *> Path;<br>
+    // We do not need a break before the initial token.<br>
+    while (Best->Previous) {<br>
+      Path.push_front(Best);<br>
+      Best = Best->Previous;<br>
+    }<br>
+    for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();<br>
+         I != E; ++I) {<br>
+      unsigned Penalty = 0;<br>
+      formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);<br>
+      Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);<br>
+<br>
+      DEBUG({<br>
+        printLineState((*I)->Previous->State);<br>
+        if ((*I)->NewLine) {<br>
+          llvm::dbgs() << "Penalty for placing "<br>
+                       << (*I)->Previous->State.NextToken->Tok.getName() << ": "<br>
+                       << Penalty << "\n";<br>
+        }<br>
+      });<br>
+    }<br>
   }<br>
-}<br>
+<br>
+  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;<br>
+};<br>
<br>
 } // namespace<br>
<br>
@@ -431,17 +738,14 @@ UnwrappedLineFormatter::format(const Sma<br>
<br>
       if (TheLine.Last->TotalLength + Indent <= ColumnLimit ||<br>
           TheLine.Type == LT_ImportStatement) {<br>
-        LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);<br>
-        while (State.NextToken) {<br>
-          formatChildren(State, /*Newline=*/false, DryRun, Penalty);<br>
-          Indenter->addTokenToState(State, /*Newline=*/false, DryRun);<br>
-        }<br>
+        Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this)<br>
+                       .formatLine(TheLine, Indent, DryRun);<br>
       } else if (Style.ColumnLimit == 0) {<br>
-        NoColumnLimitFormatter Formatter(Indenter, this);<br>
-        if (!DryRun)<br>
-          Formatter.format(Indent, &TheLine);<br>
+        NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this)<br>
+            .formatLine(TheLine, Indent, DryRun);<br>
       } else {<br>
-        Penalty += format(TheLine, Indent, DryRun);<br>
+        Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)<br>
+                       .formatLine(TheLine, Indent, DryRun);<br>
       }<br>
<br>
       if (!TheLine.InPPDirective)<br>
@@ -486,19 +790,6 @@ UnwrappedLineFormatter::format(const Sma<br>
   return Penalty;<br>
 }<br>
<br>
-unsigned UnwrappedLineFormatter::format(const AnnotatedLine &Line,<br>
-                                        unsigned FirstIndent, bool DryRun) {<br>
-  LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);<br>
-<br>
-  // If the ObjC method declaration does not fit on a line, we should format<br>
-  // it with one arg per line.<br>
-  if (State.Line->Type == LT_ObjCMethodDecl)<br>
-    State.Stack.back().BreakBeforeParameter = true;<br>
-<br>
-  // Find best solution in solution space.<br>
-  return analyzeSolutionSpace(State, DryRun);<br>
-}<br>
-<br>
 void UnwrappedLineFormatter::formatFirstToken(FormatToken &RootToken,<br>
                                               const AnnotatedLine *PreviousLine,<br>
                                               unsigned IndentLevel,<br>
@@ -567,174 +858,5 @@ void UnwrappedLineFormatter::join(Annota<br>
   }<br>
 }<br>
<br>
-unsigned UnwrappedLineFormatter::analyzeSolutionSpace(LineState &InitialState,<br>
-                                                      bool DryRun) {<br>
-  std::set<LineState *, CompareLineStatePointers> Seen;<br>
-<br>
-  // Increasing count of \c StateNode items we have created. This is used to<br>
-  // create a deterministic order independent of the container.<br>
-  unsigned Count = 0;<br>
-  QueueType Queue;<br>
-<br>
-  // Insert start element into queue.<br>
-  StateNode *Node =<br>
-      new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);<br>
-  Queue.push(QueueItem(OrderedPenalty(0, Count), Node));<br>
-  ++Count;<br>
-<br>
-  unsigned Penalty = 0;<br>
-<br>
-  // While not empty, take first element and follow edges.<br>
-  while (!Queue.empty()) {<br>
-    Penalty = Queue.top().first.first;<br>
-    StateNode *Node = Queue.top().second;<br>
-    if (!Node->State.NextToken) {<br>
-      DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");<br>
-      break;<br>
-    }<br>
-    Queue.pop();<br>
-<br>
-    // Cut off the analysis of certain solutions if the analysis gets too<br>
-    // complex. See description of IgnoreStackForComparison.<br>
-    if (Count > 10000)<br>
-      Node->State.IgnoreStackForComparison = true;<br>
-<br>
-    if (!Seen.insert(&Node->State).second)<br>
-      // State already examined with lower penalty.<br>
-      continue;<br>
-<br>
-    FormatDecision LastFormat = Node->State.NextToken->Decision;<br>
-    if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)<br>
-      addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);<br>
-    if (LastFormat == FD_Unformatted || LastFormat == FD_Break)<br>
-      addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);<br>
-  }<br>
-<br>
-  if (Queue.empty()) {<br>
-    // We were unable to find a solution, do nothing.<br>
-    // FIXME: Add diagnostic?<br>
-    DEBUG(llvm::dbgs() << "Could not find a solution.\n");<br>
-    return 0;<br>
-  }<br>
-<br>
-  // Reconstruct the solution.<br>
-  if (!DryRun)<br>
-    reconstructPath(InitialState, Queue.top().second);<br>
-<br>
-  DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");<br>
-  DEBUG(llvm::dbgs() << "---\n");<br>
-<br>
-  return Penalty;<br>
-}<br>
-<br>
-#ifndef NDEBUG<br>
-static void printLineState(const LineState &State) {<br>
-  llvm::dbgs() << "State: ";<br>
-  for (const ParenState &P : State.Stack) {<br>
-    llvm::dbgs() << P.Indent << "|" << P.LastSpace << "|" << P.NestedBlockIndent<br>
-                 << " ";<br>
-  }<br>
-  llvm::dbgs() << State.NextToken->TokenText << "\n";<br>
-}<br>
-#endif<br>
-<br>
-void UnwrappedLineFormatter::reconstructPath(LineState &State,<br>
-                                             StateNode *Current) {<br>
-  std::deque<StateNode *> Path;<br>
-  // We do not need a break before the initial token.<br>
-  while (Current->Previous) {<br>
-    Path.push_front(Current);<br>
-    Current = Current->Previous;<br>
-  }<br>
-  for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();<br>
-       I != E; ++I) {<br>
-    unsigned Penalty = 0;<br>
-    formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);<br>
-    Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);<br>
-<br>
-    DEBUG({<br>
-      printLineState((*I)->Previous->State);<br>
-      if ((*I)->NewLine) {<br>
-        llvm::dbgs() << "Penalty for placing "<br>
-                     << (*I)->Previous->State.NextToken->Tok.getName() << ": "<br>
-                     << Penalty << "\n";<br>
-      }<br>
-    });<br>
-  }<br>
-}<br>
-<br>
-void UnwrappedLineFormatter::addNextStateToQueue(unsigned Penalty,<br>
-                                                 StateNode *PreviousNode,<br>
-                                                 bool NewLine, unsigned *Count,<br>
-                                                 QueueType *Queue) {<br>
-  if (NewLine && !Indenter->canBreak(PreviousNode->State))<br>
-    return;<br>
-  if (!NewLine && Indenter->mustBreak(PreviousNode->State))<br>
-    return;<br>
-<br>
-  StateNode *Node = new (Allocator.Allocate())<br>
-      StateNode(PreviousNode->State, NewLine, PreviousNode);<br>
-  if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))<br>
-    return;<br>
-<br>
-  Penalty += Indenter->addTokenToState(Node->State, NewLine, true);<br>
-<br>
-  Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));<br>
-  ++(*Count);<br>
-}<br>
-<br>
-bool UnwrappedLineFormatter::formatChildren(LineState &State, bool NewLine,<br>
-                                            bool DryRun, unsigned &Penalty) {<br>
-  const FormatToken *LBrace = State.NextToken->getPreviousNonComment();<br>
-  FormatToken &Previous = *State.NextToken->Previous;<br>
-  if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->BlockKind != BK_Block ||<br>
-      Previous.Children.size() == 0)<br>
-    // The previous token does not open a block. Nothing to do. We don't<br>
-    // assert so that we can simply call this function for all tokens.<br>
-    return true;<br>
-<br>
-  if (NewLine) {<br>
-    int AdditionalIndent = State.Stack.back().Indent -<br>
-                           Previous.Children[0]->Level * Style.IndentWidth;<br>
-<br>
-    Penalty += format(Previous.Children, DryRun, AdditionalIndent,<br>
-                      /*FixBadIndentation=*/true);<br>
-    return true;<br>
-  }<br>
-<br>
-  if (Previous.Children[0]->First->MustBreakBefore)<br>
-    return false;<br>
-<br>
-  // Cannot merge multiple statements into a single line.<br>
-  if (Previous.Children.size() > 1)<br>
-    return false;<br>
-<br>
-  // Cannot merge into one line if this line ends on a comment.<br>
-  if (Previous.is(tok::comment))<br>
-    return false;<br>
-<br>
-  // We can't put the closing "}" on a line with a trailing comment.<br>
-  if (Previous.Children[0]->Last->isTrailingComment())<br>
-    return false;<br>
-<br>
-  // If the child line exceeds the column limit, we wouldn't want to merge it.<br>
-  // We add +2 for the trailing " }".<br>
-  if (Style.ColumnLimit > 0 &&<br>
-      Previous.Children[0]->Last->TotalLength + State.Column + 2 ><br>
-          Style.ColumnLimit)<br>
-    return false;<br>
-<br>
-  if (!DryRun) {<br>
-    Whitespaces->replaceWhitespace(<br>
-        *Previous.Children[0]->First,<br>
-        /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,<br>
-        /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);<br>
-  }<br>
-  Penalty += format(*Previous.Children[0], State.Column + 1, DryRun);<br>
-<br>
-  State.Column += 1 + Previous.Children[0]->Last->TotalLength;<br>
-  return true;<br>
-}<br>
-<br>
 } // namespace format<br>
 } // namespace clang<br>
<br>
Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.h?rev=236974&r1=236973&r2=236974&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.h?rev=236974&r1=236973&r2=236974&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.h (original)<br>
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.h Mon May 11 03:21:35 2015<br>
@@ -38,65 +38,12 @@ public:<br>
       : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),<br>
         Keywords(Keywords), IncompleteFormat(IncompleteFormat) {}<br>
<br>
-  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,<br>
-                  int AdditionalIndent = 0, bool FixBadIndentation = false);<br>
-<br>
-<br>
-  /// \brief If the \p State's next token is an r_brace closing a nested block,<br>
-  /// format the nested block before it.<br>
-  ///<br>
-  /// Returns \c true if all children could be placed successfully and adapts<br>
-  /// \p Penalty as well as \p State. If \p DryRun is false, also directly<br>
-  /// creates changes using \c Whitespaces.<br>
-  ///<br>
-  /// The crucial idea here is that children always get formatted upon<br>
-  /// encountering the closing brace right after the nested block. Now, if we<br>
-  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is<br>
-  /// \c false), the entire block has to be kept on the same line (which is only<br>
-  /// possible if it fits on the line, only contains a single statement, etc.<br>
-  ///<br>
-  /// If \p NewLine is true, we format the nested block on separate lines, i.e.<br>
-  /// break after the "{", format all lines with correct indentation and the put<br>
-  /// the closing "}" on yet another new line.<br>
-  ///<br>
-  /// This enables us to keep the simple structure of the<br>
-  /// \c UnwrappedLineFormatter, where we only have two options for each token:<br>
-  /// break or don't break.<br>
-  bool formatChildren(LineState &State, bool NewLine, bool DryRun,<br>
-                      unsigned &Penalty);<br>
+  /// \brief Format the current block and return the penalty.<br>
+  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,<br>
+                  bool DryRun = false, int AdditionalIndent = 0,<br>
+                  bool FixBadIndentation = false);<br>
<br>
 private:<br>
-  /// \brief Formats an \c AnnotatedLine and returns the penalty.<br>
-  ///<br>
-  /// If \p DryRun is \c false, directly applies the changes.<br>
-  unsigned format(const AnnotatedLine &Line, unsigned FirstIndent,<br>
-                  bool DryRun);<br>
-<br>
-  /// \brief An edge in the solution space from \c Previous->State to \c State,<br>
-  /// inserting a newline dependent on the \c NewLine.<br>
-  struct StateNode {<br>
-    StateNode(const LineState &State, bool NewLine, StateNode *Previous)<br>
-        : State(State), NewLine(NewLine), Previous(Previous) {}<br>
-    LineState State;<br>
-    bool NewLine;<br>
-    StateNode *Previous;<br>
-  };<br>
-<br>
-  /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.<br>
-  ///<br>
-  /// In case of equal penalties, we want to prefer states that were inserted<br>
-  /// first. During state generation we make sure that we insert states first<br>
-  /// that break the line as late as possible.<br>
-  typedef std::pair<unsigned, unsigned> OrderedPenalty;<br>
-<br>
-  /// \brief An item in the prioritized BFS search queue. The \c StateNode's<br>
-  /// \c State has the given \c OrderedPenalty.<br>
-  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;<br>
-<br>
-  /// \brief The BFS queue type.<br>
-  typedef std::priority_queue<QueueItem, std::vector<QueueItem>,<br>
-                              std::greater<QueueItem> > QueueType;<br>
-<br>
   /// \brief Get the offset of the line relatively to the level.<br>
   ///<br>
   /// For example, 'public:' labels in classes are offset by 1 or 2<br>
@@ -133,44 +80,16 @@ private:<br>
     return Style.ColumnLimit - (InPPDirective ? 2 : 0);<br>
   }<br>
<br>
-  struct CompareLineStatePointers {<br>
-    bool operator()(LineState *obj1, LineState *obj2) const {<br>
-      return *obj1 < *obj2;<br>
-    }<br>
-  };<br>
-<br>
-  /// \brief Analyze the entire solution space starting from \p InitialState.<br>
-  ///<br>
-  /// This implements a variant of Dijkstra's algorithm on the graph that spans<br>
-  /// the solution space (\c LineStates are the nodes). The algorithm tries to<br>
-  /// find the shortest path (the one with lowest penalty) from \p InitialState<br>
-  /// to a state where all tokens are placed. Returns the penalty.<br>
-  ///<br>
-  /// If \p DryRun is \c false, directly applies the changes.<br>
-  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false);<br>
-<br>
-  void reconstructPath(LineState &State, StateNode *Current);<br>
-<br>
-  /// \brief Add the following state to the analysis queue \c Queue.<br>
-  ///<br>
-  /// Assume the current state is \p PreviousNode and has been reached with a<br>
-  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.<br>
-  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,<br>
-                           bool NewLine, unsigned *Count, QueueType *Queue);<br>
-<br>
-  ContinuationIndenter *Indenter;<br>
-  WhitespaceManager *Whitespaces;<br>
-  FormatStyle Style;<br>
-  const AdditionalKeywords &Keywords;<br>
-<br>
-  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;<br>
-<br>
   // Cache to store the penalty of formatting a vector of AnnotatedLines<br>
   // starting from a specific additional offset. Improves performance if there<br>
   // are many nested blocks.<br>
   std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,<br>
            unsigned> PenaltyCache;<br>
<br>
+  ContinuationIndenter *Indenter;<br>
+  WhitespaceManager *Whitespaces;<br>
+  const FormatStyle &Style;<br>
+  const AdditionalKeywords &Keywords;<br>
   bool *IncompleteFormat;<br>
 };<br>
 } // end namespace format<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>