r190038 - clang-format: Enable formatting of nested blocks.
Daniel Jasper
djasper at google.com
Thu Sep 5 02:29:45 PDT 2013
Author: djasper
Date: Thu Sep 5 04:29:45 2013
New Revision: 190038
URL: http://llvm.org/viewvc/llvm-project?rev=190038&view=rev
Log:
clang-format: Enable formatting of nested blocks.
Among other things, this enables (better) formatting lambdas and
constructs like:
MACRO({
long_statement();
long_statement_2();
},
{
long_statement();
long_statement_2();
},
{ short_statement(); }, "");
This fixes llvm.org/PR15381.
Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/ContinuationIndenter.h
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/lib/Format/TokenAnnotator.h
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.h
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Thu Sep 5 04:29:45 2013
@@ -55,20 +55,20 @@ static bool startsSegmentOfBuilderTypeCa
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
SourceManager &SourceMgr,
- const AnnotatedLine &Line,
- unsigned FirstIndent,
WhitespaceManager &Whitespaces,
encoding::Encoding Encoding,
bool BinPackInconclusiveFunctions)
- : Style(Style), SourceMgr(SourceMgr), Line(Line), FirstIndent(FirstIndent),
- Whitespaces(Whitespaces), Encoding(Encoding),
+ : Style(Style), SourceMgr(SourceMgr), Whitespaces(Whitespaces),
+ Encoding(Encoding),
BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {}
-LineState ContinuationIndenter::getInitialState() {
- // Initialize state dependent on indent.
+LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
+ const AnnotatedLine *Line) {
LineState State;
+ State.FirstIndent = FirstIndent;
State.Column = FirstIndent;
- State.NextToken = Line.First;
+ State.Line = Line;
+ State.NextToken = Line->First;
State.Stack.push_back(ParenState(FirstIndent, FirstIndent,
/*AvoidBinPacking=*/false,
/*NoLineBreak=*/false));
@@ -95,7 +95,7 @@ bool ContinuationIndenter::canBreak(cons
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
- Previous.Previous &&
+ Previous.BlockKind == BK_BracedInit && Previous.Previous &&
Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
return false;
// This prevents breaks like:
@@ -183,8 +183,8 @@ bool ContinuationIndenter::mustBreak(con
return true;
if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
- Line.MightBeFunctionDecl && State.Stack.back().BreakBeforeParameter &&
- State.ParenLevel == 0)
+ State.Line->MightBeFunctionDecl &&
+ State.Stack.back().BreakBeforeParameter && State.ParenLevel == 0)
return true;
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
@@ -234,10 +234,7 @@ unsigned ContinuationIndenter::addTokenT
Penalty += Style.PenaltyBreakFirstLessLess;
if (Current.is(tok::r_brace)) {
- if (Current.BlockKind == BK_BracedInit)
- State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
- else
- State.Column = FirstIndent;
+ State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
} else if (Current.is(tok::string_literal) &&
State.StartOfStringLiteral != 0) {
State.Column = State.StartOfStringLiteral;
@@ -261,7 +258,7 @@ unsigned ContinuationIndenter::addTokenT
Current.is(tok::kw_operator)) &&
State.ParenLevel == 0 &&
(!Style.IndentFunctionDeclarationAfterType ||
- Line.StartsDefinition))) {
+ State.Line->StartsDefinition))) {
State.Column = State.Stack.back().Indent;
} else if (Current.Type == TT_ObjCSelectorName) {
if (State.Stack.back().ColonPos > Current.CodePointCount) {
@@ -280,14 +277,15 @@ unsigned ContinuationIndenter::addTokenT
Previous.Type == TT_ObjCMethodExpr) {
State.Column = ContinuationIndent;
} else if (Current.Type == TT_CtorInitializerColon) {
- State.Column = FirstIndent + Style.ConstructorInitializerIndentWidth;
+ State.Column =
+ State.FirstIndent + Style.ConstructorInitializerIndentWidth;
} else if (Current.Type == TT_CtorInitializerComma) {
State.Column = State.Stack.back().Indent;
} else {
State.Column = State.Stack.back().Indent;
// Ensure that we fall back to indenting 4 spaces instead of just
// flushing continuations left.
- if (State.Column == FirstIndent)
+ if (State.Column == State.FirstIndent)
State.Column += 4;
}
@@ -306,7 +304,7 @@ unsigned ContinuationIndenter::addTokenT
NewLines = std::max(NewLines, std::min(Current.NewlinesBefore,
Style.MaxEmptyLinesToKeep + 1));
Whitespaces.replaceWhitespace(Current, NewLines, State.Column,
- State.Column, Line.InPPDirective);
+ State.Column, State.Line->InPPDirective);
}
if (!Current.isTrailingComment())
@@ -337,13 +335,13 @@ unsigned ContinuationIndenter::addTokenT
if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||
Previous.Type == TT_BinaryOperator) ||
(!Style.AllowAllParametersOfDeclarationOnNextLine &&
- Line.MustBeDeclaration))
+ State.Line->MustBeDeclaration))
State.Stack.back().BreakBeforeParameter = true;
}
} else {
if (Current.is(tok::equal) &&
- (Line.First->is(tok::kw_for) || State.ParenLevel == 0) &&
+ (State.Line->First->is(tok::kw_for) || State.ParenLevel == 0) &&
State.Stack.back().VariablePos == 0) {
State.Stack.back().VariablePos = State.Column;
// Move over * and & if they are bound to the variable name.
@@ -403,21 +401,18 @@ unsigned ContinuationIndenter::addTokenT
else if (Previous.Type == TT_InheritanceColon)
State.Stack.back().Indent = State.Column;
else if (Previous.opensScope()) {
- // If a function has multiple parameters (including a single parameter
- // that is a binary expression) or a trailing call, indent all
- // parameters from the opening parenthesis. This avoids confusing
- // indents like:
- // OuterFunction(InnerFunctionCall(
- // ParameterToInnerFunction),
- // SecondParameterToOuterFunction);
+ // If a function has a trailing call, indent all parameters from the
+ // opening parenthesis. This avoids confusing indents like:
+ // OuterFunction(InnerFunctionCall( // break
+ // ParameterToInnerFunction)) // break
+ // .SecondInnerFunctionCall();
bool HasTrailingCall = false;
if (Previous.MatchingParen) {
const FormatToken *Next = Previous.MatchingParen->getNextNonComment();
HasTrailingCall = Next && Next->isMemberAccess();
}
- if (startsBinaryExpression(Current) ||
- (HasTrailingCall &&
- State.Stack[State.Stack.size() - 2].CallContinuation == 0))
+ if (HasTrailingCall &&
+ State.Stack[State.Stack.size() - 2].CallContinuation == 0)
State.Stack.back().LastSpace = State.Column;
}
}
@@ -434,7 +429,7 @@ unsigned ContinuationIndenter::moveState
State.Stack.back().AvoidBinPacking = true;
if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)
State.Stack.back().FirstLessLess = State.Column;
- if (Current.is(tok::l_square) &&
+ if (Current.is(tok::l_square) && Current.Type != TT_LambdaLSquare &&
State.Stack.back().StartOfArraySubscripts == 0)
State.Stack.back().StartOfArraySubscripts = State.Column;
if (Current.is(tok::question))
@@ -485,6 +480,14 @@ unsigned ContinuationIndenter::moveState
NewParenState.Indent =
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
+ // Do not indent relative to the fake parentheses inserted for "." or "->".
+ // This is a special case to make the following to statements consistent:
+ // OuterFunction(InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ // OuterFunction(SomeObject.InnerFunctionCall( // break
+ // ParameterToInnerFunction));
+ if (*I > prec::Unknown)
+ NewParenState.LastSpace = std::max(NewParenState.LastSpace, State.Column);
// Always indent conditional expressions. Never indent expression where
// the 'operator' is ',', ';' or an assignment (i.e. *I <=
@@ -504,17 +507,22 @@ unsigned ContinuationIndenter::moveState
// prepare for the following tokens.
if (Current.opensScope()) {
unsigned NewIndent;
- unsigned LastSpace = State.Stack.back().LastSpace;
bool AvoidBinPacking;
if (Current.is(tok::l_brace)) {
- NewIndent =
- LastSpace + (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);
+ if (Current.MatchingParen && Current.BlockKind == BK_Block) {
+ for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i)
+ State.Stack.pop_back();
+ NewIndent = State.Stack.back().LastSpace;
+ } else {
+ NewIndent = State.Stack.back().LastSpace +
+ (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);
+ }
const FormatToken *NextNoComment = Current.getNextNonComment();
AvoidBinPacking = NextNoComment &&
NextNoComment->Type == TT_DesignatedInitializerPeriod;
} else {
- NewIndent =
- 4 + std::max(LastSpace, State.Stack.back().StartOfFunctionCall);
+ NewIndent = 4 + std::max(State.Stack.back().LastSpace,
+ State.Stack.back().StartOfFunctionCall);
AvoidBinPacking = !Style.BinPackParameters ||
(Style.ExperimentalAutoDetectBinPacking &&
(Current.PackingKind == PPK_OnePerLine ||
@@ -522,7 +530,8 @@ unsigned ContinuationIndenter::moveState
Current.PackingKind == PPK_Inconclusive)));
}
- State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,
+ State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace,
+ AvoidBinPacking,
State.Stack.back().NoLineBreak));
++State.ParenLevel;
}
@@ -531,7 +540,8 @@ unsigned ContinuationIndenter::moveState
// one line and put one per line if they don't.
if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr &&
Current.MatchingParen != NULL) {
- if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit())
+ if (getLengthToMatchingParen(Current) + State.Column >
+ getColumnLimit(State))
State.Stack.back().BreakBeforeParameter = true;
}
@@ -539,7 +549,7 @@ unsigned ContinuationIndenter::moveState
// stacks.
if (State.Stack.size() > 1 &&
(Current.isOneOf(tok::r_paren, tok::r_square) ||
- (Current.is(tok::r_brace) && State.NextToken != Line.First) ||
+ (Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
State.NextToken->Type == TT_TemplateCloser)) {
State.Stack.pop_back();
--State.ParenLevel;
@@ -552,10 +562,13 @@ unsigned ContinuationIndenter::moveState
}
// Remove scopes created by fake parenthesis.
- for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
- unsigned VariablePos = State.Stack.back().VariablePos;
- State.Stack.pop_back();
- State.Stack.back().VariablePos = VariablePos;
+ if (Current.isNot(tok::r_brace) ||
+ (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {
+ for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
+ unsigned VariablePos = State.Stack.back().VariablePos;
+ State.Stack.pop_back();
+ State.Stack.back().VariablePos = VariablePos;
+ }
}
if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {
@@ -568,6 +581,10 @@ unsigned ContinuationIndenter::moveState
State.Column += Current.CodePointCount;
State.NextToken = State.NextToken->Next;
unsigned Penalty = breakProtrudingToken(Current, State, DryRun);
+ if (State.Column > getColumnLimit(State)) {
+ unsigned ExcessCharacters = State.Column - getColumnLimit(State);
+ Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
+ }
// If the previous has a special role, let it consume tokens as appropriate.
// It is necessary to start at the previous token for the only implemented
@@ -593,8 +610,8 @@ ContinuationIndenter::addMultilineString
// for all other lines is constant, and we ignore it.
State.Column = Current.CodePointsInLastLine;
- if (ColumnsUsed > getColumnLimit())
- return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
+ if (ColumnsUsed > getColumnLimit(State))
+ return Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit(State));
return 0;
}
@@ -623,15 +640,15 @@ unsigned ContinuationIndenter::breakProt
if (Current.IsUnterminatedLiteral)
return 0;
- Token.reset(new BreakableStringLiteral(Current, StartColumn,
- Line.InPPDirective, Encoding));
+ Token.reset(new BreakableStringLiteral(
+ Current, StartColumn, State.Line->InPPDirective, Encoding));
} else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {
unsigned OriginalStartColumn =
SourceMgr.getSpellingColumnNumber(Current.getStartOfNonWhitespace()) -
1;
Token.reset(new BreakableBlockComment(
Style, Current, StartColumn, OriginalStartColumn, !Current.Previous,
- Line.InPPDirective, Encoding));
+ State.Line->InPPDirective, Encoding));
} else if (Current.Type == TT_LineComment &&
(Current.Previous == NULL ||
Current.Previous->Type != TT_ImplicitStringLiteral)) {
@@ -648,14 +665,15 @@ unsigned ContinuationIndenter::breakProt
}
Token.reset(new BreakableLineComment(Current, StartColumn,
- Line.InPPDirective, Encoding));
+ State.Line->InPPDirective, Encoding));
} else {
return 0;
}
- if (Current.UnbreakableTailLength >= getColumnLimit())
+ if (Current.UnbreakableTailLength >= getColumnLimit(State))
return 0;
- unsigned RemainingSpace = getColumnLimit() - Current.UnbreakableTailLength;
+ unsigned RemainingSpace =
+ getColumnLimit(State) - Current.UnbreakableTailLength;
bool BreakInserted = false;
unsigned Penalty = 0;
unsigned RemainingTokenColumns = 0;
@@ -668,7 +686,7 @@ unsigned ContinuationIndenter::breakProt
Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
while (RemainingTokenColumns > RemainingSpace) {
BreakableToken::Split Split =
- Token->getSplit(LineIndex, TailOffset, getColumnLimit());
+ Token->getSplit(LineIndex, TailOffset, getColumnLimit(State));
if (Split.first == StringRef::npos) {
// The last line's penalty is handled in addNextStateToQueue().
if (LineIndex < EndIndex - 1)
@@ -685,9 +703,9 @@ unsigned ContinuationIndenter::breakProt
Penalty += Current.SplitPenalty;
unsigned ColumnsUsed =
Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);
- if (ColumnsUsed > getColumnLimit()) {
- Penalty +=
- Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
+ if (ColumnsUsed > getColumnLimit(State)) {
+ Penalty += Style.PenaltyExcessCharacter *
+ (ColumnsUsed - getColumnLimit(State));
}
TailOffset += Split.first + Split.second;
RemainingTokenColumns = NewRemainingTokenColumns;
@@ -714,9 +732,9 @@ unsigned ContinuationIndenter::breakProt
return Penalty;
}
-unsigned ContinuationIndenter::getColumnLimit() const {
+unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
// In preprocessor directives reserve two chars for trailing " \"
- return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0);
+ return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}
bool ContinuationIndenter::NextIsMultilineString(const LineState &State) {
Modified: cfe/trunk/lib/Format/ContinuationIndenter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.h (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.h Thu Sep 5 04:29:45 2013
@@ -35,14 +35,13 @@ public:
/// \brief Constructs a \c ContinuationIndenter to format \p Line starting in
/// column \p FirstIndent.
ContinuationIndenter(const FormatStyle &Style, SourceManager &SourceMgr,
- const AnnotatedLine &Line, unsigned FirstIndent,
WhitespaceManager &Whitespaces,
encoding::Encoding Encoding,
bool BinPackInconclusiveFunctions);
- /// \brief Get the initial state, i.e. the state after placing the line's
- /// first token.
- LineState getInitialState();
+ /// \brief Get the initial state, i.e. the state after placing \p Line's
+ /// first token at \p FirstIndent.
+ LineState getInitialState(unsigned FirstIndent, const AnnotatedLine *Line);
// FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a
// better home.
@@ -65,7 +64,7 @@ public:
/// \brief Get the column limit for this line. This is the style's column
/// limit, potentially reduced for preprocessor definitions.
- unsigned getColumnLimit() const;
+ unsigned getColumnLimit(const LineState &State) const;
private:
/// \brief Mark the next token as consumed in \p State and modify its stacks
@@ -101,8 +100,6 @@ private:
FormatStyle Style;
SourceManager &SourceMgr;
- const AnnotatedLine &Line;
- const unsigned FirstIndent;
WhitespaceManager &Whitespaces;
encoding::Encoding Encoding;
bool BinPackInconclusiveFunctions;
@@ -271,6 +268,14 @@ struct LineState {
/// FIXME: Come up with a better algorithm instead.
bool IgnoreStackForComparison;
+ /// \brief The indent of the first token.
+ unsigned FirstIndent;
+
+ /// \brief The line that is being formatted.
+ ///
+ /// Does not need to be considered for memoization because it doesn't change.
+ const AnnotatedLine *Line;
+
/// \brief Comparison operator to be able to used \c LineState in \c map.
bool operator<(const LineState &Other) const {
if (NextToken != Other.NextToken)
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Thu Sep 5 04:29:45 2013
@@ -324,8 +324,8 @@ public:
/// \brief Formats the line starting at \p State, simply keeping all of the
/// input's line breaking decisions.
- void format() {
- LineState State = Indenter->getInitialState();
+ void format(unsigned FirstIndent, const AnnotatedLine *Line) {
+ LineState State = Indenter->getInitialState(FirstIndent, Line);
while (State.NextToken != NULL) {
bool Newline =
Indenter->mustBreak(State) ||
@@ -341,12 +341,16 @@ private:
class UnwrappedLineFormatter {
public:
UnwrappedLineFormatter(ContinuationIndenter *Indenter,
+ WhitespaceManager *Whitespaces,
const FormatStyle &Style, const AnnotatedLine &Line)
- : Indenter(Indenter), Style(Style), Line(Line), Count(0) {}
+ : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), Line(Line),
+ Count(0) {}
- /// \brief Formats an \c UnwrappedLine.
- void format() {
- LineState State = Indenter->getInitialState();
+ /// \brief Formats an \c UnwrappedLine and returns the penalty.
+ ///
+ /// If \p DryRun is \c false, directly applies the changes.
+ unsigned format(unsigned FirstIndent, bool DryRun = false) {
+ LineState State = Indenter->getInitialState(FirstIndent, &Line);
// If the ObjC method declaration does not fit on a line, we should format
// it with one arg per line.
@@ -354,7 +358,7 @@ public:
State.Stack.back().BreakBeforeParameter = true;
// Find best solution in solution space.
- analyzeSolutionSpace(State);
+ return analyzeSolutionSpace(State, DryRun);
}
private:
@@ -388,8 +392,10 @@ private:
/// 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.
- void analyzeSolutionSpace(LineState &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) {
std::set<LineState> Seen;
// Insert start element into queue.
@@ -398,9 +404,11 @@ private:
Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
++Count;
+ unsigned Penalty = 0;
+
// While not empty, take first element and follow edges.
while (!Queue.empty()) {
- unsigned Penalty = Queue.top().first.first;
+ Penalty = Queue.top().first.first;
StateNode *Node = Queue.top().second;
if (Node->State.NextToken == NULL) {
DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
@@ -424,12 +432,16 @@ private:
if (Queue.empty())
// We were unable to find a solution, do nothing.
// FIXME: Add diagnostic?
- return;
+ return 0;
// Reconstruct the solution.
- reconstructPath(InitialState, Queue.top().second);
+ if (!DryRun)
+ reconstructPath(InitialState, Queue.top().second);
+
DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
DEBUG(llvm::dbgs() << "---\n");
+
+ return Penalty;
}
void reconstructPath(LineState &State, StateNode *Current) {
@@ -441,8 +453,10 @@ private:
}
for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
I != E; ++I) {
- unsigned Penalty = Indenter->addTokenToState(State, (*I)->NewLine, false);
- (void)Penalty;
+ unsigned Penalty = 0;
+ formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
+ Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);
+
DEBUG({
if ((*I)->NewLine) {
llvm::dbgs() << "Penalty for placing "
@@ -466,18 +480,80 @@ private:
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);
- if (Node->State.Column > Indenter->getColumnLimit()) {
- unsigned ExcessCharacters =
- Node->State.Column - Indenter->getColumnLimit();
- Penalty += Style.PenaltyExcessCharacter * ExcessCharacters;
- }
Queue.push(QueueItem(OrderedPenalty(Penalty, Count), Node));
++Count;
}
+ /// \brief Format all children of \p Tok assuming the parent is indented to
+ /// \p ParentIndent.
+ ///
+ /// 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->Previous;
+ if (LBrace.isNot(tok::l_brace) || LBrace.BlockKind != BK_Block ||
+ LBrace.Children.size() == 0)
+ return true; // The previous token does not open a block. Nothing to do.
+
+ if (NewLine) {
+ unsigned ParentIndent = State.Stack.back().Indent;
+ for (SmallVector<AnnotatedLine *, 1>::const_iterator
+ I = LBrace.Children.begin(),
+ E = LBrace.Children.end();
+ I != E; ++I) {
+ unsigned Indent =
+ ParentIndent + ((*I)->Level - Line.Level) * Style.IndentWidth;
+ if (!DryRun)
+ Whitespaces->replaceWhitespace(
+ *(*I)->First, /*Newlines=*/1, /*Spaces=*/Indent,
+ /*StartOfTokenColumn=*/Indent, Line.InPPDirective);
+ UnwrappedLineFormatter Formatter(Indenter, Whitespaces, Style, **I);
+ Penalty += Formatter.format(Indent, DryRun);
+ }
+ return true;
+ }
+
+ if (LBrace.Children.size() > 1)
+ return false; // Cannot merge multiple statements into a single line.
+
+ // We can't put the closing "}" on a line with a trailing comment.
+ if (LBrace.Children[0]->Last->isTrailingComment())
+ return false;
+
+ if (!DryRun) {
+ Whitespaces->replaceWhitespace(*LBrace.Children[0]->First,
+ /*Newlines=*/0, /*Spaces=*/1,
+ /*StartOfTokenColumn=*/State.Column,
+ State.Line->InPPDirective);
+ }
+
+ State.Column += 1 + LBrace.Children[0]->Last->TotalLength;
+ return true;
+ }
+
ContinuationIndenter *Indenter;
+ WhitespaceManager *Whitespaces;
FormatStyle Style;
const AnnotatedLine &Line;
@@ -654,7 +730,12 @@ public:
<< "\n");
}
- virtual ~Formatter() {}
+ virtual ~Formatter() {
+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
+ delete AnnotatedLines[i];
+ }
+ AnnotatedLines.clear();
+ }
tooling::Replacements format() {
FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);
@@ -663,23 +744,23 @@ public:
bool StructuralError = Parser.parse();
TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- Annotator.annotate(AnnotatedLines[i]);
+ Annotator.annotate(*AnnotatedLines[i]);
}
deriveLocalStyle();
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- Annotator.calculateFormattingInformation(AnnotatedLines[i]);
+ Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
}
// Adapt level to the next line if this is a comment.
// FIXME: Can/should this be done in the UnwrappedLineParser?
const AnnotatedLine *NextNonCommentLine = NULL;
for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) {
- if (NextNonCommentLine && AnnotatedLines[i].First->is(tok::comment) &&
- !AnnotatedLines[i].First->Next)
- AnnotatedLines[i].Level = NextNonCommentLine->Level;
+ if (NextNonCommentLine && AnnotatedLines[i]->First->is(tok::comment) &&
+ !AnnotatedLines[i]->First->Next)
+ AnnotatedLines[i]->Level = NextNonCommentLine->Level;
else
- NextNonCommentLine = AnnotatedLines[i].First->isNot(tok::r_brace)
- ? &AnnotatedLines[i]
+ NextNonCommentLine = AnnotatedLines[i]->First->isNot(tok::r_brace)
+ ? AnnotatedLines[i]
: NULL;
}
@@ -687,10 +768,10 @@ public:
bool PreviousLineWasTouched = false;
const FormatToken *PreviousLineLastToken = 0;
bool FormatPPDirective = false;
- for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(),
- E = AnnotatedLines.end();
+ for (std::vector<AnnotatedLine *>::iterator I = AnnotatedLines.begin(),
+ E = AnnotatedLines.end();
I != E; ++I) {
- const AnnotatedLine &TheLine = *I;
+ const AnnotatedLine &TheLine = **I;
const FormatToken *FirstTok = TheLine.First;
int Offset = getIndentOffset(*TheLine.First);
@@ -729,26 +810,27 @@ public:
} else {
Indent = LevelIndent = FirstTok->OriginalColumn;
}
- ContinuationIndenter Indenter(Style, SourceMgr, TheLine, Indent,
- Whitespaces, Encoding,
+ ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,
BinPackInconclusiveFunctions);
// If everything fits on a single line, just put it there.
unsigned ColumnLimit = Style.ColumnLimit;
- if ((I + 1) != E && (I + 1)->InPPDirective &&
- !(I + 1)->First->HasUnescapedNewline)
- ColumnLimit = Indenter.getColumnLimit();
+ AnnotatedLine *NextLine = *(I + 1);
+ if ((I + 1) != E && NextLine->InPPDirective &&
+ !NextLine->First->HasUnescapedNewline)
+ ColumnLimit = getColumnLimit(TheLine.InPPDirective);
- if (I->Last->TotalLength + Indent <= ColumnLimit) {
- LineState State = Indenter.getInitialState();
+ if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {
+ LineState State = Indenter.getInitialState(Indent, &TheLine);
while (State.NextToken != NULL)
Indenter.addTokenToState(State, false, false);
} else if (Style.ColumnLimit == 0) {
NoColumnLimitFormatter Formatter(&Indenter);
- Formatter.format();
+ Formatter.format(Indent, &TheLine);
} else {
- UnwrappedLineFormatter Formatter(&Indenter, Style, TheLine);
- Formatter.format();
+ UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style,
+ TheLine);
+ Formatter.format(Indent);
}
IndentForLevel[TheLine.Level] = LevelIndent;
@@ -783,7 +865,7 @@ public:
// last token.
PreviousLineWasTouched = false;
}
- PreviousLineLastToken = I->Last;
+ PreviousLineLastToken = TheLine.Last;
}
return Whitespaces.generateReplacements();
}
@@ -796,9 +878,9 @@ private:
bool HasBinPackedFunction = false;
bool HasOnePerLineFunction = false;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- if (!AnnotatedLines[i].First->Next)
+ if (!AnnotatedLines[i]->First->Next)
continue;
- FormatToken *Tok = AnnotatedLines[i].First->Next;
+ FormatToken *Tok = AnnotatedLines[i]->First->Next;
while (Tok->Next) {
if (Tok->Type == TT_PointerOrReference) {
bool SpacesBefore =
@@ -866,10 +948,11 @@ private:
/// This will change \c Line and \c AnnotatedLine to contain the merged line,
/// if possible; note that \c I will be incremented when lines are merged.
void tryFitMultipleLinesInOne(unsigned Indent,
- std::vector<AnnotatedLine>::iterator &I,
- std::vector<AnnotatedLine>::iterator E) {
+ std::vector<AnnotatedLine *>::iterator &I,
+ std::vector<AnnotatedLine *>::iterator E) {
// We can never merge stuff if there are trailing line comments.
- if (I->Last->Type == TT_LineComment)
+ AnnotatedLine *TheLine = *I;
+ if (TheLine->Last->Type == TT_LineComment)
return;
if (Indent > Style.ColumnLimit)
@@ -878,70 +961,72 @@ private:
unsigned Limit = Style.ColumnLimit - Indent;
// If we already exceed the column limit, we set 'Limit' to 0. The different
// tryMerge..() functions can then decide whether to still do merging.
- Limit = I->Last->TotalLength > Limit ? 0 : Limit - I->Last->TotalLength;
+ Limit = TheLine->Last->TotalLength > Limit
+ ? 0
+ : Limit - TheLine->Last->TotalLength;
- if (I + 1 == E || (I + 1)->Type == LT_Invalid)
+ if (I + 1 == E || (*(I + 1))->Type == LT_Invalid)
return;
- if (I->Last->is(tok::l_brace)) {
+ if (TheLine->Last->is(tok::l_brace)) {
tryMergeSimpleBlock(I, E, Limit);
} else if (Style.AllowShortIfStatementsOnASingleLine &&
- I->First->is(tok::kw_if)) {
+ TheLine->First->is(tok::kw_if)) {
tryMergeSimpleControlStatement(I, E, Limit);
} else if (Style.AllowShortLoopsOnASingleLine &&
- I->First->isOneOf(tok::kw_for, tok::kw_while)) {
+ TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
tryMergeSimpleControlStatement(I, E, Limit);
- } else if (I->InPPDirective &&
- (I->First->HasUnescapedNewline || I->First->IsFirst)) {
+ } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||
+ TheLine->First->IsFirst)) {
tryMergeSimplePPDirective(I, E, Limit);
}
}
- void tryMergeSimplePPDirective(std::vector<AnnotatedLine>::iterator &I,
- std::vector<AnnotatedLine>::iterator E,
+ void tryMergeSimplePPDirective(std::vector<AnnotatedLine *>::iterator &I,
+ std::vector<AnnotatedLine *>::iterator E,
unsigned Limit) {
if (Limit == 0)
return;
- AnnotatedLine &Line = *I;
- if (!(I + 1)->InPPDirective || (I + 1)->First->HasUnescapedNewline)
+ AnnotatedLine &Line = **I;
+ if (!(*(I + 1))->InPPDirective || (*(I + 1))->First->HasUnescapedNewline)
return;
- if (I + 2 != E && (I + 2)->InPPDirective &&
- !(I + 2)->First->HasUnescapedNewline)
+ if (I + 2 != E && (*(I + 2))->InPPDirective &&
+ !(*(I + 2))->First->HasUnescapedNewline)
return;
- if (1 + (I + 1)->Last->TotalLength > Limit)
+ if (1 + (*(I + 1))->Last->TotalLength > Limit)
return;
- join(Line, *(++I));
+ join(Line, **(++I));
}
- void tryMergeSimpleControlStatement(std::vector<AnnotatedLine>::iterator &I,
- std::vector<AnnotatedLine>::iterator E,
+ void tryMergeSimpleControlStatement(std::vector<AnnotatedLine *>::iterator &I,
+ std::vector<AnnotatedLine *>::iterator E,
unsigned Limit) {
if (Limit == 0)
return;
if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&
- (I + 1)->First->is(tok::l_brace))
+ (*(I + 1))->First->is(tok::l_brace))
return;
- if ((I + 1)->InPPDirective != I->InPPDirective ||
- ((I + 1)->InPPDirective && (I + 1)->First->HasUnescapedNewline))
+ if ((*(I + 1))->InPPDirective != (*I)->InPPDirective ||
+ ((*(I + 1))->InPPDirective && (*(I + 1))->First->HasUnescapedNewline))
return;
- AnnotatedLine &Line = *I;
+ AnnotatedLine &Line = **I;
if (Line.Last->isNot(tok::r_paren))
return;
- if (1 + (I + 1)->Last->TotalLength > Limit)
+ if (1 + (*(I + 1))->Last->TotalLength > Limit)
return;
- if ((I + 1)->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
- tok::kw_while) ||
- (I + 1)->First->Type == TT_LineComment)
+ if ((*(I + 1))->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
+ tok::kw_while) ||
+ (*(I + 1))->First->Type == TT_LineComment)
return;
// Only inline simple if's (no nested if or else).
if (I + 2 != E && Line.First->is(tok::kw_if) &&
- (I + 2)->First->is(tok::kw_else))
+ (*(I + 2))->First->is(tok::kw_else))
return;
- join(Line, *(++I));
+ join(Line, **(++I));
}
- void tryMergeSimpleBlock(std::vector<AnnotatedLine>::iterator &I,
- std::vector<AnnotatedLine>::iterator E,
+ void tryMergeSimpleBlock(std::vector<AnnotatedLine *>::iterator &I,
+ std::vector<AnnotatedLine *>::iterator E,
unsigned Limit) {
// No merging if the brace already is on the next line.
if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
@@ -950,7 +1035,7 @@ private:
// First, check that the current line allows merging. This is the case if
// we're not in a control flow statement and the last token is an opening
// brace.
- AnnotatedLine &Line = *I;
+ AnnotatedLine &Line = **I;
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
tok::kw_else, tok::kw_try, tok::kw_catch,
tok::kw_for,
@@ -958,24 +1043,24 @@ private:
tok::at, tok::minus, tok::plus))
return;
- FormatToken *Tok = (I + 1)->First;
+ FormatToken *Tok = (*(I + 1))->First;
if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
(Tok->getNextNonComment() == NULL ||
Tok->getNextNonComment()->is(tok::semi))) {
// We merge empty blocks even if the line exceeds the column limit.
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
- join(Line, *(I + 1));
+ join(Line, **(I + 1));
I += 1;
} else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
// Check that we still have three lines and they fit into the limit.
- if (I + 2 == E || (I + 2)->Type == LT_Invalid ||
+ if (I + 2 == E || (*(I + 2))->Type == LT_Invalid ||
!nextTwoLinesFitInto(I, Limit))
return;
// Second, check that the next line does not contain any braces - if it
// does, readability declines when putting it into a single line.
- if ((I + 1)->Last->Type == TT_LineComment || Tok->MustBreakBefore)
+ if ((*(I + 1))->Last->Type == TT_LineComment || Tok->MustBreakBefore)
return;
do {
if (Tok->isOneOf(tok::l_brace, tok::r_brace))
@@ -984,20 +1069,21 @@ private:
} while (Tok != NULL);
// Last, check that the third line contains a single closing brace.
- Tok = (I + 2)->First;
+ Tok = (*(I + 2))->First;
if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
return;
- join(Line, *(I + 1));
- join(Line, *(I + 2));
+ join(Line, **(I + 1));
+ join(Line, **(I + 2));
I += 2;
}
}
- bool nextTwoLinesFitInto(std::vector<AnnotatedLine>::iterator I,
+ bool nextTwoLinesFitInto(std::vector<AnnotatedLine *>::iterator I,
unsigned Limit) {
- return 1 + (I + 1)->Last->TotalLength + 1 + (I + 2)->Last->TotalLength <=
+ return 1 + (*(I + 1))->Last->TotalLength + 1 +
+ (*(I + 2))->Last->TotalLength <=
Limit;
}
@@ -1034,12 +1120,12 @@ private:
return touchesRanges(LineRange);
}
- bool touchesPPDirective(std::vector<AnnotatedLine>::iterator I,
- std::vector<AnnotatedLine>::iterator E) {
+ bool touchesPPDirective(std::vector<AnnotatedLine *>::iterator I,
+ std::vector<AnnotatedLine *>::iterator E) {
for (; I != E; ++I) {
- if (I->First->HasUnescapedNewline)
+ if ((*I)->First->HasUnescapedNewline)
return false;
- if (touchesLine(*I))
+ if (touchesLine(**I))
return true;
}
return false;
@@ -1055,7 +1141,7 @@ private:
}
virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
- AnnotatedLines.push_back(AnnotatedLine(TheLine));
+ AnnotatedLines.push_back(new AnnotatedLine(TheLine));
}
/// \brief Add a new line and the required indent before the first Token
@@ -1084,12 +1170,17 @@ private:
InPPDirective && !RootToken.HasUnescapedNewline);
}
+ unsigned getColumnLimit(bool InPPDirective) const {
+ // In preprocessor directives reserve two chars for trailing " \"
+ return Style.ColumnLimit - (InPPDirective ? 2 : 0);
+ }
+
FormatStyle Style;
Lexer &Lex;
SourceManager &SourceMgr;
WhitespaceManager Whitespaces;
std::vector<CharSourceRange> Ranges;
- std::vector<AnnotatedLine> AnnotatedLines;
+ std::vector<AnnotatedLine *> AnnotatedLines;
encoding::Encoding Encoding;
bool BinPackInconclusiveFunctions;
Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Thu Sep 5 04:29:45 2013
@@ -36,6 +36,7 @@ enum TokenType {
TT_InlineASMColon,
TT_InheritanceColon,
TT_FunctionTypeLParen,
+ TT_LambdaLSquare,
TT_LineComment,
TT_ObjCArrayLiteral,
TT_ObjCBlockLParen,
@@ -75,6 +76,7 @@ enum ParameterPackingKind {
};
class TokenRole;
+class AnnotatedLine;
/// \brief A wrapper around a \c Token storing information about the
/// whitespace characters preceeding it.
@@ -335,6 +337,8 @@ struct FormatToken {
FormatToken *Previous;
FormatToken *Next;
+ SmallVector<AnnotatedLine *, 1> Children;
+
private:
// Disallow copying.
FormatToken(const FormatToken &) LLVM_DELETED_FUNCTION;
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Thu Sep 5 04:29:45 2013
@@ -182,7 +182,7 @@ private:
FormatToken *Left = CurrentToken->Previous;
FormatToken *Parent = Left->getPreviousNonComment();
bool StartsObjCMethodExpr =
- Contexts.back().CanBeExpression &&
+ Contexts.back().CanBeExpression && Left->Type != TT_LambdaLSquare &&
(!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
tok::kw_return, tok::kw_throw) ||
Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
@@ -522,7 +522,7 @@ private:
// Reset token type in case we have already looked at it and then recovered
// from an error (e.g. failure to find the matching >).
- if (CurrentToken != NULL)
+ if (CurrentToken != NULL && CurrentToken->Type != TT_LambdaLSquare)
CurrentToken->Type = TT_Unknown;
}
@@ -974,6 +974,11 @@ private:
} // end anonymous namespace
void TokenAnnotator::annotate(AnnotatedLine &Line) {
+ for (std::vector<AnnotatedLine *>::iterator I = Line.Children.begin(),
+ E = Line.Children.end();
+ I != E; ++I) {
+ annotate(**I);
+ }
AnnotatingParser Parser(Style, Line, Ident_in);
Line.Type = Parser.parseLine();
if (Line.Type == LT_Invalid)
@@ -1026,7 +1031,7 @@ void TokenAnnotator::calculateFormatting
}
Current->CanBreakBefore =
Current->MustBreakBefore || canBreakBefore(Line, *Current);
- if (Current->MustBreakBefore ||
+ if (Current->MustBreakBefore || !Current->Children.empty() ||
(Current->is(tok::string_literal) && Current->isMultiline()))
Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
else
@@ -1048,9 +1053,13 @@ void TokenAnnotator::calculateFormatting
Current->Role->precomputeFormattingInfos(Current);
}
- DEBUG({
- printDebugInfo(Line);
- });
+ DEBUG({ printDebugInfo(Line); });
+
+ for (std::vector<AnnotatedLine *>::iterator I = Line.Children.begin(),
+ E = Line.Children.end();
+ I != E; ++I) {
+ calculateFormattingInformation(**I);
+ }
}
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
@@ -1212,7 +1221,7 @@ bool TokenAnnotator::spaceRequiredBetwee
if (Right.is(tok::r_square))
return Right.Type == TT_ObjCArrayLiteral;
if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr &&
- Left.isNot(tok::numeric_constant))
+ Right.Type != TT_LambdaLSquare && Left.isNot(tok::numeric_constant))
return false;
if (Left.is(tok::colon))
return Left.Type != TT_ObjCMethodExpr;
@@ -1233,7 +1242,7 @@ bool TokenAnnotator::spaceRequiredBetwee
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
- return false; // No spaces in "{}".
+ return !Left.Children.empty(); // No spaces in "{}".
if (Left.is(tok::l_brace) || Right.is(tok::r_brace))
return !Style.Cpp11BracedListStyle;
if (Right.Type == TT_UnaryOperator)
@@ -1355,11 +1364,13 @@ bool TokenAnnotator::canBreakBefore(cons
// change the "binding" behavior of a comment.
return false;
+ if (Right.is(tok::r_paren) || Right.Type == TT_TemplateCloser)
+ return false;
+
// We only break before r_brace if there was a corresponding break before
// the l_brace, which is tracked by BreakBeforeClosingBrace.
- if (Right.isOneOf(tok::r_brace, tok::r_paren) ||
- Right.Type == TT_TemplateCloser)
- return false;
+ if (Right.is(tok::r_brace))
+ return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
// Allow breaking after a trailing 'const', e.g. after a method declaration,
// unless it is follow by ';', '{' or '='.
Modified: cfe/trunk/lib/Format/TokenAnnotator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.h (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.h Thu Sep 5 04:29:45 2013
@@ -38,31 +38,53 @@ enum LineType {
class AnnotatedLine {
public:
AnnotatedLine(const UnwrappedLine &Line)
- : First(Line.Tokens.front()), Level(Line.Level),
+ : First(Line.Tokens.front().Tok), Level(Line.Level),
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
StartsDefinition(false) {
assert(!Line.Tokens.empty());
FormatToken *Current = First;
- for (std::list<FormatToken *>::const_iterator I = ++Line.Tokens.begin(),
- E = Line.Tokens.end();
+ for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
+ E = Line.Tokens.end();
I != E; ++I) {
- Current->Next = *I;
- (*I)->Previous = Current;
+ const UnwrappedLineNode &Node = *I;
+ Current->Next = I->Tok;
+ I->Tok->Previous = Current;
Current = Current->Next;
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator
+ I = Node.Children.begin(),
+ E = Node.Children.end();
+ I != E; ++I) {
+ Children.push_back(new AnnotatedLine(*I));
+ Current->Children.push_back(Children.back());
+ }
}
Last = Current;
}
+ ~AnnotatedLine() {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i) {
+ delete Children[i];
+ }
+ Children.clear();
+ }
+
FormatToken *First;
FormatToken *Last;
+ std::vector<AnnotatedLine *> Children;
+
LineType Type;
unsigned Level;
bool InPPDirective;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
bool StartsDefinition;
+
+private:
+ // Disallow copying.
+ AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
+ void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
};
/// \brief Determines extra information about the tokens comprising an
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Thu Sep 5 04:29:45 2013
@@ -122,9 +122,12 @@ class ScopedLineState {
public:
ScopedLineState(UnwrappedLineParser &Parser,
bool SwitchToPreprocessorLines = false)
- : Parser(Parser), SwitchToPreprocessorLines(SwitchToPreprocessorLines) {
+ : Parser(Parser) {
+ OriginalLines = Parser.CurrentLines;
if (SwitchToPreprocessorLines)
Parser.CurrentLines = &Parser.PreprocessorDirectives;
+ else if (!Parser.Line->Tokens.empty())
+ Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
PreBlockLine = Parser.Line.take();
Parser.Line.reset(new UnwrappedLine());
Parser.Line->Level = PreBlockLine->Level;
@@ -137,16 +140,16 @@ public:
}
assert(Parser.Line->Tokens.empty());
Parser.Line.reset(PreBlockLine);
- Parser.MustBreakBeforeNextToken = true;
- if (SwitchToPreprocessorLines)
- Parser.CurrentLines = &Parser.Lines;
+ if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
+ Parser.MustBreakBeforeNextToken = true;
+ Parser.CurrentLines = OriginalLines;
}
private:
UnwrappedLineParser &Parser;
- const bool SwitchToPreprocessorLines;
UnwrappedLine *PreBlockLine;
+ SmallVectorImpl<UnwrappedLine> *OriginalLines;
};
namespace {
@@ -191,7 +194,8 @@ bool UnwrappedLineParser::parse() {
Tokens = &TokenSource;
readToken();
parseFile();
- for (std::vector<UnwrappedLine>::iterator I = Lines.begin(), E = Lines.end();
+ for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),
+ E = Lines.end();
I != E; ++I) {
Callback.consumeUnwrappedLine(*I);
}
@@ -670,6 +674,8 @@ void UnwrappedLineParser::parseStructura
}
void UnwrappedLineParser::tryToParseLambda() {
+ assert(FormatTok->is(tok::l_square));
+ FormatToken &LSquare = *FormatTok;
if (!tryToParseLambdaIntroducer()) {
return;
}
@@ -681,7 +687,6 @@ void UnwrappedLineParser::tryToParseLamb
switch (FormatTok->Tok.getKind()) {
case tok::l_brace:
break;
- return;
case tok::l_paren:
parseParens();
break;
@@ -694,6 +699,7 @@ void UnwrappedLineParser::tryToParseLamb
break;
}
}
+ LSquare.Type = TT_LambdaLSquare;
parseChildBlock();
}
@@ -1183,23 +1189,39 @@ void UnwrappedLineParser::parseObjCProto
parseObjCUntilAtEnd();
}
+static void printDebugInfo(const UnwrappedLine &Line, StringRef Prefix = "") {
+ llvm::dbgs() << Prefix << "Line(" << Line.Level << ")"
+ << (Line.InPPDirective ? " MACRO" : "") << ": ";
+ for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
+ E = Line.Tokens.end();
+ I != E; ++I) {
+ llvm::dbgs() << I->Tok->Tok.getName() << " ";
+ }
+ for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
+ E = Line.Tokens.end();
+ I != E; ++I) {
+ const UnwrappedLineNode &Node = *I;
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator
+ I = Node.Children.begin(),
+ E = Node.Children.end();
+ I != E; ++I) {
+ printDebugInfo(*I, "\nChild: ");
+ }
+ }
+ llvm::dbgs() << "\n";
+}
+
void UnwrappedLineParser::addUnwrappedLine() {
if (Line->Tokens.empty())
return;
DEBUG({
- llvm::dbgs() << "Line(" << Line->Level << ")"
- << (Line->InPPDirective ? " MACRO" : "") << ": ";
- for (std::list<FormatToken *>::iterator I = Line->Tokens.begin(),
- E = Line->Tokens.end();
- I != E; ++I) {
- llvm::dbgs() << (*I)->Tok.getName() << " ";
- }
- llvm::dbgs() << "\n";
+ if (CurrentLines == &Lines)
+ printDebugInfo(*Line);
});
CurrentLines->push_back(*Line);
Line->Tokens.clear();
if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
- for (std::vector<UnwrappedLine>::iterator
+ for (SmallVectorImpl<UnwrappedLine>::iterator
I = PreprocessorDirectives.begin(),
E = PreprocessorDirectives.end();
I != E; ++I) {
@@ -1273,9 +1295,9 @@ void UnwrappedLineParser::readToken() {
}
void UnwrappedLineParser::pushToken(FormatToken *Tok) {
- Line->Tokens.push_back(Tok);
+ Line->Tokens.push_back(UnwrappedLineNode(Tok));
if (MustBreakBeforeNextToken) {
- Line->Tokens.back()->MustBreakBefore = true;
+ Line->Tokens.back().Tok->MustBreakBefore = true;
MustBreakBeforeNextToken = false;
}
}
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Thu Sep 5 04:29:45 2013
@@ -24,6 +24,8 @@
namespace clang {
namespace format {
+struct UnwrappedLineNode;
+
/// \brief An unwrapped line is a sequence of \c Token, that we would like to
/// put on a single line if there was no column limit.
///
@@ -35,7 +37,7 @@ struct UnwrappedLine {
// FIXME: Don't use std::list here.
/// \brief The \c Tokens comprising this \c UnwrappedLine.
- std::list<FormatToken *> Tokens;
+ std::list<UnwrappedLineNode> Tokens;
/// \brief The indent level of the \c UnwrappedLine.
unsigned Level;
@@ -119,18 +121,18 @@ private:
bool MustBreakBeforeNextToken;
// The parsed lines. Only added to through \c CurrentLines.
- std::vector<UnwrappedLine> Lines;
+ SmallVector<UnwrappedLine, 8> Lines;
// Preprocessor directives are parsed out-of-order from other unwrapped lines.
// Thus, we need to keep a list of preprocessor directives to be reported
// after an unwarpped line that has been started was finished.
- std::vector<UnwrappedLine> PreprocessorDirectives;
+ SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
// New unwrapped lines are added via CurrentLines.
// Usually points to \c &Lines. While parsing a preprocessor directive when
// there is an unfinished previous unwrapped line, will point to
// \c &PreprocessorDirectives.
- std::vector<UnwrappedLine> *CurrentLines;
+ SmallVectorImpl<UnwrappedLine> *CurrentLines;
// We store for each line whether it must be a declaration depending on
// whether we are in a compound statement or not.
@@ -162,6 +164,14 @@ private:
friend class ScopedLineState;
};
+struct UnwrappedLineNode {
+ UnwrappedLineNode() : Tok(NULL) {}
+ UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}
+
+ FormatToken *Tok;
+ SmallVector<UnwrappedLine, 0> Children;
+};
+
} // end namespace format
} // end namespace clang
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=190038&r1=190037&r2=190038&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Thu Sep 5 04:29:45 2013
@@ -110,7 +110,7 @@ TEST_F(FormatTest, MessUp) {
// Basic function tests.
//===----------------------------------------------------------------------===//
-TEST_F(FormatTest, DoesNotChangeCorrectlyFormatedCode) {
+TEST_F(FormatTest, DoesNotChangeCorrectlyFormattedCode) {
EXPECT_EQ(";", format(";"));
}
@@ -1496,7 +1496,9 @@ TEST_F(FormatTest, FormatsClasses) {
" public G {};");
verifyFormat("class\n"
- " ReallyReallyLongClassName {\n};",
+ " ReallyReallyLongClassName {\n"
+ " int i;\n"
+ "};",
getLLVMStyleWithColumns(32));
}
@@ -2184,23 +2186,37 @@ TEST_F(FormatTest, LayoutStatementsAroun
}
TEST_F(FormatTest, LayoutBlockInsideParens) {
+ EXPECT_EQ("functionCall({ int i; });", format(" functionCall ( {int i;} );"));
EXPECT_EQ("functionCall({\n"
" int i;\n"
+ " int j;\n"
"});",
- format(" functionCall ( {int i;} );"));
-
- // FIXME: This is bad, find a better and more generic solution.
+ format(" functionCall ( {int i;int j;} );"));
EXPECT_EQ("functionCall({\n"
- " int i;\n"
- "},\n"
+ " int i;\n"
+ " int j;\n"
+ " },\n"
" aaaa, bbbb, cccc);",
- format(" functionCall ( {int i;}, aaaa, bbbb, cccc);"));
+ format(" functionCall ( {int i;int j;}, aaaa, bbbb, cccc);"));
+ EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",
+ format(" functionCall (aaaa, bbbb, {int i;});"));
+ EXPECT_EQ("functionCall(aaaa, bbbb, {\n"
+ " int i;\n"
+ " int j;\n"
+ "});",
+ format(" functionCall (aaaa, bbbb, {int i;int j;});"));
+ EXPECT_EQ("functionCall(aaaa, bbbb, { int i; });",
+ format(" functionCall (aaaa, bbbb, {int i;});"));
verifyFormat(
"Aaa({\n"
- " int i;\n"
- "},\n"
+ " int i; // break\n"
+ " },\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
" ccccccccccccccccc));");
+ verifyFormat("DEBUG({\n"
+ " if (a)\n"
+ " f();\n"
+ "});");
}
TEST_F(FormatTest, LayoutBlockInsideStatement) {
@@ -3681,7 +3697,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStar
verifyGoogleFormat("return sizeof(int**);");
verifyIndependentOfContext("Type **A = static_cast<Type **>(P);");
verifyGoogleFormat("Type** A = static_cast<Type**>(P);");
- verifyFormat("auto a = [](int **&, int ***) {\n};");
+ verifyFormat("auto a = [](int **&, int ***) {};");
verifyIndependentOfContext("InvalidRegions[*R] = 0;");
@@ -3865,7 +3881,7 @@ TEST_F(FormatTest, FormatsCasts) {
verifyFormat("f(foo).b;");
verifyFormat("f(foo)(b);");
verifyFormat("f(foo)[b];");
- verifyFormat("[](foo) {\n return 4;\n}(bar);");
+ verifyFormat("[](foo) { return 4; }(bar);");
verifyFormat("(*funptr)(foo)[4];");
verifyFormat("funptrs[4](foo)[4];");
verifyFormat("void f(int *);");
@@ -6260,68 +6276,40 @@ TEST_F(FormatTest, FormatsProtocolBuffer
}
TEST_F(FormatTest, FormatsLambdas) {
- verifyFormat(
- "int c = [b]() mutable {\n"
- " return [&b] {\n"
- " return b++;\n"
- " }();\n"
- "}();\n");
- verifyFormat(
- "int c = [&] {\n"
- " [=] {\n"
- " return b++;\n"
- " }();\n"
- "}();\n");
- verifyFormat(
- "int c = [&, &a, a] {\n"
- " [=, c, &d] {\n"
- " return b++;\n"
- " }();\n"
- "}();\n");
- verifyFormat(
- "int c = [&a, &a, a] {\n"
- " [=, a, b, &c] {\n"
- " return b++;\n"
- " }();\n"
- "}();\n");
- verifyFormat(
- "auto c = {[&a, &a, a] {\n"
- " [=, a, b, &c] {\n"
- " return b++;\n"
- " }();\n"
- "} }\n");
- verifyFormat(
- "auto c = {[&a, &a, a] {\n"
- " [=, a, b, &c] {\n"
- " }();\n"
- "} }\n");
- verifyFormat(
- "void f() {\n"
- " other(x.begin(), x.end(), [&](int, int) {\n"
- " return 1;\n"
- " });\n"
- "}\n");
+ verifyFormat("int c = [b]() mutable {\n"
+ " return [&b] { return b++; }();\n"
+ "}();\n");
+ verifyFormat("int c = [&] {\n"
+ " [=] { return b++; }();\n"
+ "}();\n");
+ verifyFormat("int c = [&, &a, a] {\n"
+ " [=, c, &d] { return b++; }();\n"
+ "}();\n");
+ verifyFormat("int c = [&a, &a, a] {\n"
+ " [=, a, b, &c] { return b++; }();\n"
+ "}();\n");
+ verifyFormat("auto c = { [&a, &a, a] {\n"
+ " [=, a, b, &c] { return b++; }();\n"
+ "} }\n");
+ verifyFormat("auto c = { [&a, &a, a] { [=, a, b, &c] { }(); } }\n");
+ verifyFormat("void f() {\n"
+ " other(x.begin(), x.end(), [&](int, int) { return 1; });\n"
+ "}\n");
// FIXME: The formatting is incorrect; this test currently checks that
// parsing of the unwrapped lines doesn't regress.
- verifyFormat(
- "void f() {\n"
- " other(x.begin(), //\n"
- " x.end(), //\n"
- " [&](int, int) {\n"
- " return 1;\n"
- " });\n"
- "}\n");
+ verifyFormat("void f() {\n"
+ " other(x.begin(), //\n"
+ " x.end(), //\n"
+ " [&](int, int) { return 1; });\n"
+ "}\n");
}
TEST_F(FormatTest, FormatsBlocks) {
// FIXME: Make whitespace formatting consistent. Ask a ObjC dev how
// it would ideally look.
- verifyFormat("[operation setCompletionBlock:^{\n"
- " [self onOperationDone];\n"
- "}];\n");
- verifyFormat("int i = {[operation setCompletionBlock : ^{\n"
- " [self onOperationDone];\n"
- "}] };\n");
+ verifyFormat("[operation setCompletionBlock:^{ [self onOperationDone]; }];");
+ verifyFormat("int i = {[operation setCompletionBlock : ^{ [self "
+ "onOperationDone]; }] };");
}
} // end namespace tooling
More information about the cfe-commits
mailing list