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