[cfe-commits] r171856 - in /cfe/trunk: lib/Format/Format.cpp lib/Format/UnwrappedLineParser.cpp lib/Format/UnwrappedLineParser.h unittests/Format/FormatTest.cpp
Daniel Jasper
djasper at google.com
Tue Jan 8 06:56:18 PST 2013
Author: djasper
Date: Tue Jan 8 08:56:18 2013
New Revision: 171856
URL: http://llvm.org/viewvc/llvm-project?rev=171856&view=rev
Log:
Change the data structure used in clang-format.
This is a first step towards supporting more complex structures such
as #ifs inside unwrapped lines. This patch mostly converts the array-based
UnwrappedLine into a linked-list-based UnwrappedLine. Future changes will
allow multiple children for each Token turning the UnwrappedLine into a
tree.
No functional changes intended.
Modified:
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.h
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=171856&r1=171855&r2=171856&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue Jan 8 08:56:18 2013
@@ -52,8 +52,25 @@
LT_ObjCMethodDecl
};
-// FIXME: Move somewhere sane.
-struct TokenAnnotation {
+class AnnotatedToken {
+public:
+ AnnotatedToken(const FormatToken &FormatTok)
+ : FormatTok(FormatTok), Type(TT_Unknown),
+ ClosesTemplateDeclaration(false), Parent(NULL) {
+ }
+
+ bool is(tok::TokenKind Kind) const {
+ return FormatTok.Tok.is(Kind);
+ }
+ bool isNot(tok::TokenKind Kind) const {
+ return FormatTok.Tok.isNot(Kind);
+ }
+ bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
+ return FormatTok.Tok.isObjCAtKeyword(Kind);
+ }
+
+ FormatToken FormatTok;
+
TokenType Type;
bool SpaceRequiredBefore;
@@ -61,10 +78,13 @@
bool MustBreakBefore;
bool ClosesTemplateDeclaration;
+
+ std::vector<AnnotatedToken> Children;
+ AnnotatedToken *Parent;
};
-static prec::Level getPrecedence(const FormatToken &Tok) {
- return getBinOpPrecedence(Tok.Tok.getKind(), true, true);
+static prec::Level getPrecedence(const AnnotatedToken &Tok) {
+ return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
}
using llvm::MutableArrayRef;
@@ -100,15 +120,14 @@
class UnwrappedLineFormatter {
public:
- UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
- const UnwrappedLine &Line,
- unsigned PreviousEndOfLineColumn,
- LineType CurrentLineType,
- const std::vector<TokenAnnotation> &Annotations,
- tooling::Replacements &Replaces, bool StructuralError)
+ UnwrappedLineFormatter(
+ const FormatStyle &Style, SourceManager &SourceMgr,
+ const UnwrappedLine &Line, unsigned PreviousEndOfLineColumn,
+ LineType CurrentLineType, const AnnotatedToken &RootToken,
+ tooling::Replacements &Replaces, bool StructuralError)
: Style(Style), SourceMgr(SourceMgr), Line(Line),
PreviousEndOfLineColumn(PreviousEndOfLineColumn),
- CurrentLineType(CurrentLineType), Annotations(Annotations),
+ CurrentLineType(CurrentLineType), RootToken(RootToken),
Replaces(Replaces), StructuralError(StructuralError) {
Parameters.PenaltyIndentLevel = 15;
Parameters.PenaltyLevelDecrease = 30;
@@ -125,7 +144,7 @@
// Initialize state dependent on indent.
IndentState State;
State.Column = Indent;
- State.ConsumedTokens = 0;
+ State.NextToken = &RootToken;
State.Indent.push_back(Indent + 4);
State.LastSpace.push_back(Indent);
State.FirstLessLess.push_back(0);
@@ -141,21 +160,22 @@
// need to analyze the entire solution space.
unsigned Columns = State.Column;
bool FitsOnALine = true;
- for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
- Columns += (Annotations[i].SpaceRequiredBefore ? 1 : 0) +
- Line.Tokens[i].TokenLength;
+ const AnnotatedToken *Tok = State.NextToken;
+ while (Tok != NULL) {
+ Columns += (Tok->SpaceRequiredBefore ? 1 : 0) +
+ Tok->FormatTok.TokenLength;
// A special case for the colon of a constructor initializer as this only
// needs to be put on a new line if the line needs to be split.
if (Columns > Style.ColumnLimit - (Line.InPPDirective ? 1 : 0) ||
- (Annotations[i].MustBreakBefore &&
- Annotations[i].Type != TT_CtorInitializerColon)) {
+ (Tok->MustBreakBefore && Tok->Type != TT_CtorInitializerColon)) {
FitsOnALine = false;
break;
}
+ Tok = Tok->Children.empty() ? NULL : &Tok->Children[0];
}
// Start iterating at 1 as we have correctly formatted of Token #0 above.
- for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
+ while (State.NextToken != NULL) {
if (FitsOnALine) {
addTokenToState(false, false, State);
} else {
@@ -175,8 +195,7 @@
/// \brief The number of used columns in the current line.
unsigned Column;
- /// \brief The number of tokens already consumed.
- unsigned ConsumedTokens;
+ const AnnotatedToken *NextToken;
/// \brief The parenthesis level of the first token on the current line.
unsigned StartOfLineLevel;
@@ -208,8 +227,8 @@
/// \brief Comparison operator to be able to used \c IndentState in \c map.
bool operator<(const IndentState &Other) const {
- if (Other.ConsumedTokens != ConsumedTokens)
- return Other.ConsumedTokens > ConsumedTokens;
+ if (Other.NextToken != NextToken)
+ return Other.NextToken > NextToken;
if (Other.Column != Column)
return Other.Column > Column;
if (Other.StartOfLineLevel != StartOfLineLevel)
@@ -250,9 +269,8 @@
/// If \p DryRun is \c false, also creates and stores the required
/// \c Replacement.
void addTokenToState(bool Newline, bool DryRun, IndentState &State) {
- unsigned Index = State.ConsumedTokens;
- const FormatToken &Current = Line.Tokens[Index];
- const FormatToken &Previous = Line.Tokens[Index - 1];
+ const FormatToken &Current = State.NextToken->FormatTok;
+ const FormatToken &Previous = State.NextToken->Parent->FormatTok;
unsigned ParenLevel = State.Indent.size() - 1;
if (Newline) {
@@ -274,10 +292,9 @@
// Indent and extra 4 spaces after '=' as it continues an expression.
// Don't do that on the top level, as we already indent 4 there.
State.Column = State.Indent[ParenLevel] + 4;
- } else if (Line.Tokens[0].Tok.is(tok::kw_for) &&
- Previous.Tok.is(tok::comma)) {
+ } else if (RootToken.is(tok::kw_for) && Previous.Tok.is(tok::comma)) {
State.Column = State.ForLoopVariablePos;
- } else if (Annotations[Index - 1].ClosesTemplateDeclaration) {
+ } else if (State.NextToken->Parent->ClosesTemplateDeclaration) {
State.Column = State.Indent[ParenLevel] - 4;
} else {
State.Column = State.Indent[ParenLevel];
@@ -285,7 +302,7 @@
State.StartOfLineLevel = ParenLevel + 1;
- if (Line.Tokens[0].Tok.is(tok::kw_for))
+ if (RootToken.is(tok::kw_for))
State.LineContainsContinuedForLoopSection =
Previous.Tok.isNot(tok::semi);
@@ -298,25 +315,25 @@
State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
if (Current.Tok.is(tok::colon) && CurrentLineType != LT_ObjCMethodDecl &&
- Annotations[Index].Type != TT_ConditionalExpr)
+ State.NextToken->Type != TT_ConditionalExpr)
State.Indent[ParenLevel] += 2;
} else {
- if (Current.Tok.is(tok::equal) && Line.Tokens[0].Tok.is(tok::kw_for))
+ if (Current.Tok.is(tok::equal) && RootToken.is(tok::kw_for))
State.ForLoopVariablePos = State.Column - Previous.TokenLength;
- unsigned Spaces = Annotations[Index].SpaceRequiredBefore ? 1 : 0;
- if (Annotations[Index].Type == TT_LineComment)
+ unsigned Spaces = State.NextToken->SpaceRequiredBefore ? 1 : 0;
+ if (State.NextToken->Type == TT_LineComment)
Spaces = Style.SpacesBeforeTrailingComments;
if (!DryRun)
replaceWhitespace(Current, 0, Spaces);
- if (Line.Tokens[0].Tok.isNot(tok::kw_for) &&
+ if (RootToken.isNot(tok::kw_for) &&
(getPrecedence(Previous) == prec::Assignment ||
Previous.Tok.is(tok::kw_return)))
State.Indent[ParenLevel] = State.Column + Spaces;
if (Previous.Tok.is(tok::l_paren) ||
- Annotations[Index - 1].Type == TT_TemplateOpener)
+ State.NextToken->Parent->Type == TT_TemplateOpener)
State.Indent[ParenLevel] = State.Column;
// Top-level spaces that are not part of assignments are exempt as that
@@ -332,20 +349,19 @@
/// \brief Mark the next token as consumed in \p State and modify its stacks
/// accordingly.
void moveStateToNextToken(IndentState &State) {
- unsigned Index = State.ConsumedTokens;
- const FormatToken &Current = Line.Tokens[Index];
+ const AnnotatedToken &Current = *State.NextToken;
unsigned ParenLevel = State.Indent.size() - 1;
- if (Current.Tok.is(tok::lessless) && State.FirstLessLess[ParenLevel] == 0)
+ if (Current.is(tok::lessless) && State.FirstLessLess[ParenLevel] == 0)
State.FirstLessLess[ParenLevel] = State.Column;
- State.Column += Current.TokenLength;
+ State.Column += Current.FormatTok.TokenLength;
// If we encounter an opening (, [, { or <, we add a level to our stacks to
// prepare for the following tokens.
- if (Current.Tok.is(tok::l_paren) || Current.Tok.is(tok::l_square) ||
- Current.Tok.is(tok::l_brace) ||
- Annotations[Index].Type == TT_TemplateOpener) {
+ if (Current.is(tok::l_paren) || Current.is(tok::l_square) ||
+ Current.is(tok::l_brace) ||
+ State.NextToken->Type == TT_TemplateOpener) {
State.Indent.push_back(4 + State.LastSpace.back());
State.LastSpace.push_back(State.LastSpace.back());
State.FirstLessLess.push_back(0);
@@ -353,33 +369,33 @@
// If we encounter a closing ), ], } or >, we can remove a level from our
// stacks.
- if (Current.Tok.is(tok::r_paren) || Current.Tok.is(tok::r_square) ||
- (Current.Tok.is(tok::r_brace) && State.ConsumedTokens > 0) ||
- Annotations[Index].Type == TT_TemplateCloser) {
+ if (Current.is(tok::r_paren) || Current.is(tok::r_square) ||
+ (Current.is(tok::r_brace) && State.NextToken != &RootToken) ||
+ State.NextToken->Type == TT_TemplateCloser) {
State.Indent.pop_back();
State.LastSpace.pop_back();
State.FirstLessLess.pop_back();
}
-
- ++State.ConsumedTokens;
+ if (State.NextToken->Children.empty())
+ State.NextToken = NULL;
+ else
+ State.NextToken = &State.NextToken->Children[0];
}
/// \brief Calculate the penalty for splitting after the token at \p Index.
- unsigned splitPenalty(unsigned Index) {
- assert(Index < Line.Tokens.size() &&
- "Tried to calculate penalty for splitting after the last token");
- const FormatToken &Left = Line.Tokens[Index];
- const FormatToken &Right = Line.Tokens[Index + 1];
+ unsigned splitPenalty(const AnnotatedToken &Tok) {
+ const AnnotatedToken &Left = Tok;
+ const AnnotatedToken &Right = Tok.Children[0];
// In for-loops, prefer breaking at ',' and ';'.
- if (Line.Tokens[0].Tok.is(tok::kw_for) &&
- (Left.Tok.isNot(tok::comma) && Left.Tok.isNot(tok::semi)))
+ if (RootToken.is(tok::kw_for) &&
+ (Left.isNot(tok::comma) && Left.isNot(tok::semi)))
return 20;
- if (Left.Tok.is(tok::semi) || Left.Tok.is(tok::comma) ||
- Annotations[Index].ClosesTemplateDeclaration)
+ if (Left.is(tok::semi) || Left.is(tok::comma) ||
+ Left.ClosesTemplateDeclaration)
return 0;
- if (Left.Tok.is(tok::l_paren))
+ if (Left.is(tok::l_paren))
return 20;
prec::Level Level = getPrecedence(Left);
@@ -392,7 +408,7 @@
if (Level != prec::Unknown)
return Level;
- if (Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period))
+ if (Right.is(tok::arrow) || Right.is(tok::period))
return 150;
return 3;
@@ -410,21 +426,21 @@
/// better solution.
unsigned calcPenalty(IndentState State, bool NewLine, unsigned StopAt) {
// We are at the end of the unwrapped line, so we don't need any more lines.
- if (State.ConsumedTokens >= Line.Tokens.size())
+ if (State.NextToken == NULL)
return 0;
- if (!NewLine && Annotations[State.ConsumedTokens].MustBreakBefore)
+ if (!NewLine && State.NextToken->MustBreakBefore)
return UINT_MAX;
- if (NewLine && !Annotations[State.ConsumedTokens].CanBreakBefore)
+ if (NewLine && !State.NextToken->CanBreakBefore)
return UINT_MAX;
- if (!NewLine && Line.Tokens[State.ConsumedTokens - 1].Tok.is(tok::semi) &&
+ if (!NewLine && State.NextToken->Parent->is(tok::semi) &&
State.LineContainsContinuedForLoopSection)
return UINT_MAX;
unsigned CurrentPenalty = 0;
if (NewLine) {
CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() +
- splitPenalty(State.ConsumedTokens - 1);
+ splitPenalty(*State.NextToken->Parent);
} else {
if (State.Indent.size() < State.StartOfLineLevel)
CurrentPenalty += Parameters.PenaltyLevelDecrease *
@@ -501,34 +517,34 @@
/// of the \c UnwrappedLine if there was no structural parsing error.
/// Returns the indent level of the \c UnwrappedLine.
unsigned formatFirstToken() {
- const FormatToken &Token = Line.Tokens[0];
- if (!Token.WhiteSpaceStart.isValid() || StructuralError)
- return SourceMgr.getSpellingColumnNumber(Token.Tok.getLocation()) - 1;
+ const FormatToken &Tok = RootToken.FormatTok;
+ if (!Tok.WhiteSpaceStart.isValid() || StructuralError)
+ return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1;
- unsigned Newlines = std::min(Token.NewlinesBefore,
+ unsigned Newlines = std::min(Tok.NewlinesBefore,
Style.MaxEmptyLinesToKeep + 1);
- if (Newlines == 0 && !Token.IsFirst)
+ if (Newlines == 0 && !Tok.IsFirst)
Newlines = 1;
unsigned Indent = Line.Level * 2;
bool IsAccessModifier = false;
- if (Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
- Token.Tok.is(tok::kw_private))
+ if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
+ RootToken.is(tok::kw_private))
IsAccessModifier = true;
- else if (Token.Tok.is(tok::at) && Line.Tokens.size() > 1 &&
- (Line.Tokens[1].Tok.isObjCAtKeyword(tok::objc_public) ||
- Line.Tokens[1].Tok.isObjCAtKeyword(tok::objc_protected) ||
- Line.Tokens[1].Tok.isObjCAtKeyword(tok::objc_package) ||
- Line.Tokens[1].Tok.isObjCAtKeyword(tok::objc_private)))
+ else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
+ (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
IsAccessModifier = true;
if (IsAccessModifier &&
static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
Indent += Style.AccessModifierOffset;
- if (!Line.InPPDirective || Token.HasUnescapedNewline)
- replaceWhitespace(Token, Newlines, Indent);
+ if (!Line.InPPDirective || Tok.HasUnescapedNewline)
+ replaceWhitespace(Tok, Newlines, Indent);
else
- replacePPWhitespace(Token, Newlines, Indent, PreviousEndOfLineColumn);
+ replacePPWhitespace(Tok, Newlines, Indent, PreviousEndOfLineColumn);
return Indent;
}
@@ -537,7 +553,7 @@
const UnwrappedLine &Line;
const unsigned PreviousEndOfLineColumn;
const LineType CurrentLineType;
- const std::vector<TokenAnnotation> &Annotations;
+ const AnnotatedToken &RootToken;
tooling::Replacements &Replaces;
bool StructuralError;
@@ -554,7 +570,8 @@
public:
TokenAnnotator(const UnwrappedLine &Line, const FormatStyle &Style,
SourceManager &SourceMgr, Lexer &Lex)
- : Line(Line), Style(Style), SourceMgr(SourceMgr), Lex(Lex) {
+ : Style(Style), SourceMgr(SourceMgr), Lex(Lex),
+ RootToken(Line.RootToken) {
}
/// \brief A parser that gathers additional information about tokens.
@@ -564,27 +581,22 @@
/// into template parameter lists.
class AnnotatingParser {
public:
- AnnotatingParser(const SmallVector<FormatToken, 16> &Tokens,
- std::vector<TokenAnnotation> &Annotations)
- : Tokens(Tokens), Annotations(Annotations), Index(0),
- KeywordVirtualFound(false) {
+ AnnotatingParser(AnnotatedToken &RootToken)
+ : CurrentToken(&RootToken), KeywordVirtualFound(false) {
}
bool parseAngle() {
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::greater)) {
- Annotations[Index].Type = TT_TemplateCloser;
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::greater)) {
+ CurrentToken->Type = TT_TemplateCloser;
next();
return true;
}
- if (Tokens[Index].Tok.is(tok::r_paren) ||
- Tokens[Index].Tok.is(tok::r_square) ||
- Tokens[Index].Tok.is(tok::r_brace))
+ if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square) ||
+ CurrentToken->is(tok::r_brace))
return false;
- if (Tokens[Index].Tok.is(tok::pipepipe) ||
- Tokens[Index].Tok.is(tok::ampamp) ||
- Tokens[Index].Tok.is(tok::question) ||
- Tokens[Index].Tok.is(tok::colon))
+ if (CurrentToken->is(tok::pipepipe) || CurrentToken->is(tok::ampamp) ||
+ CurrentToken->is(tok::question) || CurrentToken->is(tok::colon))
return false;
if (!consumeToken())
return false;
@@ -593,13 +605,12 @@
}
bool parseParens() {
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::r_paren)) {
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::r_paren)) {
next();
return true;
}
- if (Tokens[Index].Tok.is(tok::r_square) ||
- Tokens[Index].Tok.is(tok::r_brace))
+ if (CurrentToken->is(tok::r_square) || CurrentToken->is(tok::r_brace))
return false;
if (!consumeToken())
return false;
@@ -608,13 +619,12 @@
}
bool parseSquare() {
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::r_square)) {
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::r_square)) {
next();
return true;
}
- if (Tokens[Index].Tok.is(tok::r_paren) ||
- Tokens[Index].Tok.is(tok::r_brace))
+ if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_brace))
return false;
if (!consumeToken())
return false;
@@ -623,9 +633,9 @@
}
bool parseConditional() {
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::colon)) {
- Annotations[Index].Type = TT_ConditionalExpr;
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::colon)) {
+ CurrentToken->Type = TT_ConditionalExpr;
next();
return true;
}
@@ -636,12 +646,12 @@
}
bool parseTemplateDeclaration() {
- if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::less)) {
- Annotations[Index].Type = TT_TemplateOpener;
+ if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
+ CurrentToken->Type = TT_TemplateOpener;
next();
if (!parseAngle())
return false;
- Annotations[Index - 1].ClosesTemplateDeclaration = true;
+ CurrentToken->Parent->ClosesTemplateDeclaration = true;
parseLine();
return true;
}
@@ -649,14 +659,14 @@
}
bool consumeToken() {
- unsigned CurrentIndex = Index;
+ AnnotatedToken *Tok = CurrentToken;
next();
- switch (Tokens[CurrentIndex].Tok.getKind()) {
+ switch (Tok->FormatTok.Tok.getKind()) {
case tok::l_paren:
if (!parseParens())
return false;
- if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::colon)) {
- Annotations[Index].Type = TT_CtorInitializerColon;
+ if (CurrentToken != NULL && CurrentToken->is(tok::colon)) {
+ CurrentToken->Type = TT_CtorInitializerColon;
next();
}
break;
@@ -666,29 +676,30 @@
break;
case tok::less:
if (parseAngle())
- Annotations[CurrentIndex].Type = TT_TemplateOpener;
+ Tok->Type = TT_TemplateOpener;
else {
- Annotations[CurrentIndex].Type = TT_BinaryOperator;
- Index = CurrentIndex + 1;
+ Tok->Type = TT_BinaryOperator;
+ CurrentToken = Tok;
+ next();
}
break;
case tok::r_paren:
case tok::r_square:
return false;
case tok::greater:
- Annotations[CurrentIndex].Type = TT_BinaryOperator;
+ Tok->Type = TT_BinaryOperator;
break;
case tok::kw_operator:
- if (Tokens[Index].Tok.is(tok::l_paren)) {
- Annotations[Index].Type = TT_OverloadedOperator;
+ if (CurrentToken->is(tok::l_paren)) {
+ CurrentToken->Type = TT_OverloadedOperator;
next();
- if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::r_paren)) {
- Annotations[Index].Type = TT_OverloadedOperator;
+ if (CurrentToken != NULL && CurrentToken->is(tok::r_paren)) {
+ CurrentToken->Type = TT_OverloadedOperator;
next();
}
} else {
- while (Index < Tokens.size() && !Tokens[Index].Tok.is(tok::l_paren)) {
- Annotations[Index].Type = TT_OverloadedOperator;
+ while (CurrentToken != NULL && CurrentToken->isNot(tok::l_paren)) {
+ CurrentToken->Type = TT_OverloadedOperator;
next();
}
}
@@ -706,26 +717,27 @@
}
void parseIncludeDirective() {
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::slash))
- Annotations[Index].Type = TT_DirectorySeparator;
- else if (Tokens[Index].Tok.is(tok::less))
- Annotations[Index].Type = TT_TemplateOpener;
- else if (Tokens[Index].Tok.is(tok::greater))
- Annotations[Index].Type = TT_TemplateCloser;
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::slash))
+ CurrentToken->Type = TT_DirectorySeparator;
+ else if (CurrentToken->is(tok::less))
+ CurrentToken->Type = TT_TemplateOpener;
+ else if (CurrentToken->is(tok::greater))
+ CurrentToken->Type = TT_TemplateCloser;
next();
}
}
void parsePreprocessorDirective() {
next();
- if (Index >= Tokens.size())
+ if (CurrentToken == NULL)
return;
// Hashes in the middle of a line can lead to any strange token
// sequence.
- if (Tokens[Index].Tok.getIdentifierInfo() == NULL)
+ if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL)
return;
- switch (Tokens[Index].Tok.getIdentifierInfo()->getPPKeywordID()) {
+ switch (
+ CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
case tok::pp_import:
parseIncludeDirective();
@@ -736,12 +748,12 @@
}
LineType parseLine() {
- if (Tokens[Index].Tok.is(tok::hash)) {
+ if (CurrentToken->is(tok::hash)) {
parsePreprocessorDirective();
return LT_PreprocessorDirective;
}
- while (Index < Tokens.size()) {
- if (Tokens[Index].Tok.is(tok::kw_virtual))
+ while (CurrentToken != NULL) {
+ if (CurrentToken->is(tok::kw_virtual))
KeywordVirtualFound = true;
if (!consumeToken())
return LT_Invalid;
@@ -752,55 +764,61 @@
}
void next() {
- ++Index;
+ if (CurrentToken != NULL && !CurrentToken->Children.empty())
+ CurrentToken = &CurrentToken->Children[0];
+ else
+ CurrentToken = NULL;
}
private:
- const SmallVector<FormatToken, 16> &Tokens;
- std::vector<TokenAnnotation> &Annotations;
- unsigned Index;
+ AnnotatedToken *CurrentToken;
bool KeywordVirtualFound;
};
- bool annotate() {
- if (Line.Tokens.size() == 0)
- return true;
+ void createAnnotatedTokens(AnnotatedToken &Current) {
+ if (!Current.FormatTok.Children.empty()) {
+ Current.Children.push_back(AnnotatedToken(Current.FormatTok.Children[0]));
+ Current.Children.back().Parent = &Current;
+ createAnnotatedTokens(Current.Children.back());
+ }
+ }
- Annotations.clear();
- for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
- Annotations.push_back(TokenAnnotation());
+ void calculateExtraInformation(AnnotatedToken &Current) {
+ Current.SpaceRequiredBefore = spaceRequiredBefore(Current);
+
+ if (Current.Type == TT_CtorInitializerColon || Current.Parent->Type ==
+ TT_LineComment || (Current.is(tok::string_literal) &&
+ Current.Parent->is(tok::string_literal))) {
+ Current.MustBreakBefore = true;
+ } else if (Current.is(tok::at) && Current.Parent->Parent->is(tok::at)) {
+ // Don't put two objc's '@' on the same line. This could happen,
+ // as in, @optional @property ...
+ Current.MustBreakBefore = true;
+ } else {
+ Current.MustBreakBefore = false;
}
- AnnotatingParser Parser(Line.Tokens, Annotations);
+ Current.CanBreakBefore = Current.MustBreakBefore || canBreakBefore(Current);
+
+ if (!Current.Children.empty())
+ calculateExtraInformation(Current.Children[0]);
+ }
+
+ bool annotate() {
+ createAnnotatedTokens(RootToken);
+
+ AnnotatingParser Parser(RootToken);
CurrentLineType = Parser.parseLine();
if (CurrentLineType == LT_Invalid)
return false;
- determineTokenTypes();
+ determineTokenTypes(RootToken, /*IsRHS=*/false);
- if (Annotations[0].Type == TT_ObjCMethodSpecifier)
+ if (RootToken.Type == TT_ObjCMethodSpecifier)
CurrentLineType = LT_ObjCMethodDecl;
- for (int i = 1, e = Line.Tokens.size(); i != e; ++i) {
- TokenAnnotation &Annotation = Annotations[i];
-
- Annotation.SpaceRequiredBefore = spaceRequiredBefore(i);
-
- if (Annotation.Type == TT_CtorInitializerColon ||
- Annotations[i - 1].Type == TT_LineComment ||
- (Line.Tokens[i].Tok.is(tok::string_literal) &&
- Line.Tokens[i - 1].Tok.is(tok::string_literal))) {
- Annotation.MustBreakBefore = true;
- } else if (Line.Tokens[i].Tok.is(tok::at) &&
- Line.Tokens[i - 2].Tok.is(tok::at)) {
- // Don't put two objc's '@' on the same line. This could happen,
- // as in, @optional @property ...
- Annotation.MustBreakBefore = true;
- }
-
- Annotation.CanBreakBefore = Annotation.MustBreakBefore ||
- canBreakBefore(i);
- }
+ if (!RootToken.Children.empty())
+ calculateExtraInformation(RootToken.Children[0]);
return true;
}
@@ -808,62 +826,57 @@
return CurrentLineType;
}
- const std::vector<TokenAnnotation> &getAnnotations() {
- return Annotations;
+ const AnnotatedToken &getRootToken() {
+ return RootToken;
}
private:
- void determineTokenTypes() {
- bool IsRHS = false;
- for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
- TokenAnnotation &Annotation = Annotations[i];
- const FormatToken &Tok = Line.Tokens[i];
-
- if (getPrecedence(Tok) == prec::Assignment ||
- Tok.Tok.is(tok::kw_return) || Tok.Tok.is(tok::kw_throw))
- IsRHS = true;
-
- if (Annotation.Type != TT_Unknown)
- continue;
-
- if (Tok.Tok.is(tok::star) || Tok.Tok.is(tok::amp)) {
- Annotation.Type = determineStarAmpUsage(i, IsRHS);
- } else if (Tok.Tok.is(tok::minus) || Tok.Tok.is(tok::plus)) {
- Annotation.Type = determinePlusMinusUsage(i);
- } else if (Tok.Tok.is(tok::minusminus) || Tok.Tok.is(tok::plusplus)) {
- Annotation.Type = determineIncrementUsage(i);
- } else if (Tok.Tok.is(tok::exclaim)) {
- Annotation.Type = TT_UnaryOperator;
- } else if (isBinaryOperator(Line.Tokens[i])) {
- Annotation.Type = TT_BinaryOperator;
- } else if (Tok.Tok.is(tok::comment)) {
- std::string Data(
- Lexer::getSpelling(Tok.Tok, SourceMgr, Lex.getLangOpts()));
+ void determineTokenTypes(AnnotatedToken &Current, bool IsRHS) {
+ if (getPrecedence(Current) == prec::Assignment ||
+ Current.is(tok::kw_return) || Current.is(tok::kw_throw))
+ IsRHS = true;
+
+ if (Current.Type == TT_Unknown) {
+ if (Current.is(tok::star) || Current.is(tok::amp)) {
+ Current.Type = determineStarAmpUsage(Current, IsRHS);
+ } else if (Current.is(tok::minus) || Current.is(tok::plus)) {
+ Current.Type = determinePlusMinusUsage(Current);
+ } else if (Current.is(tok::minusminus) || Current.is(tok::plusplus)) {
+ Current.Type = determineIncrementUsage(Current);
+ } else if (Current.is(tok::exclaim)) {
+ Current.Type = TT_UnaryOperator;
+ } else if (isBinaryOperator(Current)) {
+ Current.Type = TT_BinaryOperator;
+ } else if (Current.is(tok::comment)) {
+ std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr,
+ Lex.getLangOpts()));
if (StringRef(Data).startswith("//"))
- Annotation.Type = TT_LineComment;
+ Current.Type = TT_LineComment;
else
- Annotation.Type = TT_BlockComment;
+ Current.Type = TT_BlockComment;
}
}
+
+ if (!Current.Children.empty())
+ determineTokenTypes(Current.Children[0], IsRHS);
}
- bool isBinaryOperator(const FormatToken &Tok) {
+ bool isBinaryOperator(const AnnotatedToken &Tok) {
// Comma is a binary operator, but does not behave as such wrt. formatting.
return getPrecedence(Tok) > prec::Comma;
}
- TokenType determineStarAmpUsage(unsigned Index, bool IsRHS) {
- if (Index == 0)
+ TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsRHS) {
+ if (Tok.Parent == NULL)
return TT_UnaryOperator;
- if (Index == Annotations.size())
+ if (Tok.Children.size() == 0)
return TT_Unknown;
- const FormatToken &PrevToken = Line.Tokens[Index - 1];
- const FormatToken &NextToken = Line.Tokens[Index + 1];
+ const FormatToken &PrevToken = Tok.Parent->FormatTok;
+ const FormatToken &NextToken = Tok.Children[0].FormatTok;
if (PrevToken.Tok.is(tok::l_paren) || PrevToken.Tok.is(tok::l_square) ||
PrevToken.Tok.is(tok::comma) || PrevToken.Tok.is(tok::kw_return) ||
- PrevToken.Tok.is(tok::colon) ||
- Annotations[Index - 1].Type == TT_BinaryOperator)
+ PrevToken.Tok.is(tok::colon) || Tok.Parent->Type == TT_BinaryOperator)
return TT_UnaryOperator;
if (PrevToken.Tok.isLiteral() || NextToken.Tok.isLiteral() ||
@@ -885,21 +898,20 @@
return TT_PointerOrReference;
}
- TokenType determinePlusMinusUsage(unsigned Index) {
+ TokenType determinePlusMinusUsage(const AnnotatedToken &Tok) {
// At the start of the line, +/- specific ObjectiveC method declarations.
- if (Index == 0)
+ if (Tok.Parent == NULL)
return TT_ObjCMethodSpecifier;
// Use heuristics to recognize unary operators.
- const Token &PreviousTok = Line.Tokens[Index - 1].Tok;
- if (PreviousTok.is(tok::equal) || PreviousTok.is(tok::l_paren) ||
- PreviousTok.is(tok::comma) || PreviousTok.is(tok::l_square) ||
- PreviousTok.is(tok::question) || PreviousTok.is(tok::colon) ||
- PreviousTok.is(tok::kw_return) || PreviousTok.is(tok::kw_case))
+ if (Tok.Parent->is(tok::equal) || Tok.Parent->is(tok::l_paren) ||
+ Tok.Parent->is(tok::comma) || Tok.Parent->is(tok::l_square) ||
+ Tok.Parent->is(tok::question) || Tok.Parent->is(tok::colon) ||
+ Tok.Parent->is(tok::kw_return) || Tok.Parent->is(tok::kw_case))
return TT_UnaryOperator;
// There can't be to consecutive binary operators.
- if (Annotations[Index - 1].Type == TT_BinaryOperator)
+ if (Tok.Parent->Type == TT_BinaryOperator)
return TT_UnaryOperator;
// Fall back to marking the token as binary operator.
@@ -907,14 +919,15 @@
}
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
- TokenType determineIncrementUsage(unsigned Index) {
- if (Index != 0 && Line.Tokens[Index - 1].Tok.is(tok::identifier))
+ TokenType determineIncrementUsage(const AnnotatedToken &Tok) {
+ if (Tok.Parent != NULL && Tok.Parent->is(tok::identifier))
return TT_TrailingUnaryOperator;
return TT_UnaryOperator;
}
- bool spaceRequiredBetween(Token Left, Token Right) {
+ bool spaceRequiredBetween(const AnnotatedToken &Left,
+ const AnnotatedToken &Right) {
if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
return false;
if (Left.is(tok::kw_template) && Right.is(tok::less))
@@ -928,11 +941,12 @@
if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
return false;
if (Right.is(tok::amp) || Right.is(tok::star))
- return Left.isLiteral() ||
+ return Left.FormatTok.Tok.isLiteral() ||
(Left.isNot(tok::star) && Left.isNot(tok::amp) &&
!Style.PointerAndReferenceBindToType);
if (Left.is(tok::amp) || Left.is(tok::star))
- return Right.isLiteral() || Style.PointerAndReferenceBindToType;
+ return Right.FormatTok.Tok.isLiteral() ||
+ Style.PointerAndReferenceBindToType;
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
if (Left.is(tok::l_square) || Right.is(tok::l_square) ||
@@ -956,118 +970,102 @@
(Left.isNot(tok::identifier) && Left.isNot(tok::kw_sizeof) &&
Left.isNot(tok::kw_typeof) && Left.isNot(tok::kw_alignof));
}
- if (Left.is(tok::at) && Right.getObjCKeywordID() != tok::objc_not_keyword)
+ if (Left.is(tok::at) &&
+ Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword)
return false;
return true;
}
- bool spaceRequiredBefore(unsigned i) {
- TokenAnnotation &Annotation = Annotations[i];
- const FormatToken &Current = Line.Tokens[i];
-
+ bool spaceRequiredBefore(const AnnotatedToken &Tok) {
if (CurrentLineType == LT_ObjCMethodDecl) {
- if (Current.Tok.is(tok::identifier) && (i != Line.Tokens.size() - 1) &&
- Line.Tokens[i + 1].Tok.is(tok::colon) &&
- Line.Tokens[i - 1].Tok.is(tok::identifier))
+ if (Tok.is(tok::identifier) && !Tok.Children.empty() &&
+ Tok.Children[0].is(tok::colon) && Tok.Parent->is(tok::identifier))
return true;
- if (Current.Tok.is(tok::colon))
+ if (Tok.is(tok::colon))
return false;
- if (Annotations[i - 1].Type == TT_ObjCMethodSpecifier)
+ if (Tok.Parent->Type == TT_ObjCMethodSpecifier)
return true;
- if (Line.Tokens[i - 1].Tok.is(tok::r_paren) &&
- Current.Tok.is(tok::identifier))
+ if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier))
// Don't space between ')' and <id>
return false;
- if (Line.Tokens[i - 1].Tok.is(tok::colon) && Current.Tok.is(tok::l_paren))
+ if (Tok.Parent->is(tok::colon) && Tok.is(tok::l_paren))
// Don't space between ':' and '('
return false;
}
- if (Annotation.Type == TT_CtorInitializerColon)
+ if (Tok.Type == TT_CtorInitializerColon)
return true;
- if (Annotation.Type == TT_OverloadedOperator)
- return Current.Tok.is(tok::identifier) || Current.Tok.is(tok::kw_new) ||
- Current.Tok.is(tok::kw_delete);
- if (Annotations[i - 1].Type == TT_OverloadedOperator)
- return false;
- if (Current.Tok.is(tok::colon))
- return Line.Tokens[0].Tok.isNot(tok::kw_case) &&
- (i != Line.Tokens.size() - 1);
- if (Annotations[i - 1].Type == TT_UnaryOperator)
- return false;
- if (Annotation.Type == TT_UnaryOperator)
- return Line.Tokens[i - 1].Tok.isNot(tok::l_paren) &&
- Line.Tokens[i - 1].Tok.isNot(tok::l_square);
- if (Line.Tokens[i - 1].Tok.is(tok::greater) &&
- Current.Tok.is(tok::greater)) {
- return Annotation.Type == TT_TemplateCloser && Annotations[i - 1].Type ==
+ if (Tok.Type == TT_OverloadedOperator)
+ return Tok.is(tok::identifier) || Tok.is(tok::kw_new) ||
+ Tok.is(tok::kw_delete);
+ if (Tok.Parent->Type == TT_OverloadedOperator)
+ return false;
+ if (Tok.is(tok::colon))
+ return RootToken.isNot(tok::kw_case) && (!Tok.Children.empty());
+ if (Tok.Parent->Type == TT_UnaryOperator)
+ return false;
+ if (Tok.Type == TT_UnaryOperator)
+ return Tok.Parent->isNot(tok::l_paren) &&
+ Tok.Parent->isNot(tok::l_square);
+ if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) {
+ return Tok.Type == TT_TemplateCloser && Tok.Parent->Type ==
TT_TemplateCloser && Style.SplitTemplateClosingGreater;
}
- if (Annotation.Type == TT_DirectorySeparator ||
- Annotations[i - 1].Type == TT_DirectorySeparator)
+ if (Tok.Type == TT_DirectorySeparator ||
+ Tok.Parent->Type == TT_DirectorySeparator)
return false;
- if (Annotation.Type == TT_BinaryOperator ||
- Annotations[i - 1].Type == TT_BinaryOperator)
+ if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator)
return true;
- if (Annotations[i - 1].Type == TT_TemplateCloser &&
- Current.Tok.is(tok::l_paren))
+ if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
return false;
- if (Current.Tok.is(tok::less) && Line.Tokens[0].Tok.is(tok::hash))
+ if (Tok.is(tok::less) && RootToken.is(tok::hash))
return true;
- if (Annotation.Type == TT_TrailingUnaryOperator)
+ if (Tok.Type == TT_TrailingUnaryOperator)
return false;
- return spaceRequiredBetween(Line.Tokens[i - 1].Tok, Current.Tok);
+ return spaceRequiredBetween(*Tok.Parent, Tok);
}
- bool canBreakBefore(unsigned i) {
+ bool canBreakBefore(const AnnotatedToken &Right) {
+ const AnnotatedToken &Left = *Right.Parent;
if (CurrentLineType == LT_ObjCMethodDecl) {
- if (Line.Tokens[i].Tok.is(tok::identifier) &&
- (i != Line.Tokens.size() - 1) &&
- Line.Tokens[i + 1].Tok.is(tok::colon) &&
- Line.Tokens[i - 1].Tok.is(tok::identifier))
+ if (Right.is(tok::identifier) && !Right.Children.empty() &&
+ Right.Children[0].is(tok::colon) && Left.is(tok::identifier))
return true;
- if (CurrentLineType == LT_ObjCMethodDecl &&
- Line.Tokens[i].Tok.is(tok::identifier) &&
- Line.Tokens[i - 1].Tok.is(tok::l_paren) &&
- Line.Tokens[i - 2].Tok.is(tok::colon))
+ if (CurrentLineType == LT_ObjCMethodDecl && Right.is(tok::identifier) &&
+ Left.is(tok::l_paren) && Left.Parent->is(tok::colon))
// Don't break this identifier as ':' or identifier
// before it will break.
return false;
- if (Line.Tokens[i].Tok.is(tok::colon) &&
- Line.Tokens[i - 1].Tok.is(tok::identifier) &&
- Annotations[i - 1].CanBreakBefore)
+ if (Right.is(tok::colon) && Left.is(tok::identifier) &&
+ Left.CanBreakBefore)
// Don't break at ':' if identifier before it can beak.
return false;
}
- if (Annotations[i - 1].ClosesTemplateDeclaration)
+ if (Left.ClosesTemplateDeclaration)
return true;
- if (Annotations[i - 1].Type == TT_PointerOrReference ||
- Annotations[i - 1].Type == TT_TemplateCloser ||
- Annotations[i].Type == TT_ConditionalExpr) {
+ if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
+ Right.Type == TT_ConditionalExpr) {
return false;
}
- const FormatToken &Left = Line.Tokens[i - 1];
- const FormatToken &Right = Line.Tokens[i];
- if (Left.Tok.is(tok::equal) && CurrentLineType == LT_VirtualFunctionDecl)
+ if (Left.is(tok::equal) && CurrentLineType == LT_VirtualFunctionDecl)
return false;
- if (Right.Tok.is(tok::r_paren) || Right.Tok.is(tok::l_brace) ||
- Right.Tok.is(tok::comment) || Right.Tok.is(tok::greater))
+ if (Right.is(tok::r_paren) || Right.is(tok::l_brace) ||
+ Right.is(tok::comment) || Right.is(tok::greater))
return false;
- return (isBinaryOperator(Left) && Left.Tok.isNot(tok::lessless)) ||
- Left.Tok.is(tok::comma) || Right.Tok.is(tok::lessless) ||
- Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period) ||
- Right.Tok.is(tok::colon) || Left.Tok.is(tok::semi) ||
- Left.Tok.is(tok::l_brace) ||
- (Left.Tok.is(tok::l_paren) && !Right.Tok.is(tok::r_paren));
+ return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) ||
+ Left.is(tok::comma) || Right.is(tok::lessless) ||
+ Right.is(tok::arrow) || Right.is(tok::period) ||
+ Right.is(tok::colon) || Left.is(tok::semi) ||
+ Left.is(tok::l_brace) ||
+ (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
}
- const UnwrappedLine &Line;
FormatStyle Style;
SourceManager &SourceMgr;
Lexer &Lex;
LineType CurrentLineType;
- std::vector<TokenAnnotation> Annotations;
+ AnnotatedToken RootToken;
};
class LexerBasedFormatTokenSource : public FormatTokenSource {
@@ -1183,12 +1181,13 @@
unsigned formatUnwrappedLine(const UnwrappedLine &TheLine,
unsigned PreviousEndOfLineColumn) {
- if (TheLine.Tokens.empty())
- return 0; // FIXME: Find out how this can ever happen.
-
+ const FormatToken *First = &TheLine.RootToken;
+ const FormatToken *Last = First;
+ while (!Last->Children.empty())
+ Last = &Last->Children.back();
CharSourceRange LineRange = CharSourceRange::getTokenRange(
- TheLine.Tokens.front().Tok.getLocation(),
- TheLine.Tokens.back().Tok.getLocation());
+ First->Tok.getLocation(),
+ Last->Tok.getLocation());
for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
if (SourceMgr.isBeforeInTranslationUnit(LineRange.getEnd(),
@@ -1202,16 +1201,15 @@
break;
UnwrappedLineFormatter Formatter(
Style, SourceMgr, TheLine, PreviousEndOfLineColumn,
- Annotator.getLineType(), Annotator.getAnnotations(), Replaces,
+ Annotator.getLineType(), Annotator.getRootToken(), Replaces,
StructuralError);
return Formatter.format();
}
// If we did not reformat this unwrapped line, the column at the end of the
// last token is unchanged - thus, we can calculate the end of the last
// token, and return the result.
- const FormatToken &Token = TheLine.Tokens.back();
- return SourceMgr.getSpellingColumnNumber(Token.Tok.getLocation()) +
- Lex.MeasureTokenLength(Token.Tok.getLocation(), SourceMgr,
+ return SourceMgr.getSpellingColumnNumber(Last->Tok.getLocation()) +
+ Lex.MeasureTokenLength(Last->Tok.getLocation(), SourceMgr,
Lex.getLangOpts()) -
1;
}
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=171856&r1=171855&r2=171856&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Tue Jan 8 08:56:18 2013
@@ -74,7 +74,8 @@
UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
FormatTokenSource &Tokens,
UnwrappedLineConsumer &Callback)
- : Style(Style), Tokens(&Tokens), Callback(Callback) {
+ : RootTokenInitialized(false), Style(Style), Tokens(&Tokens),
+ Callback(Callback) {
}
bool UnwrappedLineParser::parse() {
@@ -493,13 +494,15 @@
}
void UnwrappedLineParser::addUnwrappedLine() {
+ if (!RootTokenInitialized)
+ return;
// Consume trailing comments.
while (!eof() && FormatTok.NewlinesBefore == 0 &&
FormatTok.Tok.is(tok::comment)) {
nextToken();
}
Callback.consumeUnwrappedLine(Line);
- Line.Tokens.clear();
+ RootTokenInitialized = false;
}
bool UnwrappedLineParser::eof() const {
@@ -509,7 +512,14 @@
void UnwrappedLineParser::nextToken() {
if (eof())
return;
- Line.Tokens.push_back(FormatTok);
+ if (RootTokenInitialized) {
+ LastInCurrentLine->Children.push_back(FormatTok);
+ LastInCurrentLine = &LastInCurrentLine->Children.back();
+ } else {
+ Line.RootToken = FormatTok;
+ RootTokenInitialized = true;
+ LastInCurrentLine = &Line.RootToken;
+ }
readToken();
}
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=171856&r1=171855&r2=171856&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Tue Jan 8 08:56:18 2013
@@ -24,6 +24,8 @@
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
+#include <vector>
+
namespace clang {
namespace format {
@@ -65,6 +67,11 @@
/// \brief Indicates that this is the first token.
bool IsFirst;
+
+ // FIXME: We currently assume that there is exactly one token in this vector
+ // except for the very last token that does not have any children.
+ /// \brief All tokens that logically follow this token.
+ std::vector<FormatToken> Children;
};
/// \brief An unwrapped line is a sequence of \c Token, that we would like to
@@ -78,7 +85,7 @@
}
/// \brief The \c Token comprising this \c UnwrappedLine.
- SmallVector<FormatToken, 16> Tokens;
+ FormatToken RootToken;
/// \brief The indent level of the \c UnwrappedLine.
unsigned Level;
@@ -138,6 +145,8 @@
// subtracted from beyond 0. Introduce a method to subtract from Line.Level
// and use that everywhere in the Parser.
UnwrappedLine Line;
+ bool RootTokenInitialized;
+ FormatToken *LastInCurrentLine;
FormatToken FormatTok;
const FormatStyle &Style;
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=171856&r1=171855&r2=171856&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Jan 8 08:56:18 2013
@@ -537,8 +537,8 @@
}
TEST_F(FormatTest, LayoutSingleUnwrappedLineInMacro) {
- EXPECT_EQ("#define A \\\n b;",
- format("#define A b;", 10, 2, getLLVMStyleWithColumns(11)));
+ EXPECT_EQ("# define A\\\n b;",
+ format("# define A b;", 11, 2, getLLVMStyleWithColumns(11)));
}
TEST_F(FormatTest, MacroDefinitionInsideStatement) {
More information about the cfe-commits
mailing list