unsigned UnwrappedLineFormatter::analyzeSolutionSpace(LineState &InitialState, bool DryRun) { std::set<LineState *, CompareLineStatePointers> Seen; // Increasing count of \c StateNode items we have created. This is used to // create a deterministic order independent of the container. unsigned Count = 0; QueueType Queue; // Insert start element into queue. StateNode *Node = new (Allocator.Allocate()) StateNode(InitialState, false, nullptr); Queue.push(QueueItem(OrderedPenalty(0, Count), Node)); ++Count; unsigned Penalty = 0; // While not empty, take first element and follow edges. while (!Queue.empty()) { Penalty = Queue.top().first.first; StateNode *Node = Queue.top().second; if (!Node->State.NextToken) { DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n"); break; } Queue.pop(); // Cut off the analysis of certain solutions if the analysis gets too // complex. See description of IgnoreStackForComparison. if (Count > 10000) Node->State.IgnoreStackForComparison = true; if (!Seen.insert(&Node->State).second) // State already examined with lower penalty. continue; FormatDecision LastFormat = Node->State.NextToken->Decision; if (LastFormat == FD_Unformatted || LastFormat == FD_Continue) addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue); if (LastFormat == FD_Unformatted || LastFormat == FD_Break) addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue); } if (Queue.empty()) { // We were unable to find a solution, do nothing. // FIXME: Add diagnostic? DEBUG(llvm::dbgs() << "Could not find a solution.\n"); return 0; } // Reconstruct the solution. if (!DryRun) reconstructPath(InitialState, Queue.top().second); DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n"); DEBUG(llvm::dbgs() << "---\n"); return Penalty; }
/// \brief Add the following state to the analysis queue \c Queue. /// /// Assume the current state is \p PreviousNode and has been reached with a /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true. void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode, bool NewLine, unsigned *Count, QueueType *Queue) { if (NewLine && !Indenter->canBreak(PreviousNode->State)) return; if (!NewLine && Indenter->mustBreak(PreviousNode->State)) return; StateNode *Node = new (Allocator.Allocate()) StateNode(PreviousNode->State, NewLine, PreviousNode); if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty)) return; Penalty += Indenter->addTokenToState(Node->State, NewLine, true); Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node)); ++(*Count); }