<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">This patch causes this failure on a VS buildbot machine.<div><br></div><div><pre style="font-family: 'Courier New', courier, monotype, monospace; "><span class="stdout">style-on-command-line.cpp</span></pre><div>- Fariborz</div><div><br></div><div><div>On Nov 5, 2013, at 11:10 AM, Daniel Jasper <<a href="mailto:djasper@google.com">djasper@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Author: djasper<br>Date: Tue Nov 5 13:10:03 2013<br>New Revision: 194090<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194090&view=rev">http://llvm.org/viewvc/llvm-project?rev=194090&view=rev</a><br>Log:<br>clang-format: Allow line merging and partial formatting of nested blocks<br><br>Before, clang-format would always format entire nested blocks, which<br>can be unwanted e.g. for long DEBUG({...}) statements. Also<br>clang-format would not allow to merge lines in nested blocks (e.g. to<br>put "if (a) return;" on one line in Google style).<br><br>This is the first step of several refactorings mostly focussing on the<br>additional functionality (by reusing the "format many lines" code to<br>format the children of a nested block). The next steps are:<br>* Pull out the line merging into its own class.<br>* Seperate the formatting of many lines from the formatting of a single<br> line (and the analysis of the solution space).<br><br>Modified:<br> cfe/trunk/lib/Format/Format.cpp<br> cfe/trunk/lib/Format/TokenAnnotator.cpp<br> cfe/trunk/unittests/Format/FormatTest.cpp<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=194090&r1=194089&r2=194090&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=194090&r1=194089&r2=194090&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Format/Format.cpp (original)<br>+++ cfe/trunk/lib/Format/Format.cpp Tue Nov 5 13:10:03 2013<br>@@ -372,28 +372,148 @@ private:<br><br> class UnwrappedLineFormatter {<br> public:<br>- UnwrappedLineFormatter(ContinuationIndenter *Indenter,<br>+ UnwrappedLineFormatter(SourceManager &SourceMgr,<br>+ SmallVectorImpl<CharSourceRange> &Ranges,<br>+ ContinuationIndenter *Indenter,<br> WhitespaceManager *Whitespaces,<br>- const FormatStyle &Style, const AnnotatedLine &Line)<br>- : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), Line(Line),<br>- Count(0) {}<br>+ const FormatStyle &Style)<br>+ : SourceMgr(SourceMgr), Ranges(Ranges), Indenter(Indenter),<br>+ Whitespaces(Whitespaces), Style(Style) {}<br>+<br>+ unsigned format(SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,<br>+ int AdditionalIndent = 0) {<br>+ assert(!Lines.empty());<br>+ unsigned Penalty = 0;<br>+ std::vector<int> IndentForLevel;<br>+ for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)<br>+ IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);<br>+ bool PreviousLineWasTouched = false;<br>+ const AnnotatedLine *PreviousLine = NULL;<br>+ bool FormatPPDirective = false;<br>+ for (SmallVectorImpl<AnnotatedLine *>::iterator I = Lines.begin(),<br>+ E = Lines.end();<br>+ I != E; ++I) {<br>+ const AnnotatedLine &TheLine = **I;<br>+ const FormatToken *FirstTok = TheLine.First;<br>+ int Offset = getIndentOffset(*FirstTok);<br>+<br>+ // Check whether this line is part of a formatted preprocessor directive.<br>+ if (FirstTok->HasUnescapedNewline)<br>+ FormatPPDirective = false;<br>+ if (!FormatPPDirective && TheLine.InPPDirective &&<br>+ (touchesLine(TheLine) || touchesPPDirective(I + 1, E)))<br>+ FormatPPDirective = true;<br>+<br>+ // Determine indent and try to merge multiple unwrapped lines.<br>+ while (IndentForLevel.size() <= TheLine.Level)<br>+ IndentForLevel.push_back(-1);<br>+ IndentForLevel.resize(TheLine.Level + 1);<br>+ unsigned Indent = getIndent(IndentForLevel, TheLine.Level);<br>+ if (static_cast<int>(Indent) + Offset >= 0)<br>+ Indent += Offset;<br>+ if (!DryRun)<br>+ tryFitMultipleLinesInOne(Indent, I, E);<br>+<br>+ bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0;<br>+ if (TheLine.First->is(tok::eof)) {<br>+ if (PreviousLineWasTouched && !DryRun) {<br>+ unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);<br>+ Whitespaces->replaceWhitespace(*TheLine.First, Newlines,<br>+ /*IndentLevel=*/0, /*Spaces=*/0,<br>+ /*TargetColumn=*/0);<br>+ }<br>+ } else if (TheLine.Type != LT_Invalid &&<br>+ (WasMoved || FormatPPDirective || touchesLine(TheLine))) {<br>+ unsigned LevelIndent =<br>+ getIndent(IndentForLevel, TheLine.Level);<br>+ if (FirstTok->WhitespaceRange.isValid()) {<br>+ if (!DryRun)<br>+ formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level,<br>+ Indent, TheLine.InPPDirective);<br>+ } else {<br>+ Indent = LevelIndent = FirstTok->OriginalColumn;<br>+ }<br>+<br>+ // If everything fits on a single line, just put it there.<br>+ unsigned ColumnLimit = Style.ColumnLimit;<br>+ if (I + 1 != E) {<br>+ AnnotatedLine *NextLine = *(I + 1);<br>+ if (NextLine->InPPDirective && !NextLine->First->HasUnescapedNewline)<br>+ ColumnLimit = getColumnLimit(TheLine.InPPDirective);<br>+ }<br>+<br>+ if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {<br>+ LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);<br>+ while (State.NextToken != NULL)<br>+ Indenter->addTokenToState(State, /*Newline=*/false, DryRun);<br>+ } else if (Style.ColumnLimit == 0) {<br>+ NoColumnLimitFormatter Formatter(Indenter);<br>+ if (!DryRun)<br>+ Formatter.format(Indent, &TheLine);<br>+ } else {<br>+ Penalty += format(TheLine, Indent, DryRun);<br>+ }<br>+<br>+ IndentForLevel[TheLine.Level] = LevelIndent;<br>+ PreviousLineWasTouched = true;<br>+ } else {<br>+ // Format the first token if necessary, and notify the WhitespaceManager<br>+ // about the unchanged whitespace.<br>+ for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {<br>+ if (Tok == TheLine.First &&<br>+ (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {<br>+ unsigned LevelIndent = Tok->OriginalColumn;<br>+ if (!DryRun) {<br>+ // Remove trailing whitespace of the previous line if it was<br>+ // touched.<br>+ if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) {<br>+ formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,<br>+ TheLine.InPPDirective);<br>+ } else {<br>+ Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);<br>+ }<br>+ }<br>+<br>+ if (static_cast<int>(LevelIndent) - Offset >= 0)<br>+ LevelIndent -= Offset;<br>+ if (Tok->isNot(tok::comment))<br>+ IndentForLevel[TheLine.Level] = LevelIndent;<br>+ } else if (!DryRun) {<br>+ Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);<br>+ }<br>+ }<br>+ // If we did not reformat this unwrapped line, the column at the end of<br>+ // the last token is unchanged - thus, we can calculate the end of the<br>+ // last token.<br>+ PreviousLineWasTouched = false;<br>+ }<br>+ if (!DryRun) {<br>+ for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {<br>+ Tok->Finalized = true;<br>+ }<br>+ }<br>+ PreviousLine = *I;<br>+ }<br>+ return Penalty;<br>+ }<br><br>- /// \brief Formats an \c UnwrappedLine and returns the penalty.<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(unsigned FirstIndent, bool DryRun = false) {<br>+ unsigned format(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 (Line.Type == LT_ObjCMethodDecl)<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>-private:<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>@@ -419,6 +539,262 @@ private:<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>+ /// characters to the left from their level.<br>+ int getIndentOffset(const FormatToken &RootToken) {<br>+ if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())<br>+ return Style.AccessModifierOffset;<br>+ return 0;<br>+ }<br>+<br>+ /// \brief Add a new line and the required indent before the first Token<br>+ /// of the \c UnwrappedLine if there was no structural parsing error.<br>+ void formatFirstToken(FormatToken &RootToken,<br>+ const AnnotatedLine *PreviousLine, unsigned IndentLevel,<br>+ unsigned Indent, bool InPPDirective) {<br>+ unsigned Newlines =<br>+ std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);<br>+ // Remove empty lines before "}" where applicable.<br>+ if (<a href="http://RootToken.is">RootToken.is</a>(tok::r_brace) &&<br>+ (!RootToken.Next ||<br>+ (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))<br>+ Newlines = std::min(Newlines, 1u);<br>+ if (Newlines == 0 && !RootToken.IsFirst)<br>+ Newlines = 1;<br>+<br>+ // Insert extra new line before access specifiers.<br>+ if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&<br>+ RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)<br>+ ++Newlines;<br>+<br>+ // Remove empty lines after access specifiers.<br>+ if (PreviousLine && PreviousLine->First->isAccessSpecifier())<br>+ Newlines = std::min(1u, Newlines);<br>+<br>+ Whitespaces->replaceWhitespace(<br>+ RootToken, Newlines, IndentLevel, Indent, Indent,<br>+ InPPDirective && !RootToken.HasUnescapedNewline);<br>+ }<br>+<br>+ /// \brief Get the indent of \p Level from \p IndentForLevel.<br>+ ///<br>+ /// \p IndentForLevel must contain the indent for the level \c l<br>+ /// at \p IndentForLevel[l], or a value < 0 if the indent for<br>+ /// that level is unknown.<br>+ unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) {<br>+ if (IndentForLevel[Level] != -1)<br>+ return IndentForLevel[Level];<br>+ if (Level == 0)<br>+ return 0;<br>+ return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;<br>+ }<br>+<br>+ /// \brief Tries to merge lines into one.<br>+ ///<br>+ /// This will change \c Line and \c AnnotatedLine to contain the merged line,<br>+ /// if possible; note that \c I will be incremented when lines are merged.<br>+ void tryFitMultipleLinesInOne(unsigned Indent,<br>+ SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>+ SmallVectorImpl<AnnotatedLine *>::iterator E) {<br>+ // We can never merge stuff if there are trailing line comments.<br>+ AnnotatedLine *TheLine = *I;<br>+ if (TheLine->Last->Type == TT_LineComment)<br>+ return;<br>+<br>+ if (Indent > Style.ColumnLimit)<br>+ return;<br>+<br>+ unsigned Limit = Style.ColumnLimit - Indent;<br>+ // If we already exceed the column limit, we set 'Limit' to 0. The different<br>+ // tryMerge..() functions can then decide whether to still do merging.<br>+ Limit = TheLine->Last->TotalLength > Limit<br>+ ? 0<br>+ : Limit - TheLine->Last->TotalLength;<br>+<br>+ if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)<br>+ return;<br>+<br>+ if (TheLine->Last->is(tok::l_brace)) {<br>+ tryMergeSimpleBlock(I, E, Limit);<br>+ } else if (Style.AllowShortIfStatementsOnASingleLine &&<br>+ TheLine->First->is(tok::kw_if)) {<br>+ tryMergeSimpleControlStatement(I, E, Limit);<br>+ } else if (Style.AllowShortLoopsOnASingleLine &&<br>+ TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {<br>+ tryMergeSimpleControlStatement(I, E, Limit);<br>+ } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||<br>+ TheLine->First->IsFirst)) {<br>+ tryMergeSimplePPDirective(I, E, Limit);<br>+ }<br>+ }<br>+<br>+ void tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>+ SmallVectorImpl<AnnotatedLine *>::iterator E,<br>+ unsigned Limit) {<br>+ if (Limit == 0)<br>+ return;<br>+ AnnotatedLine &Line = **I;<br>+ if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)<br>+ return;<br>+ if (I + 2 != E && (*(I + 2))->InPPDirective &&<br>+ !(*(I + 2))->First->HasUnescapedNewline)<br>+ return;<br>+ if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>+ return;<br>+ join(Line, **(++I));<br>+ }<br>+<br>+ void<br>+ tryMergeSimpleControlStatement(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>+ SmallVectorImpl<AnnotatedLine *>::iterator E,<br>+ unsigned Limit) {<br>+ if (Limit == 0)<br>+ return;<br>+ if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&<br>+ (*(I + 1))->First->is(tok::l_brace))<br>+ return;<br>+ if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||<br>+ ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))<br>+ return;<br>+ AnnotatedLine &Line = **I;<br>+ if (Line.Last->isNot(tok::r_paren))<br>+ return;<br>+ if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>+ return;<br>+ if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,<br>+ tok::kw_while) ||<br>+ (*(I + 1))->First->Type == TT_LineComment)<br>+ return;<br>+ // Only inline simple if's (no nested if or else).<br>+ if (I + 2 != E && Line.First->is(tok::kw_if) &&<br>+ (*(I + 2))->First->is(tok::kw_else))<br>+ return;<br>+ join(Line, **(++I));<br>+ }<br>+<br>+ void tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>+ SmallVectorImpl<AnnotatedLine *>::iterator E,<br>+ unsigned Limit) {<br>+ // No merging if the brace already is on the next line.<br>+ if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)<br>+ return;<br>+<br>+ // First, check that the current line allows merging. This is the case if<br>+ // we're not in a control flow statement and the last token is an opening<br>+ // brace.<br>+ AnnotatedLine &Line = **I;<br>+ if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,<br>+ tok::kw_else, tok::kw_try, tok::kw_catch,<br>+ tok::kw_for,<br>+ // This gets rid of all ObjC @ keywords and methods.<br>+ tok::at, tok::minus, tok::plus))<br>+ return;<br>+<br>+ FormatToken *Tok = (*(I + 1))->First;<br>+ if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&<br>+ (Tok->getNextNonComment() == NULL ||<br>+ Tok->getNextNonComment()->is(tok::semi))) {<br>+ // We merge empty blocks even if the line exceeds the column limit.<br>+ Tok->SpacesRequiredBefore = 0;<br>+ Tok->CanBreakBefore = true;<br>+ join(Line, **(I + 1));<br>+ I += 1;<br>+ } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {<br>+ // Check that we still have three lines and they fit into the limit.<br>+ if (I + 2 == E || (*(I + 2))->Type == LT_Invalid ||<br>+ !nextTwoLinesFitInto(I, Limit))<br>+ return;<br>+<br>+ // Second, check that the next line does not contain any braces - if it<br>+ // does, readability declines when putting it into a single line.<br>+ if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)<br>+ return;<br>+ do {<br>+ if (Tok->isOneOf(tok::l_brace, tok::r_brace))<br>+ return;<br>+ Tok = Tok->Next;<br>+ } while (Tok != NULL);<br>+<br>+ // Last, check that the third line contains a single closing brace.<br>+ Tok = (*(I + 2))->First;<br>+ if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||<br>+ Tok->MustBreakBefore)<br>+ return;<br>+<br>+ join(Line, **(I + 1));<br>+ join(Line, **(I + 2));<br>+ I += 2;<br>+ }<br>+ }<br>+<br>+ bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::iterator I,<br>+ unsigned Limit) {<br>+ return 1 + (*(I + 1))->Last->TotalLength + 1 +<br>+ (*(I + 2))->Last->TotalLength <=<br>+ Limit;<br>+ }<br>+<br>+ void join(AnnotatedLine &A, const AnnotatedLine &B) {<br>+ assert(!A.Last->Next);<br>+ assert(!B.First->Previous);<br>+ A.Last->Next = B.First;<br>+ B.First->Previous = A.Last;<br>+ unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;<br>+ for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {<br>+ Tok->TotalLength += LengthA;<br>+ A.Last = Tok;<br>+ }<br>+ }<br>+<br>+ unsigned getColumnLimit(bool InPPDirective) const {<br>+ // In preprocessor directives reserve two chars for trailing " \"<br>+ return Style.ColumnLimit - (InPPDirective ? 2 : 0);<br>+ }<br>+<br>+ bool touchesRanges(const CharSourceRange &Range) {<br>+ for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),<br>+ E = Ranges.end();<br>+ I != E; ++I) {<br>+ if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&<br>+ !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))<br>+ return true;<br>+ }<br>+ return false;<br>+ }<br>+<br>+ bool touchesLine(const AnnotatedLine &TheLine) {<br>+ const FormatToken *First = TheLine.First;<br>+ const FormatToken *Last = TheLine.Last;<br>+ CharSourceRange LineRange = CharSourceRange::getCharRange(<br>+ First->WhitespaceRange.getBegin().getLocWithOffset(<br>+ First->LastNewlineOffset),<br>+ Last->getStartOfNonWhitespace().getLocWithOffset(<br>+ Last->TokenText.size() - 1));<br>+ return touchesRanges(LineRange);<br>+ }<br>+<br>+ bool touchesPPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,<br>+ SmallVectorImpl<AnnotatedLine *>::const_iterator E) {<br>+ for (; I != E; ++I) {<br>+ if ((*I)->First->HasUnescapedNewline)<br>+ return false;<br>+ if (touchesLine(**I))<br>+ return true;<br>+ }<br>+ return false;<br>+ }<br>+<br>+ bool touchesEmptyLineBefore(const AnnotatedLine &TheLine) {<br>+ const FormatToken *First = TheLine.First;<br>+ CharSourceRange LineRange = CharSourceRange::getCharRange(<br>+ First->WhitespaceRange.getBegin(),<br>+ First->WhitespaceRange.getBegin().getLocWithOffset(<br>+ First->LastNewlineOffset));<br>+ return touchesRanges(LineRange);<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>@@ -430,6 +806,11 @@ private:<br> unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {<br> std::set<LineState> 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, NULL);<br>@@ -459,9 +840,9 @@ private:<br><br> FormatDecision LastFormat = Node->State.NextToken->Decision;<br> if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)<br>- addNextStateToQueue(Penalty, Node, /*NewLine=*/false);<br>+ addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);<br> if (LastFormat == FD_Unformatted || LastFormat == FD_Break)<br>- addNextStateToQueue(Penalty, Node, /*NewLine=*/true);<br>+ addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);<br> }<br><br> if (Queue.empty()) {<br>@@ -509,7 +890,7 @@ private:<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) {<br>+ bool NewLine, unsigned *Count, QueueType *Queue) {<br> if (NewLine && !Indenter->canBreak(PreviousNode->State))<br> return;<br> if (!NewLine && Indenter->mustBreak(PreviousNode->State))<br>@@ -522,8 +903,8 @@ private:<br><br> Penalty += Indenter->addTokenToState(Node->State, NewLine, true);<br><br>- Queue.push(QueueItem(OrderedPenalty(Penalty, Count), Node));<br>- ++Count;<br>+ Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));<br>+ ++(*Count);<br> }<br><br> /// \brief If the \p State's next token is an r_brace closing a nested block,<br>@@ -548,7 +929,7 @@ private:<br> /// break or don't break.<br> bool formatChildren(LineState &State, bool NewLine, bool DryRun,<br> unsigned &Penalty) {<br>- const FormatToken &Previous = *State.NextToken->Previous;<br>+ FormatToken &Previous = *State.NextToken->Previous;<br> const FormatToken *LBrace = State.NextToken->getPreviousNonComment();<br> if (!LBrace || LBrace->isNot(tok::l_brace) ||<br> LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)<br>@@ -557,29 +938,15 @@ private:<br> return true;<br><br> if (NewLine) {<br>- unsigned ParentIndent = State.Stack.back().Indent;<br>- for (SmallVector<AnnotatedLine *, 1>::const_iterator<br>- I = Previous.Children.begin(),<br>- E = Previous.Children.end();<br>- I != E; ++I) {<br>- unsigned Indent =<br>- ParentIndent + ((*I)->Level - Line.Level - 1) * Style.IndentWidth;<br>- if (!DryRun) {<br>- unsigned Newlines = std::min((*I)->First->NewlinesBefore,<br>- Style.MaxEmptyLinesToKeep + 1);<br>- Newlines = std::max(1u, Newlines);<br>- Whitespaces->replaceWhitespace(<br>- *(*I)->First, Newlines, (*I)->Level, /*Spaces=*/Indent,<br>- /*StartOfTokenColumn=*/Indent, Line.InPPDirective);<br>- }<br>- UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style, **I);<br>- Penalty += Formatter.format(Indent, DryRun);<br>- }<br>+ int AdditionalIndent = State.Stack.back().Indent -<br>+ Previous.Children[0]->Level * Style.IndentWidth;<br>+ Penalty += format(Previous.Children, DryRun, AdditionalIndent);<br> return true;<br> }<br><br>+ // Cannot merge multiple statements into a single line.<br> if (Previous.Children.size() > 1)<br>- return false; // Cannot merge multiple statements into a single line.<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>@@ -590,25 +957,20 @@ private:<br> *Previous.Children[0]->First,<br> /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,<br> /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);<br>- UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style,<br>- *Previous.Children[0]);<br>- Penalty += Formatter.format(State.Column + 1, DryRun);<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>+ SourceManager &SourceMgr;<br>+ SmallVectorImpl<CharSourceRange> &Ranges;<br> ContinuationIndenter *Indenter;<br> WhitespaceManager *Whitespaces;<br> FormatStyle Style;<br>- const AnnotatedLine &Line;<br><br> llvm::SpecificBumpPtrAllocator<StateNode> Allocator;<br>- QueueType Queue;<br>- // Increasing count of \c StateNode items we have created. This is used<br>- // to create a deterministic order independent of the container.<br>- unsigned Count;<br> };<br><br> class FormatTokenLexer {<br>@@ -831,7 +1193,7 @@ public:<br> const std::vector<CharSourceRange> &Ranges)<br> : Style(Style), Lex(Lex), SourceMgr(SourceMgr),<br> Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())),<br>- Ranges(Ranges), UnwrappedLines(1),<br>+ Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1),<br> Encoding(encoding::detectEncoding(Lex.getBuffer())) {<br> DEBUG(llvm::dbgs() << "File encoding: "<br> << (Encoding == encoding::Encoding_UTF8 ? "UTF8"<br>@@ -875,120 +1237,20 @@ public:<br> tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,<br> bool StructuralError, FormatTokenLexer &Tokens) {<br> TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));<br>- for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>- Annotator.annotate(*AnnotatedLines[i]);<br>- }<br>- deriveLocalStyle(AnnotatedLines);<br>- for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>- Annotator.calculateFormattingInformation(*AnnotatedLines[i]);<br>- }<br>-<br>- Annotator.setCommentLineLevels(AnnotatedLines);<br>-<br>- std::vector<int> IndentForLevel;<br>- bool PreviousLineWasTouched = false;<br>- const AnnotatedLine *PreviousLine = NULL;<br>- bool FormatPPDirective = false;<br>- for (SmallVectorImpl<AnnotatedLine *>::iterator I = AnnotatedLines.begin(),<br>- E = AnnotatedLines.end();<br>- I != E; ++I) {<br>- const AnnotatedLine &TheLine = **I;<br>- const FormatToken *FirstTok = TheLine.First;<br>- int Offset = getIndentOffset(*TheLine.First);<br>-<br>- // Check whether this line is part of a formatted preprocessor directive.<br>- if (FirstTok->HasUnescapedNewline)<br>- FormatPPDirective = false;<br>- if (!FormatPPDirective && TheLine.InPPDirective &&<br>- (touchesLine(TheLine) || touchesPPDirective(I + 1, E)))<br>- FormatPPDirective = true;<br>-<br>- // Determine indent and try to merge multiple unwrapped lines.<br>- while (IndentForLevel.size() <= TheLine.Level)<br>- IndentForLevel.push_back(-1);<br>- IndentForLevel.resize(TheLine.Level + 1);<br>- unsigned Indent = getIndent(IndentForLevel, TheLine.Level);<br>- if (static_cast<int>(Indent) + Offset >= 0)<br>- Indent += Offset;<br>- tryFitMultipleLinesInOne(Indent, I, E);<br>-<br>- bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0;<br>- if (TheLine.First->is(tok::eof)) {<br>- if (PreviousLineWasTouched) {<br>- unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);<br>- Whitespaces.replaceWhitespace(*TheLine.First, Newlines,<br>- /*IndentLevel=*/0, /*Spaces=*/0,<br>- /*TargetColumn=*/0);<br>- }<br>- } else if (TheLine.Type != LT_Invalid &&<br>- (WasMoved || FormatPPDirective || touchesLine(TheLine))) {<br>- unsigned LevelIndent = getIndent(IndentForLevel, TheLine.Level);<br>- if (FirstTok->WhitespaceRange.isValid()) {<br>- formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level, Indent,<br>- TheLine.InPPDirective);<br>- } else {<br>- Indent = LevelIndent = FirstTok->OriginalColumn;<br>- }<br>- ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,<br>- BinPackInconclusiveFunctions);<br>-<br>- // If everything fits on a single line, just put it there.<br>- unsigned ColumnLimit = Style.ColumnLimit;<br>- AnnotatedLine *NextLine = *(I + 1);<br>- if ((I + 1) != E && NextLine->InPPDirective &&<br>- !NextLine->First->HasUnescapedNewline)<br>- ColumnLimit = getColumnLimit(TheLine.InPPDirective);<br>-<br>- if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {<br>- LineState State =<br>- Indenter.getInitialState(Indent, &TheLine, /*DryRun=*/false);<br>- while (State.NextToken != NULL)<br>- Indenter.addTokenToState(State, false, false);<br>- } else if (Style.ColumnLimit == 0) {<br>- NoColumnLimitFormatter Formatter(&Indenter);<br>- Formatter.format(Indent, &TheLine);<br>- } else {<br>- UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style,<br>- TheLine);<br>- Formatter.format(Indent);<br>- }<br>-<br>- IndentForLevel[TheLine.Level] = LevelIndent;<br>- PreviousLineWasTouched = true;<br>- } else {<br>- // Format the first token if necessary, and notify the WhitespaceManager<br>- // about the unchanged whitespace.<br>- for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {<br>- if (Tok == TheLine.First &&<br>- (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {<br>- unsigned LevelIndent = Tok->OriginalColumn;<br>- // Remove trailing whitespace of the previous line if it was<br>- // touched.<br>- if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) {<br>- formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,<br>- TheLine.InPPDirective);<br>- } else {<br>- Whitespaces.addUntouchableToken(*Tok, TheLine.InPPDirective);<br>- }<br>-<br>- if (static_cast<int>(LevelIndent) - Offset >= 0)<br>- LevelIndent -= Offset;<br>- if (Tok->isNot(tok::comment))<br>- IndentForLevel[TheLine.Level] = LevelIndent;<br>- } else {<br>- Whitespaces.addUntouchableToken(*Tok, TheLine.InPPDirective);<br>- }<br>- }<br>- // If we did not reformat this unwrapped line, the column at the end of<br>- // the last token is unchanged - thus, we can calculate the end of the<br>- // last token.<br>- PreviousLineWasTouched = false;<br>- }<br>- for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {<br>- Tok->Finalized = true;<br>- }<br>- PreviousLine = *I;<br>+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>+ Annotator.annotate(*AnnotatedLines[i]);<br>+ }<br>+ deriveLocalStyle(AnnotatedLines);<br>+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {<br>+ Annotator.calculateFormattingInformation(*AnnotatedLines[i]);<br> }<br>+<br>+ Annotator.setCommentLineLevels(AnnotatedLines);<br>+ ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,<br>+ BinPackInconclusiveFunctions);<br>+ UnwrappedLineFormatter Formatter(SourceMgr, Ranges, &Indenter, &Whitespaces,<br>+ Style);<br>+ Formatter.format(AnnotatedLines, /*DryRun=*/false);<br> return Whitespaces.generateReplacements();<br> }<br><br>@@ -1051,228 +1313,6 @@ private:<br> HasBinPackedFunction || !HasOnePerLineFunction;<br> }<br><br>- /// \brief Get the indent of \p Level from \p IndentForLevel.<br>- ///<br>- /// \p IndentForLevel must contain the indent for the level \c l<br>- /// at \p IndentForLevel[l], or a value < 0 if the indent for<br>- /// that level is unknown.<br>- unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) {<br>- if (IndentForLevel[Level] != -1)<br>- return IndentForLevel[Level];<br>- if (Level == 0)<br>- return 0;<br>- return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;<br>- }<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>- /// characters to the left from their level.<br>- int getIndentOffset(const FormatToken &RootToken) {<br>- if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())<br>- return Style.AccessModifierOffset;<br>- return 0;<br>- }<br>-<br>- /// \brief Tries to merge lines into one.<br>- ///<br>- /// This will change \c Line and \c AnnotatedLine to contain the merged line,<br>- /// if possible; note that \c I will be incremented when lines are merged.<br>- void tryFitMultipleLinesInOne(unsigned Indent,<br>- SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>- SmallVectorImpl<AnnotatedLine *>::iterator E) {<br>- // We can never merge stuff if there are trailing line comments.<br>- AnnotatedLine *TheLine = *I;<br>- if (TheLine->Last->Type == TT_LineComment)<br>- return;<br>-<br>- if (Indent > Style.ColumnLimit)<br>- return;<br>-<br>- unsigned Limit = Style.ColumnLimit - Indent;<br>- // If we already exceed the column limit, we set 'Limit' to 0. The different<br>- // tryMerge..() functions can then decide whether to still do merging.<br>- Limit = TheLine->Last->TotalLength > Limit<br>- ? 0<br>- : Limit - TheLine->Last->TotalLength;<br>-<br>- if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)<br>- return;<br>-<br>- if (TheLine->Last->is(tok::l_brace)) {<br>- tryMergeSimpleBlock(I, E, Limit);<br>- } else if (Style.AllowShortIfStatementsOnASingleLine &&<br>- TheLine->First->is(tok::kw_if)) {<br>- tryMergeSimpleControlStatement(I, E, Limit);<br>- } else if (Style.AllowShortLoopsOnASingleLine &&<br>- TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {<br>- tryMergeSimpleControlStatement(I, E, Limit);<br>- } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||<br>- TheLine->First->IsFirst)) {<br>- tryMergeSimplePPDirective(I, E, Limit);<br>- }<br>- }<br>-<br>- void tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>- SmallVectorImpl<AnnotatedLine *>::iterator E,<br>- unsigned Limit) {<br>- if (Limit == 0)<br>- return;<br>- AnnotatedLine &Line = **I;<br>- if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)<br>- return;<br>- if (I + 2 != E && (*(I + 2))->InPPDirective &&<br>- !(*(I + 2))->First->HasUnescapedNewline)<br>- return;<br>- if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>- return;<br>- join(Line, **(++I));<br>- }<br>-<br>- void<br>- tryMergeSimpleControlStatement(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>- SmallVectorImpl<AnnotatedLine *>::iterator E,<br>- unsigned Limit) {<br>- if (Limit == 0)<br>- return;<br>- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&<br>- (*(I + 1))->First->is(tok::l_brace))<br>- return;<br>- if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||<br>- ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))<br>- return;<br>- AnnotatedLine &Line = **I;<br>- if (Line.Last->isNot(tok::r_paren))<br>- return;<br>- if (1 + (*(I + 1))->Last->TotalLength > Limit)<br>- return;<br>- if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,<br>- tok::kw_while) ||<br>- (*(I + 1))->First->Type == TT_LineComment)<br>- return;<br>- // Only inline simple if's (no nested if or else).<br>- if (I + 2 != E && Line.First->is(tok::kw_if) &&<br>- (*(I + 2))->First->is(tok::kw_else))<br>- return;<br>- join(Line, **(++I));<br>- }<br>-<br>- void tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::iterator &I,<br>- SmallVectorImpl<AnnotatedLine *>::iterator E,<br>- unsigned Limit) {<br>- // No merging if the brace already is on the next line.<br>- if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)<br>- return;<br>-<br>- // First, check that the current line allows merging. This is the case if<br>- // we're not in a control flow statement and the last token is an opening<br>- // brace.<br>- AnnotatedLine &Line = **I;<br>- if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,<br>- tok::kw_else, tok::kw_try, tok::kw_catch,<br>- tok::kw_for,<br>- // This gets rid of all ObjC @ keywords and methods.<br>- tok::at, tok::minus, tok::plus))<br>- return;<br>-<br>- FormatToken *Tok = (*(I + 1))->First;<br>- if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&<br>- (Tok->getNextNonComment() == NULL ||<br>- Tok->getNextNonComment()->is(tok::semi))) {<br>- // We merge empty blocks even if the line exceeds the column limit.<br>- Tok->SpacesRequiredBefore = 0;<br>- Tok->CanBreakBefore = true;<br>- join(Line, **(I + 1));<br>- I += 1;<br>- } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {<br>- // Check that we still have three lines and they fit into the limit.<br>- if (I + 2 == E || (*(I + 2))->Type == LT_Invalid ||<br>- !nextTwoLinesFitInto(I, Limit))<br>- return;<br>-<br>- // Second, check that the next line does not contain any braces - if it<br>- // does, readability declines when putting it into a single line.<br>- if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)<br>- return;<br>- do {<br>- if (Tok->isOneOf(tok::l_brace, tok::r_brace))<br>- return;<br>- Tok = Tok->Next;<br>- } while (Tok != NULL);<br>-<br>- // Last, check that the third line contains a single closing brace.<br>- Tok = (*(I + 2))->First;<br>- if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||<br>- Tok->MustBreakBefore)<br>- return;<br>-<br>- join(Line, **(I + 1));<br>- join(Line, **(I + 2));<br>- I += 2;<br>- }<br>- }<br>-<br>- bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::iterator I,<br>- unsigned Limit) {<br>- return 1 + (*(I + 1))->Last->TotalLength + 1 +<br>- (*(I + 2))->Last->TotalLength <=<br>- Limit;<br>- }<br>-<br>- void join(AnnotatedLine &A, const AnnotatedLine &B) {<br>- assert(!A.Last->Next);<br>- assert(!B.First->Previous);<br>- A.Last->Next = B.First;<br>- B.First->Previous = A.Last;<br>- unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;<br>- for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {<br>- Tok->TotalLength += LengthA;<br>- A.Last = Tok;<br>- }<br>- }<br>-<br>- bool touchesRanges(const CharSourceRange &Range) {<br>- for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {<br>- if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),<br>- Ranges[i].getBegin()) &&<br>- !SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(),<br>- Range.getBegin()))<br>- return true;<br>- }<br>- return false;<br>- }<br>-<br>- bool touchesLine(const AnnotatedLine &TheLine) {<br>- const FormatToken *First = TheLine.First;<br>- const FormatToken *Last = TheLine.Last;<br>- CharSourceRange LineRange = CharSourceRange::getCharRange(<br>- First->WhitespaceRange.getBegin().getLocWithOffset(<br>- First->LastNewlineOffset),<br>- Last->getStartOfNonWhitespace().getLocWithOffset(<br>- Last->TokenText.size() - 1));<br>- return touchesRanges(LineRange);<br>- }<br>-<br>- bool touchesPPDirective(SmallVectorImpl<AnnotatedLine *>::iterator I,<br>- SmallVectorImpl<AnnotatedLine *>::iterator E) {<br>- for (; I != E; ++I) {<br>- if ((*I)->First->HasUnescapedNewline)<br>- return false;<br>- if (touchesLine(**I))<br>- return true;<br>- }<br>- return false;<br>- }<br>-<br>- bool touchesEmptyLineBefore(const AnnotatedLine &TheLine) {<br>- const FormatToken *First = TheLine.First;<br>- CharSourceRange LineRange = CharSourceRange::getCharRange(<br>- First->WhitespaceRange.getBegin(),<br>- First->WhitespaceRange.getBegin().getLocWithOffset(<br>- First->LastNewlineOffset));<br>- return touchesRanges(LineRange);<br>- }<br>-<br> virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {<br> assert(!UnwrappedLines.empty());<br> UnwrappedLines.back().push_back(TheLine);<br>@@ -1282,45 +1322,11 @@ private:<br> UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());<br> }<br><br>- /// \brief Add a new line and the required indent before the first Token<br>- /// of the \c UnwrappedLine if there was no structural parsing error.<br>- void formatFirstToken(FormatToken &RootToken,<br>- const AnnotatedLine *PreviousLine, unsigned IndentLevel,<br>- unsigned Indent, bool InPPDirective) {<br>- unsigned Newlines =<br>- std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);<br>- // Remove empty lines before "}" where applicable.<br>- if (<a href="http://RootToken.is">RootToken.is</a>(tok::r_brace) &&<br>- (!RootToken.Next ||<br>- (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))<br>- Newlines = std::min(Newlines, 1u);<br>- if (Newlines == 0 && !RootToken.IsFirst)<br>- Newlines = 1;<br>-<br>- // Insert extra new line before access specifiers.<br>- if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&<br>- RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)<br>- ++Newlines;<br>-<br>- // Remove empty lines after access specifiers.<br>- if (PreviousLine && PreviousLine->First->isAccessSpecifier())<br>- Newlines = std::min(1u, Newlines);<br>-<br>- Whitespaces.replaceWhitespace(<br>- RootToken, Newlines, IndentLevel, Indent, Indent,<br>- InPPDirective && !RootToken.HasUnescapedNewline);<br>- }<br>-<br>- unsigned getColumnLimit(bool InPPDirective) const {<br>- // In preprocessor directives reserve two chars for trailing " \"<br>- return Style.ColumnLimit - (InPPDirective ? 2 : 0);<br>- }<br>-<br> FormatStyle Style;<br> Lexer &Lex;<br> SourceManager &SourceMgr;<br> WhitespaceManager Whitespaces;<br>- std::vector<CharSourceRange> Ranges;<br>+ SmallVector<CharSourceRange, 8> Ranges;<br> SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;<br><br> encoding::Encoding Encoding;<br><br>Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=194090&r1=194089&r2=194090&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=194090&r1=194089&r2=194090&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)<br>+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Nov 5 13:10:03 2013<br>@@ -1013,22 +1013,21 @@ private:<br><br> void<br> TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) {<br>- if (Lines.empty())<br>- return;<br>-<br> const AnnotatedLine *NextNonCommentLine = NULL;<br>- for (unsigned i = Lines.size() - 1; i > 0; --i) {<br>- if (NextNonCommentLine && Lines[i]->First->is(tok::comment) &&<br>- !Lines[i]->First->Next)<br>- Lines[i]->Level = NextNonCommentLine->Level;<br>+ for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(),<br>+ E = Lines.rend();<br>+ I != E; ++I) {<br>+ if (NextNonCommentLine && (*I)->First->is(tok::comment) &&<br>+ (*I)->First->Next == NULL)<br>+ (*I)->Level = NextNonCommentLine->Level;<br> else<br>- NextNonCommentLine =<br>- Lines[i]->First->isNot(tok::r_brace) ? Lines[i] : NULL;<br>+ NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : NULL;<br>+<br>+ setCommentLineLevels((*I)->Children);<br> }<br> }<br><br> void TokenAnnotator::annotate(AnnotatedLine &Line) {<br>- setCommentLineLevels(Line.Children);<br> for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),<br> E = Line.Children.end();<br> I != E; ++I) {<br><br>Modified: cfe/trunk/unittests/Format/FormatTest.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=194090&r1=194089&r2=194090&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=194090&r1=194089&r2=194090&view=diff</a><br>==============================================================================<br>--- cfe/trunk/unittests/Format/FormatTest.cpp (original)<br>+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Nov 5 13:10:03 2013<br>@@ -2447,6 +2447,45 @@ TEST_F(FormatTest, LayoutNestedBlocks) {<br> " // comment\n"<br> " int j;\n"<br> "});"));<br>+<br>+ verifyFormat("DEBUG({\n"<br>+ " if (a)\n"<br>+ " return;\n"<br>+ "});");<br>+ verifyGoogleFormat("DEBUG({\n"<br>+ " if (a) return;\n"<br>+ "});");<br>+ FormatStyle Style = getGoogleStyle();<br>+ Style.ColumnLimit = 45;<br>+ verifyFormat("Debug(aaaaa, {\n"<br>+ " if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"<br>+ " return;\n"<br>+ " },\n"<br>+ " a);", Style);<br>+<br>+ EXPECT_EQ("Debug({\n"<br>+ " if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"<br>+ " return;\n"<br>+ " },\n"<br>+ " a);",<br>+ format("Debug({\n"<br>+ " if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"<br>+ " return;\n"<br>+ " },\n"<br>+ " a);",<br>+ 50, 1, getLLVMStyle()));<br>+}<br>+<br>+TEST_F(FormatTest, IndividualStatementsOfNestedBlocks) {<br>+ EXPECT_EQ("DEBUG({\n"<br>+ " int i;\n"<br>+ " int j;\n"<br>+ "});",<br>+ format("DEBUG( {\n"<br>+ " int i;\n"<br>+ " int j;\n"<br>+ "} ) ;",<br>+ 40, 1, getLLVMStyle()));<br> }<br><br> TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) {<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></blockquote></div><br></div></body></html>