// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
-static unsigned getLengthToMatchingParen(const AnnotatedToken &Tok) {
+static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
if (Tok.MatchingParen == NULL)
return 0;
- AnnotatedToken *End = Tok.MatchingParen;
- while (!End->Children.empty() && !End->Children[0].CanBreakBefore) {
- End = &End->Children[0];
+ FormatToken *End = Tok.MatchingParen;
+ while (End->Next && !End->Next->CanBreakBefore) {
+ End = End->Next;
}
return End->TotalLength - Tok.TotalLength + 1;
}
public:
UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
const AnnotatedLine &Line, unsigned FirstIndent,
- const AnnotatedToken &RootToken,
+ const FormatToken *RootToken,
WhitespaceManager &Whitespaces)
: Style(Style), SourceMgr(SourceMgr), Line(Line),
FirstIndent(FirstIndent), RootToken(RootToken),
// Initialize state dependent on indent.
LineState State;
State.Column = FirstIndent;
- State.NextToken = &RootToken;
+ State.NextToken = RootToken;
State.Stack.push_back(
ParenState(FirstIndent, FirstIndent, /*AvoidBinPacking=*/ false,
/*NoLineBreak=*/ false));
// If everything fits on a single line, just put it there.
unsigned ColumnLimit = Style.ColumnLimit;
if (NextLine && NextLine->InPPDirective &&
- !NextLine->First.FormatTok->HasUnescapedNewline)
+ !NextLine->First->HasUnescapedNewline)
ColumnLimit = getColumnLimit();
if (Line.Last->TotalLength <= ColumnLimit - FirstIndent) {
while (State.NextToken != NULL) {
}
private:
- void DebugTokenState(const AnnotatedToken &AnnotatedTok) {
- const Token &Tok = AnnotatedTok.FormatTok->Tok;
+ void DebugTokenState(const FormatToken &FormatTok) {
+ const Token &Tok = FormatTok.Tok;
llvm::dbgs() << StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
Tok.getLength());
llvm::dbgs();
unsigned Column;
/// \brief The token that needs to be next formatted.
- const AnnotatedToken *NextToken;
+ const FormatToken *NextToken;
/// \brief \c true if this line contains a continued for-loop section.
bool LineContainsContinuedForLoopSection;
/// If \p DryRun is \c false, also creates and stores the required
/// \c Replacement.
unsigned addTokenToState(bool Newline, bool DryRun, LineState &State) {
- const AnnotatedToken &Current = *State.NextToken;
- const AnnotatedToken &Previous = *State.NextToken->Parent;
+ const FormatToken &Current = *State.NextToken;
+ const FormatToken &Previous = *State.NextToken->Previous;
if (State.Stack.size() == 0 || Current.Type == TT_ImplicitStringLiteral) {
// FIXME: Is this correct?
- int WhitespaceLength =
- SourceMgr.getSpellingColumnNumber(
- State.NextToken->FormatTok->WhitespaceRange.getEnd()) -
- SourceMgr.getSpellingColumnNumber(
- State.NextToken->FormatTok->WhitespaceRange.getBegin());
- State.Column +=
- WhitespaceLength + State.NextToken->FormatTok->TokenLength;
- if (State.NextToken->Children.empty())
- State.NextToken = NULL;
- else
- State.NextToken = &State.NextToken->Children[0];
+ int WhitespaceLength = SourceMgr.getSpellingColumnNumber(
+ State.NextToken->WhitespaceRange.getEnd()) -
+ SourceMgr.getSpellingColumnNumber(
+ State.NextToken->WhitespaceRange.getBegin());
+ State.Column += WhitespaceLength + State.NextToken->TokenLength;
+ State.NextToken = State.NextToken->Next;
return 0;
}
Line.StartsDefinition)) {
State.Column = State.Stack.back().Indent;
} else if (Current.Type == TT_ObjCSelectorName) {
- if (State.Stack.back().ColonPos > Current.FormatTok->TokenLength) {
- State.Column =
- State.Stack.back().ColonPos - Current.FormatTok->TokenLength;
+ if (State.Stack.back().ColonPos > Current.TokenLength) {
+ State.Column = State.Stack.back().ColonPos - Current.TokenLength;
} else {
State.Column = State.Stack.back().Indent;
- State.Stack.back().ColonPos =
- State.Column + Current.FormatTok->TokenLength;
+ State.Stack.back().ColonPos = State.Column + Current.TokenLength;
}
} else if (Current.Type == TT_StartOfName ||
Previous.isOneOf(tok::coloncolon, tok::equal) ||
if (!DryRun) {
unsigned NewLines = 1;
if (Current.Type == TT_LineComment)
- NewLines =
- std::max(NewLines, std::min(Current.FormatTok->NewlinesBefore,
- Style.MaxEmptyLinesToKeep + 1));
+ NewLines = std::max(
+ NewLines,
+ std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
Whitespaces.replaceWhitespace(Current, NewLines, State.Column,
State.Column, Line.InPPDirective);
}
State.Stack.back().LastSpace = State.Column;
if (Current.isOneOf(tok::arrow, tok::period) &&
Current.Type != TT_DesignatedInitializerPeriod)
- State.Stack.back().LastSpace += Current.FormatTok->TokenLength;
+ State.Stack.back().LastSpace += Current.TokenLength;
State.StartOfLineLevel = State.ParenLevel;
State.LowestLevelOnLine = State.ParenLevel;
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
State.Stack[i].BreakBeforeParameter = true;
}
- const AnnotatedToken *TokenBefore = Current.getPreviousNoneComment();
+ const FormatToken *TokenBefore = Current.getPreviousNoneComment();
if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) &&
TokenBefore->Type != TT_TemplateCloser &&
TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope())
}
} else {
if (Current.is(tok::equal) &&
- (RootToken.is(tok::kw_for) || State.ParenLevel == 0) &&
+ (RootToken->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.
- const AnnotatedToken *Tok = &Previous;
- while (Tok &&
- State.Stack.back().VariablePos >= Tok->FormatTok->TokenLength) {
- State.Stack.back().VariablePos -= Tok->FormatTok->TokenLength;
+ const FormatToken *Tok = &Previous;
+ while (Tok && State.Stack.back().VariablePos >= Tok->TokenLength) {
+ State.Stack.back().VariablePos -= Tok->TokenLength;
if (Tok->SpacesRequiredBefore != 0)
break;
- Tok = Tok->Parent;
+ Tok = Tok->Previous;
}
if (Previous.PartOfMultiVariableDeclStmt)
State.Stack.back().LastSpace = State.Stack.back().VariablePos;
if (Current.Type == TT_ObjCSelectorName &&
State.Stack.back().ColonPos == 0) {
if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
- State.Column + Spaces + Current.FormatTok->TokenLength)
+ State.Column + Spaces + Current.TokenLength)
State.Stack.back().ColonPos =
State.Stack.back().Indent + Current.LongestObjCSelectorName;
else
State.Stack.back().ColonPos =
- State.Column + Spaces + Current.FormatTok->TokenLength;
+ State.Column + Spaces + Current.TokenLength;
}
if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr &&
else if ((Previous.Type == TT_BinaryOperator ||
Previous.Type == TT_ConditionalExpr ||
Previous.Type == TT_CtorInitializerColon) &&
- !(getPrecedence(Previous) == prec::Assignment &&
+ !(Previous.getPrecedence() == prec::Assignment &&
Current.FakeLParens.empty()))
// Always indent relative to the RHS of the expression unless this is a
// simple assignment without binary expression on the RHS.
/// \brief Mark the next token as consumed in \p State and modify its stacks
/// accordingly.
unsigned moveStateToNextToken(LineState &State, bool DryRun) {
- const AnnotatedToken &Current = *State.NextToken;
+ const FormatToken &Current = *State.NextToken;
assert(State.Stack.size());
if (Current.Type == TT_InheritanceColon)
if (Current.isOneOf(tok::period, tok::arrow) &&
Line.Type == LT_BuilderTypeCall && State.ParenLevel == 0)
State.Stack.back().StartOfFunctionCall =
- Current.LastInChainOfCalls ? 0 : State.Column +
- Current.FormatTok->TokenLength;
+ Current.LastInChainOfCalls ? 0 : State.Column + Current.TokenLength;
if (Current.Type == TT_CtorInitializerColon) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
State.Stack.back().Indent += 4;
// Insert scopes created by fake parenthesis.
- const AnnotatedToken *Previous = Current.getPreviousNoneComment();
+ const FormatToken *Previous = Current.getPreviousNoneComment();
// Don't add extra indentation for the first fake parenthesis after
// 'return', assignements or opening <({[. The indentation for these cases
// is special cased.
bool SkipFirstExtraIndent =
Current.is(tok::kw_return) ||
(Previous && (Previous->opensScope() ||
- getPrecedence(*Previous) == prec::Assignment));
+ Previous->getPrecedence() == prec::Assignment));
for (SmallVector<prec::Level, 4>::const_reverse_iterator
I = Current.FakeLParens.rbegin(),
E = Current.FakeLParens.rend();
bool AvoidBinPacking;
if (Current.is(tok::l_brace)) {
NewIndent = Style.IndentWidth + LastSpace;
- const AnnotatedToken *NextNoComment = Current.getNextNoneComment();
+ const FormatToken *NextNoComment = Current.getNextNoneComment();
AvoidBinPacking = NextNoComment &&
NextNoComment->Type == TT_DesignatedInitializerPeriod;
} else {
// If we encounter a closing ), ], } or >, we can remove a level from our
// stacks.
if (Current.isOneOf(tok::r_paren, tok::r_square) ||
- (Current.is(tok::r_brace) && State.NextToken != &RootToken) ||
+ (Current.is(tok::r_brace) && State.NextToken != RootToken) ||
State.NextToken->Type == TT_TemplateCloser) {
State.Stack.pop_back();
--State.ParenLevel;
State.StartOfStringLiteral = 0;
}
- State.Column += Current.FormatTok->TokenLength;
+ State.Column += Current.TokenLength;
- if (State.NextToken->Children.empty())
- State.NextToken = NULL;
- else
- State.NextToken = &State.NextToken->Children[0];
+ State.NextToken = State.NextToken->Next;
return breakProtrudingToken(Current, State, DryRun);
}
/// Note that the penalty of the token protruding the allowed line length is
/// already handled in \c addNextStateToQueue; the returned penalty will only
/// cover the cost of the additional line breaks.
- unsigned breakProtrudingToken(const AnnotatedToken &Current, LineState &State,
+ unsigned breakProtrudingToken(const FormatToken &Current, LineState &State,
bool DryRun) {
unsigned UnbreakableTailLength = Current.UnbreakableTailLength;
llvm::OwningPtr<BreakableToken> Token;
- unsigned StartColumn = State.Column - Current.FormatTok->TokenLength;
+ unsigned StartColumn = State.Column - Current.TokenLength;
unsigned OriginalStartColumn =
- SourceMgr.getSpellingColumnNumber(
- Current.FormatTok->getStartOfNonWhitespace()) -
+ SourceMgr.getSpellingColumnNumber(Current.getStartOfNonWhitespace()) -
1;
if (Current.is(tok::string_literal) &&
Current.Type != TT_ImplicitStringLiteral) {
// Only break up default narrow strings.
- const char *LiteralData = SourceMgr.getCharacterData(
- Current.FormatTok->getStartOfNonWhitespace());
+ const char *LiteralData =
+ SourceMgr.getCharacterData(Current.getStartOfNonWhitespace());
if (!LiteralData || *LiteralData != '"')
return 0;
- Token.reset(new BreakableStringLiteral(*Current.FormatTok, StartColumn));
+ Token.reset(new BreakableStringLiteral(Current, StartColumn));
} else if (Current.Type == TT_BlockComment) {
- BreakableBlockComment *BBC =
- new BreakableBlockComment(Style, *Current.FormatTok, StartColumn,
- OriginalStartColumn, !Current.Parent);
+ BreakableBlockComment *BBC = new BreakableBlockComment(
+ Style, Current, StartColumn, OriginalStartColumn, !Current.Previous);
Token.reset(BBC);
} else if (Current.Type == TT_LineComment &&
- (Current.Parent == NULL ||
- Current.Parent->Type != TT_ImplicitStringLiteral)) {
- Token.reset(new BreakableLineComment(*Current.FormatTok, StartColumn));
+ (Current.Previous == NULL ||
+ Current.Previous->Type != TT_ImplicitStringLiteral)) {
+ Token.reset(new BreakableLineComment(Current, StartColumn));
} else {
return 0;
}
reconstructPath(State, Current->Previous);
DEBUG({
if (Current->NewLine) {
- llvm::dbgs()
- << "Penalty for splitting before "
- << Current->Previous->State.NextToken->FormatTok->Tok.getName()
- << ": " << Current->Previous->State.NextToken->SplitPenalty << "\n";
+ llvm::dbgs() << "Penalty for splitting before "
+ << Current->Previous->State.NextToken->Tok.getName()
+ << ": " << Current->Previous->State.NextToken->SplitPenalty
+ << "\n";
}
});
addTokenToState(Current->NewLine, false, State);
/// \brief Returns \c true, if a line break after \p State is allowed.
bool canBreak(const LineState &State) {
- const AnnotatedToken &Current = *State.NextToken;
- const AnnotatedToken &Previous = *Current.Parent;
+ const FormatToken &Current = *State.NextToken;
+ const FormatToken &Previous = *Current.Previous;
+ assert(&Previous == Current.Previous);
if (!Current.CanBreakBefore &&
!(Current.is(tok::r_brace) &&
State.Stack.back().BreakBeforeClosingBrace))
// 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.Parent &&
- Previous.Parent->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
+ Previous.Previous &&
+ Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
return false;
// This prevents breaks like:
// ...
/// \brief Returns \c true, if a line break after \p State is mandatory.
bool mustBreak(const LineState &State) {
- const AnnotatedToken &Current = *State.NextToken;
- const AnnotatedToken &Previous = *Current.Parent;
+ const FormatToken &Current = *State.NextToken;
+ const FormatToken &Previous = *Current.Previous;
if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon)
return true;
if (Current.is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace)
if (Previous.Type == TT_BinaryOperator &&
Current.Type != TT_BinaryOperator && // Special case for ">>".
!Previous.isOneOf(tok::lessless, tok::question) &&
- getPrecedence(Previous) != prec::Assignment &&
+ Previous.getPrecedence() != prec::Assignment &&
State.Stack.back().BreakBeforeParameter)
return true;
// Returns the total number of columns required for the remaining tokens.
unsigned getRemainingLength(const LineState &State) {
- if (State.NextToken && State.NextToken->Parent)
- return Line.Last->TotalLength - State.NextToken->Parent->TotalLength;
+ if (State.NextToken && State.NextToken->Previous)
+ return Line.Last->TotalLength - State.NextToken->Previous->TotalLength;
return 0;
}
SourceManager &SourceMgr;
const AnnotatedLine &Line;
const unsigned FirstIndent;
- const AnnotatedToken &RootToken;
+ const FormatToken *RootToken;
WhitespaceManager &Whitespaces;
llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
// FIXME: Can/should this be done in the UnwrappedLineParser?
const AnnotatedLine *NextNoneCommentLine = NULL;
for (unsigned i = AnnotatedLines.size() - 1; i > 0; --i) {
- if (NextNoneCommentLine && AnnotatedLines[i].First.is(tok::comment) &&
- AnnotatedLines[i].First.Children.empty())
+ if (NextNoneCommentLine && AnnotatedLines[i].First->is(tok::comment) &&
+ !AnnotatedLines[i].First->Next)
AnnotatedLines[i].Level = NextNoneCommentLine->Level;
else
NextNoneCommentLine =
- AnnotatedLines[i].First.isNot(tok::r_brace) ? &AnnotatedLines[i]
- : NULL;
+ AnnotatedLines[i].First->isNot(tok::r_brace) ? &AnnotatedLines[i]
+ : NULL;
}
std::vector<int> IndentForLevel;
bool PreviousLineWasTouched = false;
- const AnnotatedToken *PreviousLineLastToken = 0;
+ const FormatToken *PreviousLineLastToken = 0;
bool FormatPPDirective = false;
for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(),
E = AnnotatedLines.end();
I != E; ++I) {
const AnnotatedLine &TheLine = *I;
- const FormatToken *FirstTok = TheLine.First.FormatTok;
- int Offset = getIndentOffset(TheLine.First);
+ const FormatToken *FirstTok = TheLine.First;
+ int Offset = getIndentOffset(*TheLine.First);
// Check whether this line is part of a formatted preprocessor directive.
if (FirstTok->HasUnescapedNewline)
tryFitMultipleLinesInOne(Indent, I, E);
bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0;
- if (TheLine.First.is(tok::eof)) {
+ if (TheLine.First->is(tok::eof)) {
if (PreviousLineWasTouched) {
unsigned NewLines = std::min(FirstTok->NewlinesBefore, 1u);
- Whitespaces.replaceWhitespace(TheLine.First, NewLines, /*Indent*/ 0,
+ Whitespaces.replaceWhitespace(*TheLine.First, NewLines, /*Indent*/ 0,
/*TargetColumn*/ 0);
}
} else if (TheLine.Type != LT_Invalid &&
// Insert a break even if there is a structural error in case where
// we break apart a line consisting of multiple unwrapped lines.
(FirstTok->NewlinesBefore == 0 || !StructuralError)) {
- formatFirstToken(TheLine.First, PreviousLineLastToken, Indent,
+ formatFirstToken(*TheLine.First, PreviousLineLastToken, Indent,
TheLine.InPPDirective);
} else {
Indent = LevelIndent =
} else {
// Format the first token if necessary, and notify the WhitespaceManager
// about the unchanged whitespace.
- for (const AnnotatedToken *Tok = &TheLine.First; Tok != NULL;
- Tok = Tok->Children.empty() ? NULL : &Tok->Children[0]) {
- if (Tok == &TheLine.First &&
- (Tok->FormatTok->NewlinesBefore > 0 || Tok->FormatTok->IsFirst)) {
- unsigned LevelIndent = SourceMgr.getSpellingColumnNumber(
- Tok->FormatTok->Tok.getLocation()) -
- 1;
+ for (const FormatToken *Tok = TheLine.First; Tok != NULL;
+ Tok = Tok->Next) {
+ if (Tok == TheLine.First &&
+ (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
+ unsigned LevelIndent =
+ SourceMgr.getSpellingColumnNumber(Tok->Tok.getLocation()) - 1;
// Remove trailing whitespace of the previous line if it was
// touched.
if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) {
formatFirstToken(*Tok, PreviousLineLastToken, LevelIndent,
TheLine.InPPDirective);
} else {
- Whitespaces.addUntouchableToken(*Tok->FormatTok,
- TheLine.InPPDirective);
+ Whitespaces.addUntouchableToken(*Tok, TheLine.InPPDirective);
}
if (static_cast<int>(LevelIndent) - Offset >= 0)
if (Tok->isNot(tok::comment))
IndentForLevel[TheLine.Level] = LevelIndent;
} else {
- Whitespaces.addUntouchableToken(*Tok->FormatTok,
- TheLine.InPPDirective);
+ Whitespaces.addUntouchableToken(*Tok, TheLine.InPPDirective);
}
}
// If we did not reformat this unwrapped line, the column at the end of
unsigned CountBoundToType = 0;
bool HasCpp03IncompatibleFormat = false;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- if (AnnotatedLines[i].First.Children.empty())
+ if (!AnnotatedLines[i].First->Next)
continue;
- AnnotatedToken *Tok = &AnnotatedLines[i].First.Children[0];
- while (!Tok->Children.empty()) {
+ FormatToken *Tok = AnnotatedLines[i].First->Next;
+ while (Tok->Next) {
if (Tok->Type == TT_PointerOrReference) {
- bool SpacesBefore = Tok->FormatTok->WhitespaceRange.getBegin() !=
- Tok->FormatTok->WhitespaceRange.getEnd();
- bool SpacesAfter =
- Tok->Children[0].FormatTok->WhitespaceRange.getBegin() !=
- Tok->Children[0].FormatTok->WhitespaceRange.getEnd();
+ bool SpacesBefore =
+ Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
+ bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
+ Tok->Next->WhitespaceRange.getEnd();
if (SpacesBefore && !SpacesAfter)
++CountBoundToVariable;
else if (!SpacesBefore && SpacesAfter)
}
if (Tok->Type == TT_TemplateCloser &&
- Tok->Parent->Type == TT_TemplateCloser &&
- Tok->FormatTok->WhitespaceRange.getBegin() ==
- Tok->FormatTok->WhitespaceRange.getEnd())
+ Tok->Previous->Type == TT_TemplateCloser &&
+ Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd())
HasCpp03IncompatibleFormat = true;
- Tok = &Tok->Children[0];
+ Tok = Tok->Next;
}
}
if (Style.DerivePointerBinding) {
///
/// For example, 'public:' labels in classes are offset by 1 or 2
/// characters to the left from their level.
- int getIndentOffset(const AnnotatedToken &RootToken) {
+ int getIndentOffset(const FormatToken &RootToken) {
if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
return Style.AccessModifierOffset;
return 0;
if (I->Last->is(tok::l_brace)) {
tryMergeSimpleBlock(I, E, Limit);
} else if (Style.AllowShortIfStatementsOnASingleLine &&
- I->First.is(tok::kw_if)) {
+ I->First->is(tok::kw_if)) {
tryMergeSimpleControlStatement(I, E, Limit);
} else if (Style.AllowShortLoopsOnASingleLine &&
- I->First.isOneOf(tok::kw_for, tok::kw_while)) {
+ I->First->isOneOf(tok::kw_for, tok::kw_while)) {
tryMergeSimpleControlStatement(I, E, Limit);
- } else if (I->InPPDirective && (I->First.FormatTok->HasUnescapedNewline ||
- I->First.FormatTok->IsFirst)) {
+ } else if (I->InPPDirective &&
+ (I->First->HasUnescapedNewline || I->First->IsFirst)) {
tryMergeSimplePPDirective(I, E, Limit);
}
}
if (Limit == 0)
return;
AnnotatedLine &Line = *I;
- if (!(I + 1)->InPPDirective ||
- (I + 1)->First.FormatTok->HasUnescapedNewline)
+ if (!(I + 1)->InPPDirective || (I + 1)->First->HasUnescapedNewline)
return;
if (I + 2 != E && (I + 2)->InPPDirective &&
- !(I + 2)->First.FormatTok->HasUnescapedNewline)
+ !(I + 2)->First->HasUnescapedNewline)
return;
if (1 + (I + 1)->Last->TotalLength > Limit)
return;
if (Limit == 0)
return;
if ((I + 1)->InPPDirective != I->InPPDirective ||
- ((I + 1)->InPPDirective &&
- (I + 1)->First.FormatTok->HasUnescapedNewline))
+ ((I + 1)->InPPDirective && (I + 1)->First->HasUnescapedNewline))
return;
AnnotatedLine &Line = *I;
if (Line.Last->isNot(tok::r_paren))
return;
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))
+ if (I + 2 != E && Line.First->is(tok::kw_if) &&
+ (I + 2)->First->is(tok::kw_else))
return;
join(Line, *(++I));
}
// we're not in a control flow statement and the last token is an opening
// brace.
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, tok::kw_namespace,
- // This gets rid of all ObjC @ keywords and methods.
- tok::at, tok::minus, tok::plus))
+ 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, tok::kw_namespace,
+ // This gets rid of all ObjC @ keywords and methods.
+ tok::at, tok::minus, tok::plus))
return;
- AnnotatedToken *Tok = &(I + 1)->First;
+ FormatToken *Tok = (I + 1)->First;
if (Tok->getNextNoneComment() == NULL && Tok->is(tok::r_brace) &&
!Tok->MustBreakBefore) {
// We merge empty blocks even if the line exceeds the column limit.
do {
if (Tok->isOneOf(tok::l_brace, tok::r_brace))
return;
- Tok = Tok->Children.empty() ? NULL : &Tok->Children.back();
+ Tok = Tok->Next;
} while (Tok != NULL);
// Last, check that the third line contains a single closing brace.
- Tok = &(I + 2)->First;
+ Tok = (I + 2)->First;
if (Tok->getNextNoneComment() != NULL || Tok->isNot(tok::r_brace) ||
Tok->MustBreakBefore)
return;
}
void join(AnnotatedLine &A, const AnnotatedLine &B) {
- unsigned LengthA = A.Last->TotalLength + B.First.SpacesRequiredBefore;
- A.Last->Children.push_back(B.First);
- while (!A.Last->Children.empty()) {
- A.Last->Children[0].Parent = A.Last;
- A.Last->Children[0].TotalLength += LengthA;
- A.Last = &A.Last->Children[0];
+ assert(!A.Last->Next);
+ assert(!B.First->Previous);
+ A.Last->Next = B.First;
+ B.First->Previous = A.Last;
+ unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
+ for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
+ Tok->TotalLength += LengthA;
+ A.Last = Tok;
}
}
}
bool touchesLine(const AnnotatedLine &TheLine) {
- const FormatToken *First = TheLine.First.FormatTok;
- const FormatToken *Last = TheLine.Last->FormatTok;
+ const FormatToken *First = TheLine.First;
+ const FormatToken *Last = TheLine.Last;
CharSourceRange LineRange = CharSourceRange::getCharRange(
First->WhitespaceRange.getBegin().getLocWithOffset(
First->LastNewlineOffset),
bool touchesPPDirective(std::vector<AnnotatedLine>::iterator I,
std::vector<AnnotatedLine>::iterator E) {
for (; I != E; ++I) {
- if (I->First.FormatTok->HasUnescapedNewline)
+ if (I->First->HasUnescapedNewline)
return false;
if (touchesLine(*I))
return true;
}
bool touchesEmptyLineBefore(const AnnotatedLine &TheLine) {
- const FormatToken *First = TheLine.First.FormatTok;
+ const FormatToken *First = TheLine.First;
CharSourceRange LineRange = CharSourceRange::getCharRange(
First->WhitespaceRange.getBegin(),
First->WhitespaceRange.getBegin().getLocWithOffset(
/// \brief Add a new line and the required indent before the first Token
/// of the \c UnwrappedLine if there was no structural parsing error.
/// Returns the indent level of the \c UnwrappedLine.
- void formatFirstToken(const AnnotatedToken &RootToken,
- const AnnotatedToken *PreviousToken, unsigned Indent,
+ void formatFirstToken(const FormatToken &RootToken,
+ const FormatToken *PreviousToken, unsigned Indent,
bool InPPDirective) {
- const FormatToken *Tok = RootToken.FormatTok;
-
unsigned Newlines =
- std::min(Tok->NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
- if (Newlines == 0 && !Tok->IsFirst)
+ std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
+ if (Newlines == 0 && !RootToken.IsFirst)
Newlines = 1;
// Insert extra new line before access specifiers.
if (PreviousToken && PreviousToken->isOneOf(tok::semi, tok::r_brace) &&
- RootToken.isAccessSpecifier() && Tok->NewlinesBefore == 1)
+ RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
++Newlines;
- Whitespaces.replaceWhitespace(RootToken, Newlines, Indent, Indent,
- InPPDirective && !Tok->HasUnescapedNewline);
+ Whitespaces.replaceWhitespace(
+ RootToken, Newlines, Indent, Indent,
+ InPPDirective && !RootToken.HasUnescapedNewline);
}
FormatStyle Style;
namespace clang {
namespace format {
-bool AnnotatedToken::isUnaryOperator() const {
- switch (FormatTok->Tok.getKind()) {
- case tok::plus:
- case tok::plusplus:
- case tok::minus:
- case tok::minusminus:
- case tok::exclaim:
- case tok::tilde:
- case tok::kw_sizeof:
- case tok::kw_alignof:
- return true;
- default:
- return false;
- }
-}
-
-bool AnnotatedToken::isBinaryOperator() const {
- // Comma is a binary operator, but does not behave as such wrt. formatting.
- return getPrecedence(*this) > prec::Comma;
-}
-
-bool AnnotatedToken::isTrailingComment() const {
- return is(tok::comment) &&
- (Children.empty() || Children[0].FormatTok->NewlinesBefore > 0);
-}
-
-AnnotatedToken *AnnotatedToken::getPreviousNoneComment() const {
- AnnotatedToken *Tok = Parent;
- while (Tok != NULL && Tok->is(tok::comment))
- Tok = Tok->Parent;
- return Tok;
-}
-
-const AnnotatedToken *AnnotatedToken::getNextNoneComment() const {
- const AnnotatedToken *Tok = Children.empty() ? NULL : &Children[0];
- while (Tok != NULL && Tok->is(tok::comment))
- Tok = Tok->Children.empty() ? NULL : &Tok->Children[0];
- return Tok;
-}
-
-bool AnnotatedToken::closesScope() const {
- return isOneOf(tok::r_paren, tok::r_brace, tok::r_square) ||
- Type == TT_TemplateCloser;
-}
-
-bool AnnotatedToken::opensScope() const {
- return isOneOf(tok::l_paren, tok::l_brace, tok::l_square) ||
- Type == TT_TemplateOpener;
-}
-
/// \brief A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
public:
AnnotatingParser(SourceManager &SourceMgr, Lexer &Lex, AnnotatedLine &Line,
IdentifierInfo &Ident_in)
- : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First),
+ : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(Line.First),
KeywordVirtualFound(false), NameFound(false), Ident_in(Ident_in) {
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/ false));
}
if (CurrentToken == NULL)
return false;
ScopedContextCreator ContextCreator(*this, tok::less, 10);
- AnnotatedToken *Left = CurrentToken->Parent;
+ FormatToken *Left = CurrentToken->Previous;
Contexts.back().IsExpression = false;
while (CurrentToken != NULL) {
if (CurrentToken->is(tok::greater)) {
if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace,
tok::question, tok::colon))
return false;
- if (CurrentToken->Parent->isOneOf(tok::pipepipe, tok::ampamp) &&
- CurrentToken->Parent->Type != TT_PointerOrReference &&
- Line.First.isNot(tok::kw_template))
+ if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
+ CurrentToken->Previous->Type != TT_PointerOrReference &&
+ Line.First->isNot(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
bool StartsObjCMethodExpr = false;
- AnnotatedToken *Left = CurrentToken->Parent;
+ FormatToken *Left = CurrentToken->Previous;
if (CurrentToken->is(tok::caret)) {
// ^( starts a block.
Left->Type = TT_ObjCBlockLParen;
- } else if (AnnotatedToken *MaybeSel = Left->Parent) {
+ } else if (FormatToken *MaybeSel = Left->Previous) {
// @selector( starts a selector.
- if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Parent &&
- MaybeSel->Parent->is(tok::at)) {
+ if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
+ MaybeSel->Previous->is(tok::at)) {
StartsObjCMethodExpr = true;
}
}
// 'identifier' '*' 'identifier' followed by not '=' -- this
// '*' has to be a binary operator but determineStarAmpUsage() will
// categorize it as an unary operator, so set the right type here.
- if (LookForDecls && !CurrentToken->Children.empty()) {
- AnnotatedToken &Prev = *CurrentToken->Parent;
- AnnotatedToken &Next = CurrentToken->Children[0];
- if (Prev.Parent->is(tok::identifier) &&
- Prev.isOneOf(tok::star, tok::amp, tok::ampamp) &&
- CurrentToken->is(tok::identifier) && Next.isNot(tok::equal)) {
- Prev.Type = TT_BinaryOperator;
+ if (LookForDecls && CurrentToken->Next) {
+ FormatToken *Prev = CurrentToken->Previous;
+ FormatToken *Next = CurrentToken->Next;
+ if (Prev->Previous->is(tok::identifier) &&
+ Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
+ CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
+ Prev->Type = TT_BinaryOperator;
LookForDecls = false;
}
}
if (CurrentToken->is(tok::r_paren)) {
- if (MightBeFunctionType && !CurrentToken->Children.empty() &&
- CurrentToken->Children[0].isOneOf(tok::l_paren, tok::l_square))
+ if (MightBeFunctionType && CurrentToken->Next &&
+ CurrentToken->Next->isOneOf(tok::l_paren, tok::l_square))
Left->Type = TT_FunctionTypeLParen;
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
}
if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
return false;
- if (CurrentToken->Parent->Type == TT_PointerOrReference &&
- CurrentToken->Parent->Parent->isOneOf(tok::l_paren, tok::coloncolon))
+ if (CurrentToken->Previous->Type == TT_PointerOrReference &&
+ CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
+ tok::coloncolon))
MightBeFunctionType = true;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
// A '[' could be an index subscript (after an indentifier or after
// ')' or ']'), it could be the start of an Objective-C method
// expression, or it could the the start of an Objective-C array literal.
- AnnotatedToken *Left = CurrentToken->Parent;
- AnnotatedToken *Parent = Left->getPreviousNoneComment();
+ FormatToken *Left = CurrentToken->Previous;
+ FormatToken *Parent = Left->getPreviousNoneComment();
bool StartsObjCMethodExpr =
Contexts.back().CanBeExpression &&
(!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
tok::kw_return, tok::kw_throw) ||
Parent->isUnaryOperator() || Parent->Type == TT_ObjCForIn ||
Parent->Type == TT_CastRParen ||
- getBinOpPrecedence(Parent->FormatTok->Tok.getKind(), true, true) >
- prec::Unknown);
+ getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown);
ScopedContextCreator ContextCreator(*this, tok::l_square, 10);
Contexts.back().IsExpression = true;
bool StartsObjCArrayLiteral = Parent && Parent->is(tok::at);
while (CurrentToken != NULL) {
if (CurrentToken->is(tok::r_square)) {
- if (!CurrentToken->Children.empty() &&
- CurrentToken->Children[0].is(tok::l_paren)) {
+ if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren)) {
// An ObjC method call is rarely followed by an open parenthesis.
// FIXME: Do we incorrectly label ":" with this?
StartsObjCMethodExpr = false;
bool parseBrace() {
if (CurrentToken != NULL) {
ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
- AnnotatedToken *Left = CurrentToken->Parent;
+ FormatToken *Left = CurrentToken->Previous;
- AnnotatedToken *Parent = Left->getPreviousNoneComment();
+ FormatToken *Parent = Left->getPreviousNoneComment();
bool StartsObjCDictLiteral = Parent && Parent->is(tok::at);
if (StartsObjCDictLiteral) {
Contexts.back().ColonIsObjCDictLiteral = true;
return true;
}
- void updateParameterCount(AnnotatedToken *Left, AnnotatedToken *Current) {
+ void updateParameterCount(FormatToken *Left, FormatToken *Current) {
if (Current->is(tok::comma))
++Left->ParameterCount;
else if (Left->ParameterCount == 0 && Current->isNot(tok::comment))
if (!parseAngle())
return false;
if (CurrentToken != NULL)
- CurrentToken->Parent->ClosesTemplateDeclaration = true;
+ CurrentToken->Previous->ClosesTemplateDeclaration = true;
return true;
}
return false;
}
bool consumeToken() {
- AnnotatedToken *Tok = CurrentToken;
+ FormatToken *Tok = CurrentToken;
next();
- switch (Tok->FormatTok->Tok.getKind()) {
+ switch (Tok->Tok.getKind()) {
case tok::plus:
case tok::minus:
- if (Tok->Parent == NULL && Line.MustBeDeclaration)
+ if (Tok->Previous == NULL && Line.MustBeDeclaration)
Tok->Type = TT_ObjCMethodSpecifier;
break;
case tok::colon:
- if (Tok->Parent == NULL)
+ if (Tok->Previous == NULL)
return false;
// Colons from ?: are handled in parseConditional().
- if (Tok->Parent->is(tok::r_paren) && Contexts.size() == 1) {
+ if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1) {
Tok->Type = TT_CtorInitializerColon;
} else if (Contexts.back().ColonIsObjCDictLiteral) {
Tok->Type = TT_ObjCDictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
- Line.First.Type == TT_ObjCMethodSpecifier) {
+ Line.First->Type == TT_ObjCMethodSpecifier) {
Tok->Type = TT_ObjCMethodExpr;
- Tok->Parent->Type = TT_ObjCSelectorName;
- if (Tok->Parent->FormatTok->TokenLength >
+ Tok->Previous->Type = TT_ObjCSelectorName;
+ if (Tok->Previous->TokenLength >
Contexts.back().LongestObjCSelectorName)
- Contexts.back().LongestObjCSelectorName =
- Tok->Parent->FormatTok->TokenLength;
+ Contexts.back().LongestObjCSelectorName = Tok->Previous->TokenLength;
if (Contexts.back().FirstObjCSelectorName == NULL)
- Contexts.back().FirstObjCSelectorName = Tok->Parent;
+ Contexts.back().FirstObjCSelectorName = Tok->Previous;
} else if (Contexts.back().ColonIsForRangeExpr) {
Tok->Type = TT_RangeBasedForLoopColon;
} else if (Contexts.size() == 1) {
return false;
case tok::r_brace:
// Lines can start with '}'.
- if (Tok->Parent != NULL)
+ if (Tok->Previous != NULL)
return false;
break;
case tok::greater:
}
if (CurrentToken) {
CurrentToken->Type = TT_OverloadedOperatorLParen;
- if (CurrentToken->Parent->Type == TT_BinaryOperator)
- CurrentToken->Parent->Type = TT_OverloadedOperator;
+ if (CurrentToken->Previous->Type == TT_BinaryOperator)
+ CurrentToken->Previous->Type = TT_OverloadedOperator;
}
break;
case tok::question:
parseTemplateDeclaration();
break;
case tok::identifier:
- if (Line.First.is(tok::kw_for) &&
- Tok->FormatTok->Tok.getIdentifierInfo() == &Ident_in)
+ if (Line.First->is(tok::kw_for) &&
+ Tok->Tok.getIdentifierInfo() == &Ident_in)
Tok->Type = TT_ObjCForIn;
break;
case tok::comma:
if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
next();
while (CurrentToken != NULL) {
- if (CurrentToken->isNot(tok::comment) ||
- !CurrentToken->Children.empty())
+ if (CurrentToken->isNot(tok::comment) || CurrentToken->Next)
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
return;
// Hashes in the middle of a line can lead to any strange token
// sequence.
- if (CurrentToken->FormatTok->Tok.getIdentifierInfo() == NULL)
+ if (CurrentToken->Tok.getIdentifierInfo() == NULL)
return;
- switch (
- CurrentToken->FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
+ switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
case tok::pp_import:
parseIncludeDirective();
public:
LineType parseLine() {
int PeriodsAndArrows = 0;
- AnnotatedToken *LastPeriodOrArrow = NULL;
+ FormatToken *LastPeriodOrArrow = NULL;
bool CanBeBuilderTypeStmt = true;
if (CurrentToken->is(tok::hash)) {
parsePreprocessorDirective();
++PeriodsAndArrows;
LastPeriodOrArrow = CurrentToken;
}
- AnnotatedToken *TheToken = CurrentToken;
+ FormatToken *TheToken = CurrentToken;
if (!consumeToken())
return LT_Invalid;
- if (getPrecedence(*TheToken) > prec::Assignment &&
+ if (TheToken->getPrecedence() > prec::Assignment &&
TheToken->Type == TT_BinaryOperator)
CanBeBuilderTypeStmt = false;
}
return LT_BuilderTypeCall;
}
- if (Line.First.Type == TT_ObjCMethodSpecifier) {
+ if (Line.First->Type == TT_ObjCMethodSpecifier) {
if (Contexts.back().FirstObjCSelectorName != NULL)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
CurrentToken->BindingStrength = Contexts.back().BindingStrength;
}
- if (CurrentToken != NULL && !CurrentToken->Children.empty())
- CurrentToken = &CurrentToken->Children[0];
- else
- CurrentToken = NULL;
+ if (CurrentToken != NULL)
+ CurrentToken = CurrentToken->Next;
// Reset token type in case we have already looked at it and then recovered
// from an error (e.g. failure to find the matching >).
bool ColonIsForRangeExpr;
bool ColonIsObjCDictLiteral;
bool ColonIsObjCMethodExpr;
- AnnotatedToken *FirstObjCSelectorName;
- AnnotatedToken *FirstStartOfName;
+ FormatToken *FirstObjCSelectorName;
+ FormatToken *FirstStartOfName;
bool IsExpression;
bool CanBeExpression;
};
~ScopedContextCreator() { P.Contexts.pop_back(); }
};
- void determineTokenType(AnnotatedToken &Current) {
- if (getPrecedence(Current) == prec::Assignment &&
- (!Current.Parent || Current.Parent->isNot(tok::kw_operator))) {
+ void determineTokenType(FormatToken &Current) {
+ if (Current.getPrecedence() == prec::Assignment &&
+ (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
Contexts.back().IsExpression = true;
- for (AnnotatedToken *Previous = Current.Parent;
+ for (FormatToken *Previous = Current.Previous;
Previous && Previous->isNot(tok::comma);
- Previous = Previous->Parent) {
+ Previous = Previous->Previous) {
if (Previous->is(tok::r_square))
Previous = Previous->MatchingParen;
if (Previous->Type == TT_BinaryOperator &&
} else if (Current.isOneOf(tok::kw_return, tok::kw_throw) ||
(Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
!Line.InPPDirective &&
- (!Current.Parent || Current.Parent->isNot(tok::kw_for)))) {
+ (!Current.Previous || Current.Previous->isNot(tok::kw_for)))) {
Contexts.back().IsExpression = true;
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
- for (AnnotatedToken *Previous = Current.Parent;
+ for (FormatToken *Previous = Current.Previous;
Previous && Previous->isOneOf(tok::star, tok::amp);
- Previous = Previous->Parent)
+ Previous = Previous->Previous)
Previous->Type = TT_PointerOrReference;
- } else if (Current.Parent &&
- Current.Parent->Type == TT_CtorInitializerColon) {
+ } else if (Current.Previous &&
+ Current.Previous->Type == TT_CtorInitializerColon) {
Contexts.back().IsExpression = true;
} else if (Current.is(tok::kw_new)) {
Contexts.back().CanBeExpression = false;
}
if (Current.Type == TT_Unknown) {
- if (Current.Parent && Current.is(tok::identifier) &&
- ((Current.Parent->is(tok::identifier) &&
- Current.Parent->FormatTok->Tok.getIdentifierInfo()
- ->getPPKeywordID() ==
+ if (Current.Previous && Current.is(tok::identifier) &&
+ ((Current.Previous->is(tok::identifier) &&
+ Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_not_keyword) ||
- isSimpleTypeSpecifier(*Current.Parent) ||
- Current.Parent->Type == TT_PointerOrReference ||
- Current.Parent->Type == TT_TemplateCloser)) {
+ isSimpleTypeSpecifier(*Current.Previous) ||
+ Current.Previous->Type == TT_PointerOrReference ||
+ Current.Previous->Type == TT_TemplateCloser)) {
Contexts.back().FirstStartOfName = &Current;
Current.Type = TT_StartOfName;
NameFound = true;
} else if (Current.isBinaryOperator()) {
Current.Type = TT_BinaryOperator;
} else if (Current.is(tok::comment)) {
- std::string Data(Lexer::getSpelling(Current.FormatTok->Tok, SourceMgr,
- Lex.getLangOpts()));
+ std::string Data(
+ Lexer::getSpelling(Current.Tok, SourceMgr, Lex.getLangOpts()));
if (StringRef(Data).startswith("//"))
Current.Type = TT_LineComment;
else
Current.Type = TT_BlockComment;
} else if (Current.is(tok::r_paren)) {
- bool ParensNotExpr =
- !Current.Parent || Current.Parent->Type == TT_PointerOrReference ||
- Current.Parent->Type == TT_TemplateCloser;
+ bool ParensNotExpr = !Current.Previous ||
+ Current.Previous->Type == TT_PointerOrReference ||
+ Current.Previous->Type == TT_TemplateCloser;
bool ParensCouldEndDecl =
- !Current.Children.empty() &&
- Current.Children[0].isOneOf(tok::equal, tok::semi, tok::l_brace);
+ Current.Next &&
+ Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
bool IsSizeOfOrAlignOf =
- Current.MatchingParen && Current.MatchingParen->Parent &&
- Current.MatchingParen->Parent->isOneOf(tok::kw_sizeof,
- tok::kw_alignof);
+ Current.MatchingParen && Current.MatchingParen->Previous &&
+ Current.MatchingParen->Previous->isOneOf(tok::kw_sizeof,
+ tok::kw_alignof);
if (ParensNotExpr && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
Contexts.back().IsExpression)
// FIXME: We need to get smarter and understand more cases of casts.
Current.Type = TT_CastRParen;
- } else if (Current.is(tok::at) && Current.Children.size()) {
- switch (Current.Children[0].FormatTok->Tok.getObjCKeywordID()) {
+ } else if (Current.is(tok::at) && Current.Next) {
+ switch (Current.Next->Tok.getObjCKeywordID()) {
case tok::objc_interface:
case tok::objc_implementation:
case tok::objc_protocol:
break;
}
} else if (Current.is(tok::period)) {
- AnnotatedToken *PreviousNoComment= Current.getPreviousNoneComment();
+ FormatToken *PreviousNoComment = Current.getPreviousNoneComment();
if (PreviousNoComment &&
PreviousNoComment->isOneOf(tok::comma, tok::l_brace))
Current.Type = TT_DesignatedInitializerPeriod;
}
/// \brief Return the type of the given token assuming it is * or &.
- TokenType determineStarAmpUsage(const AnnotatedToken &Tok,
- bool IsExpression) {
- const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment();
+ TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) {
+ const FormatToken *PrevToken = Tok.getPreviousNoneComment();
if (PrevToken == NULL)
return TT_UnaryOperator;
- const AnnotatedToken *NextToken = Tok.getNextNoneComment();
+ const FormatToken *NextToken = Tok.getNextNoneComment();
if (NextToken == NULL)
return TT_Unknown;
if (NextToken->is(tok::l_square))
return TT_PointerOrReference;
- if (PrevToken->FormatTok->Tok.isLiteral() ||
+ if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square) ||
- NextToken->FormatTok->Tok.isLiteral() || NextToken->isUnaryOperator())
+ NextToken->Tok.isLiteral() || NextToken->isUnaryOperator())
return TT_BinaryOperator;
// It is very unlikely that we are going to find a pointer or reference type
return TT_PointerOrReference;
}
- TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok) {
- const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment();
+ TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
+ const FormatToken *PrevToken = Tok.getPreviousNoneComment();
if (PrevToken == NULL)
return TT_UnaryOperator;
}
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
- TokenType determineIncrementUsage(const AnnotatedToken &Tok) {
- const AnnotatedToken *PrevToken = Tok.getPreviousNoneComment();
+ TokenType determineIncrementUsage(const FormatToken &Tok) {
+ const FormatToken *PrevToken = Tok.getPreviousNoneComment();
if (PrevToken == NULL)
return TT_UnaryOperator;
if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
// FIXME: This is copy&pasted from Sema. Put it in a common place and remove
// duplication.
/// \brief Determine whether the token kind starts a simple-type-specifier.
- bool isSimpleTypeSpecifier(const AnnotatedToken &Tok) const {
- switch (Tok.FormatTok->Tok.getKind()) {
+ bool isSimpleTypeSpecifier(const FormatToken &Tok) const {
+ switch (Tok.Tok.getKind()) {
case tok::kw_short:
case tok::kw_long:
case tok::kw___int64:
SourceManager &SourceMgr;
Lexer &Lex;
AnnotatedLine &Line;
- AnnotatedToken *CurrentToken;
+ FormatToken *CurrentToken;
bool KeywordVirtualFound;
bool NameFound;
IdentifierInfo &Ident_in;
/// operator precedence.
class ExpressionParser {
public:
- ExpressionParser(AnnotatedLine &Line) : Current(&Line.First) {}
+ ExpressionParser(AnnotatedLine &Line) : Current(Line.First) {}
/// \brief Parse expressions with the given operatore precedence.
void parse(int Precedence = 0) {
next();
}
- AnnotatedToken *Start = Current;
+ FormatToken *Start = Current;
bool OperatorFound = false;
while (Current) {
else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon)
CurrentPrecedence = 1;
else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
- CurrentPrecedence = 1 + (int) getPrecedence(*Current);
+ CurrentPrecedence = 1 + (int) Current->getPrecedence();
}
// At the end of the line or when an operator with higher precedence is
if (OperatorFound) {
Start->FakeLParens.push_back(prec::Level(Precedence - 1));
if (Current)
- ++Current->Parent->FakeRParens;
+ ++Current->Previous->FakeRParens;
}
return;
}
private:
void next() {
if (Current != NULL)
- Current = Current->Children.empty() ? NULL : &Current->Children[0];
+ Current = Current->Next;
}
- AnnotatedToken *Current;
+ FormatToken *Current;
};
void TokenAnnotator::annotate(AnnotatedLine &Line) {
ExpressionParser ExprParser(Line);
ExprParser.parse();
- if (Line.First.Type == TT_ObjCMethodSpecifier)
+ if (Line.First->Type == TT_ObjCMethodSpecifier)
Line.Type = LT_ObjCMethodDecl;
- else if (Line.First.Type == TT_ObjCDecl)
+ else if (Line.First->Type == TT_ObjCDecl)
Line.Type = LT_ObjCDecl;
- else if (Line.First.Type == TT_ObjCProperty)
+ else if (Line.First->Type == TT_ObjCProperty)
Line.Type = LT_ObjCProperty;
- Line.First.SpacesRequiredBefore = 1;
- Line.First.MustBreakBefore = Line.First.FormatTok->MustBreakBefore;
- Line.First.CanBreakBefore = Line.First.MustBreakBefore;
+ Line.First->SpacesRequiredBefore = 1;
+ Line.First->CanBreakBefore = Line.First->MustBreakBefore;
}
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
- if (Line.First.Children.empty())
+ Line.First->TotalLength = Line.First->TokenLength;
+ if (!Line.First->Next)
return;
- AnnotatedToken *Current = &Line.First.Children[0];
+ FormatToken *Current = Line.First->Next;
while (Current != NULL) {
if (Current->Type == TT_LineComment)
Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
Current->SpacesRequiredBefore =
spaceRequiredBefore(Line, *Current) ? 1 : 0;
- if (Current->FormatTok->MustBreakBefore) {
- Current->MustBreakBefore = true;
+ if (Current->MustBreakBefore) {
} else if (Current->Type == TT_LineComment) {
- Current->MustBreakBefore = Current->FormatTok->NewlinesBefore > 0;
- } else if (Current->Parent->isTrailingComment() ||
+ Current->MustBreakBefore = Current->NewlinesBefore > 0;
+ } else if (Current->Previous->isTrailingComment() ||
(Current->is(tok::string_literal) &&
- Current->Parent->is(tok::string_literal))) {
+ Current->Previous->is(tok::string_literal))) {
Current->MustBreakBefore = true;
- } else if (Current->is(tok::lessless) && !Current->Children.empty() &&
- Current->Parent->is(tok::string_literal) &&
- Current->Children[0].is(tok::string_literal)) {
+ } else if (Current->is(tok::lessless) && Current->Next &&
+ Current->Previous->is(tok::string_literal) &&
+ Current->Next->is(tok::string_literal)) {
Current->MustBreakBefore = true;
- } else if (Current->Parent->ClosesTemplateDeclaration &&
+ } else if (Current->Previous->ClosesTemplateDeclaration &&
Style.AlwaysBreakTemplateDeclarations) {
Current->MustBreakBefore = true;
} else {
Current->CanBreakBefore =
Current->MustBreakBefore || canBreakBefore(Line, *Current);
if (Current->MustBreakBefore)
- Current->TotalLength = Current->Parent->TotalLength + Style.ColumnLimit;
+ Current->TotalLength = Current->Previous->TotalLength + Style.ColumnLimit;
else
Current->TotalLength =
- Current->Parent->TotalLength + Current->FormatTok->TokenLength +
+ Current->Previous->TotalLength + Current->TokenLength +
Current->SpacesRequiredBefore;
// FIXME: Only calculate this if CanBreakBefore is true once static
// initializers etc. are sorted out.
Current->SplitPenalty =
20 * Current->BindingStrength + splitPenalty(Line, *Current);
- Current = Current->Children.empty() ? NULL : &Current->Children[0];
+ Current = Current->Next;
}
calculateUnbreakableTailLengths(Line);
void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) {
unsigned UnbreakableTailLength = 0;
- AnnotatedToken *Current = Line.Last;
+ FormatToken *Current = Line.Last;
while (Current != NULL) {
Current->UnbreakableTailLength = UnbreakableTailLength;
if (Current->CanBreakBefore ||
UnbreakableTailLength = 0;
} else {
UnbreakableTailLength +=
- Current->FormatTok->TokenLength + Current->SpacesRequiredBefore;
+ Current->TokenLength + Current->SpacesRequiredBefore;
}
- Current = Current->Parent;
+ Current = Current->Previous;
}
}
unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
- const AnnotatedToken &Tok) {
- const AnnotatedToken &Left = *Tok.Parent;
- const AnnotatedToken &Right = Tok;
+ const FormatToken &Tok) {
+ const FormatToken &Left = *Tok.Previous;
+ const FormatToken &Right = Tok;
if (Left.is(tok::semi))
return 0;
return 1;
if (Right.Type == TT_StartOfName) {
- if (Line.First.is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
+ if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
else if (Line.MightBeFunctionDecl && Right.BindingStrength == 1)
// FIXME: Clean up hack of using BindingStrength to find top-level names.
return 150;
// In for-loops, prefer breaking at ',' and ';'.
- if (Line.First.is(tok::kw_for) && Left.is(tok::equal))
+ if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
return 4;
// In Objective-C method expressions, prefer breaking before "param:" over
if (Right.is(tok::lessless)) {
if (Left.is(tok::string_literal)) {
- StringRef Content = StringRef(Left.FormatTok->Tok.getLiteralData(),
- Left.FormatTok->TokenLength);
+ StringRef Content =
+ StringRef(Left.Tok.getLiteralData(), Left.TokenLength);
Content = Content.drop_back(1).drop_front(1).trim();
if (Content.size() > 1 &&
(Content.back() == ':' || Content.back() == '='))
}
if (Left.Type == TT_ConditionalExpr)
return prec::Conditional;
- prec::Level Level = getPrecedence(Left);
+ prec::Level Level = Left.getPrecedence();
if (Level != prec::Unknown)
return Level;
}
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
- const AnnotatedToken &Left,
- const AnnotatedToken &Right) {
+ const FormatToken &Left,
+ const FormatToken &Right) {
if (Right.is(tok::hashhash))
return Left.is(tok::hash);
if (Left.isOneOf(tok::hashhash, tok::hash))
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
return false;
if (Right.Type == TT_PointerOrReference)
- return Left.FormatTok->Tok.isLiteral() ||
+ return Left.Tok.isLiteral() ||
((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
!Style.PointerBindsToType);
if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
(Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
return true;
if (Left.Type == TT_PointerOrReference)
- return Right.FormatTok->Tok.isLiteral() ||
+ return Right.Tok.isLiteral() ||
((Right.Type != TT_PointerOrReference) &&
Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
- Left.Parent &&
- !Left.Parent->isOneOf(tok::l_paren, tok::coloncolon));
+ Left.Previous &&
+ !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
if (Left.is(tok::l_square))
tok::kw_return, tok::kw_catch, tok::kw_new,
tok::kw_delete, tok::semi);
}
- if (Left.is(tok::at) &&
- Right.FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword)
+ 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 "{}".
}
bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
- const AnnotatedToken &Tok) {
- if (Tok.FormatTok->Tok.getIdentifierInfo() &&
- Tok.Parent->FormatTok->Tok.getIdentifierInfo())
+ const FormatToken &Tok) {
+ if (Tok.Tok.getIdentifierInfo() && Tok.Previous->Tok.getIdentifierInfo())
return true; // Never ever merge two identifiers.
if (Line.Type == LT_ObjCMethodDecl) {
- if (Tok.Parent->Type == TT_ObjCMethodSpecifier)
+ if (Tok.Previous->Type == TT_ObjCMethodSpecifier)
return true;
- if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier))
+ if (Tok.Previous->is(tok::r_paren) && Tok.is(tok::identifier))
// Don't space between ')' and <id>
return false;
}
if (Line.Type == LT_ObjCProperty &&
- (Tok.is(tok::equal) || Tok.Parent->is(tok::equal)))
+ (Tok.is(tok::equal) || Tok.Previous->is(tok::equal)))
return false;
- if (Tok.Parent->is(tok::comma))
+ if (Tok.Previous->is(tok::comma))
return true;
if (Tok.is(tok::comma))
return false;
if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
return true;
- if (Tok.Parent->FormatTok->Tok.is(tok::kw_operator))
+ if (Tok.Previous->Tok.is(tok::kw_operator))
return false;
if (Tok.Type == TT_OverloadedOperatorLParen)
return false;
if (Tok.is(tok::colon))
- return !Line.First.isOneOf(tok::kw_case, tok::kw_default) &&
+ return !Line.First->isOneOf(tok::kw_case, tok::kw_default) &&
Tok.getNextNoneComment() != NULL && Tok.Type != TT_ObjCMethodExpr;
- if (Tok.Parent->Type == TT_UnaryOperator || Tok.Parent->Type == TT_CastRParen)
+ if (Tok.Previous->Type == TT_UnaryOperator ||
+ Tok.Previous->Type == TT_CastRParen)
return false;
- if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) {
+ if (Tok.Previous->is(tok::greater) && Tok.is(tok::greater)) {
return Tok.Type == TT_TemplateCloser &&
- Tok.Parent->Type == TT_TemplateCloser &&
+ Tok.Previous->Type == TT_TemplateCloser &&
Style.Standard != FormatStyle::LS_Cpp11;
}
if (Tok.isOneOf(tok::arrowstar, tok::periodstar) ||
- Tok.Parent->isOneOf(tok::arrowstar, tok::periodstar))
+ Tok.Previous->isOneOf(tok::arrowstar, tok::periodstar))
return false;
- if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator)
+ if (Tok.Type == TT_BinaryOperator || Tok.Previous->Type == TT_BinaryOperator)
return true;
- if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
+ if (Tok.Previous->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
return false;
- if (Tok.is(tok::less) && Line.First.is(tok::hash))
+ if (Tok.is(tok::less) && Line.First->is(tok::hash))
return true;
if (Tok.Type == TT_TrailingUnaryOperator)
return false;
- return spaceRequiredBetween(Line, *Tok.Parent, Tok);
+ return spaceRequiredBetween(Line, *Tok.Previous, Tok);
}
bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
- const AnnotatedToken &Right) {
- const AnnotatedToken &Left = *Right.Parent;
+ const FormatToken &Right) {
+ const FormatToken &Left = *Right.Previous;
if (Right.Type == TT_StartOfName)
return true;
if (Right.is(tok::colon) &&
return false;
if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
return false;
- if (Left.is(tok::l_paren) && Right.is(tok::l_paren) && Left.Parent &&
- Left.Parent->is(tok::kw___attribute))
+ if (Left.is(tok::l_paren) && Right.is(tok::l_paren) && Left.Previous &&
+ Left.Previous->is(tok::kw___attribute))
return false;
if (Right.Type == TT_LineComment)
// Allow breaking after a trailing 'const', e.g. after a method declaration,
// unless it is follow by ';', '{' or '='.
- if (Left.is(tok::kw_const) && Left.Parent != NULL &&
- Left.Parent->is(tok::r_paren))
+ if (Left.is(tok::kw_const) && Left.Previous != NULL &&
+ Left.Previous->is(tok::r_paren))
return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal);
if (Right.is(tok::kw___attribute))
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
llvm::errs() << "AnnotatedTokens:\n";
- const AnnotatedToken *Tok = &Line.First;
+ const FormatToken *Tok = Line.First;
while (Tok) {
- llvm::errs()
- << " M=" << Tok->MustBreakBefore << " C=" << Tok->CanBreakBefore
- << " T=" << Tok->Type << " S=" << Tok->SpacesRequiredBefore
- << " P=" << Tok->SplitPenalty
- << " Name=" << Tok->FormatTok->Tok.getName() << " FakeLParens=";
+ llvm::errs() << " M=" << Tok->MustBreakBefore
+ << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type << " S="
+ << Tok->SpacesRequiredBefore << " P=" << Tok->SplitPenalty
+ << " Name=" << Tok->Tok.getName() << " FakeLParens=";
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
- Tok = Tok->Children.empty() ? NULL : &Tok->Children[0];
+ Tok = Tok->Next;
}
llvm::errs() << "----\n";
}
#define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
#include "UnwrappedLineParser.h"
-#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Format/Format.h"
#include <string>
namespace format {
-enum TokenType {
- TT_BinaryOperator,
- TT_BlockComment,
- TT_CastRParen,
- TT_ConditionalExpr,
- TT_CtorInitializerColon,
- TT_DesignatedInitializerPeriod,
- TT_ImplicitStringLiteral,
- TT_InlineASMColon,
- TT_InheritanceColon,
- TT_FunctionTypeLParen,
- TT_LineComment,
- TT_ObjCArrayLiteral,
- TT_ObjCBlockLParen,
- TT_ObjCDecl,
- TT_ObjCDictLiteral,
- TT_ObjCForIn,
- TT_ObjCMethodExpr,
- TT_ObjCMethodSpecifier,
- TT_ObjCProperty,
- TT_ObjCSelectorName,
- TT_OverloadedOperator,
- TT_OverloadedOperatorLParen,
- TT_PointerOrReference,
- TT_PureVirtualSpecifier,
- TT_RangeBasedForLoopColon,
- TT_StartOfName,
- TT_TemplateCloser,
- TT_TemplateOpener,
- TT_TrailingUnaryOperator,
- TT_UnaryOperator,
- TT_Unknown
-};
-
enum LineType {
LT_Invalid,
LT_Other,
LT_ObjCProperty // An @property line.
};
-class AnnotatedToken {
-public:
- explicit AnnotatedToken(FormatToken *FormatTok)
- : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
- CanBreakBefore(false), MustBreakBefore(false),
- ClosesTemplateDeclaration(false), MatchingParen(NULL),
- ParameterCount(0), TotalLength(FormatTok->TokenLength),
- UnbreakableTailLength(0), BindingStrength(0), SplitPenalty(0),
- LongestObjCSelectorName(0), Parent(NULL), FakeRParens(0),
- LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false) {}
-
- bool is(tok::TokenKind Kind) const { return FormatTok->Tok.is(Kind); }
-
- bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
- return is(K1) || is(K2);
- }
-
- bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3) const {
- return is(K1) || is(K2) || is(K3);
- }
-
- bool isOneOf(
- tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3,
- tok::TokenKind K4, tok::TokenKind K5 = tok::NUM_TOKENS,
- tok::TokenKind K6 = tok::NUM_TOKENS, tok::TokenKind K7 = tok::NUM_TOKENS,
- tok::TokenKind K8 = tok::NUM_TOKENS, tok::TokenKind K9 = tok::NUM_TOKENS,
- tok::TokenKind K10 = tok::NUM_TOKENS,
- tok::TokenKind K11 = tok::NUM_TOKENS,
- tok::TokenKind K12 = tok::NUM_TOKENS) const {
- return is(K1) || is(K2) || is(K3) || is(K4) || is(K5) || is(K6) || is(K7) ||
- is(K8) || is(K9) || is(K10) || is(K11) || is(K12);
- }
-
- bool isNot(tok::TokenKind Kind) const { return FormatTok->Tok.isNot(Kind); }
-
- bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
- return FormatTok->Tok.isObjCAtKeyword(Kind);
- }
-
- bool isAccessSpecifier(bool ColonRequired = true) const {
- return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) &&
- (!ColonRequired ||
- (!Children.empty() && Children[0].is(tok::colon)));
- }
-
- bool isObjCAccessSpecifier() const {
- return is(tok::at) && !Children.empty() &&
- (Children[0].isObjCAtKeyword(tok::objc_public) ||
- Children[0].isObjCAtKeyword(tok::objc_protected) ||
- Children[0].isObjCAtKeyword(tok::objc_package) ||
- Children[0].isObjCAtKeyword(tok::objc_private));
- }
-
- /// \brief Returns whether \p Tok is ([{ or a template opening <.
- bool opensScope() const;
- /// \brief Returns whether \p Tok is )]} or a template opening >.
- bool closesScope() const;
-
- bool isUnaryOperator() const;
- bool isBinaryOperator() const;
- bool isTrailingComment() const;
-
- FormatToken *FormatTok;
-
- TokenType Type;
-
- unsigned SpacesRequiredBefore;
- bool CanBreakBefore;
- bool MustBreakBefore;
-
- bool ClosesTemplateDeclaration;
-
- AnnotatedToken *MatchingParen;
-
- /// \brief Number of parameters, if this is "(", "[" or "<".
- ///
- /// This is initialized to 1 as we don't need to distinguish functions with
- /// 0 parameters from functions with 1 parameter. Thus, we can simply count
- /// the number of commas.
- unsigned ParameterCount;
-
- /// \brief The total length of the line up to and including this token.
- unsigned TotalLength;
-
- /// \brief The length of following tokens until the next natural split point,
- /// or the next token that can be broken.
- unsigned UnbreakableTailLength;
-
- // FIXME: Come up with a 'cleaner' concept.
- /// \brief The binding strength of a token. This is a combined value of
- /// operator precedence, parenthesis nesting, etc.
- unsigned BindingStrength;
-
- /// \brief Penalty for inserting a line break before this token.
- unsigned SplitPenalty;
-
- /// \brief If this is the first ObjC selector name in an ObjC method
- /// definition or call, this contains the length of the longest name.
- unsigned LongestObjCSelectorName;
-
- std::vector<AnnotatedToken> Children;
- AnnotatedToken *Parent;
-
- /// \brief Stores the number of required fake parentheses and the
- /// corresponding operator precedence.
- ///
- /// If multiple fake parentheses start at a token, this vector stores them in
- /// reverse order, i.e. inner fake parenthesis first.
- SmallVector<prec::Level, 4> FakeLParens;
- /// \brief Insert this many fake ) after this token for correct indentation.
- unsigned FakeRParens;
-
- /// \brief Is this the last "." or "->" in a builder-type call?
- bool LastInChainOfCalls;
-
- /// \brief Is this token part of a \c DeclStmt defining multiple variables?
- ///
- /// Only set if \c Type == \c TT_StartOfName.
- bool PartOfMultiVariableDeclStmt;
-
- /// \brief Returns the previous token ignoring comments.
- AnnotatedToken *getPreviousNoneComment() const;
-
- /// \brief Returns the next token ignoring comments.
- const AnnotatedToken *getNextNoneComment() const;
-};
-
class AnnotatedLine {
public:
AnnotatedLine(const UnwrappedLine &Line)
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
StartsDefinition(false) {
assert(!Line.Tokens.empty());
- AnnotatedToken *Current = &First;
+ FormatToken *Current = First;
for (std::list<FormatToken *>::const_iterator I = ++Line.Tokens.begin(),
E = Line.Tokens.end();
I != E; ++I) {
- Current->Children.push_back(AnnotatedToken(*I));
- Current->Children[0].Parent = Current;
- Current = &Current->Children[0];
+ Current->Next = *I;
+ (*I)->Previous = Current;
+ Current = Current->Next;
}
Last = Current;
}
- AnnotatedLine(const AnnotatedLine &Other)
- : First(Other.First), Type(Other.Type), Level(Other.Level),
- InPPDirective(Other.InPPDirective),
- MustBeDeclaration(Other.MustBeDeclaration),
- MightBeFunctionDecl(Other.MightBeFunctionDecl),
- StartsDefinition(Other.StartsDefinition) {
- Last = &First;
- while (!Last->Children.empty()) {
- Last->Children[0].Parent = Last;
- Last = &Last->Children[0];
- }
- }
- AnnotatedToken First;
- AnnotatedToken *Last;
+ FormatToken *First;
+ FormatToken *Last;
LineType Type;
unsigned Level;
bool StartsDefinition;
};
-inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
- return getBinOpPrecedence(Tok.FormatTok->Tok.getKind(), true, true);
-}
-
/// \brief Determines extra information about the tokens comprising an
/// \c UnwrappedLine.
class TokenAnnotator {
private:
/// \brief Calculate the penalty for splitting before \c Tok.
- unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
+ unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok);
- bool spaceRequiredBetween(const AnnotatedLine &Line,
- const AnnotatedToken &Left,
- const AnnotatedToken &Right);
+ bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
+ const FormatToken &Right);
- bool spaceRequiredBefore(const AnnotatedLine &Line,
- const AnnotatedToken &Tok);
+ bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
- bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
+ bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
void printDebugInfo(const AnnotatedLine &Line);
#define LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include <list>
namespace clang {
namespace format {
+enum TokenType {
+ TT_BinaryOperator,
+ TT_BlockComment,
+ TT_CastRParen,
+ TT_ConditionalExpr,
+ TT_CtorInitializerColon,
+ TT_DesignatedInitializerPeriod,
+ TT_ImplicitStringLiteral,
+ TT_InlineASMColon,
+ TT_InheritanceColon,
+ TT_FunctionTypeLParen,
+ TT_LineComment,
+ TT_ObjCArrayLiteral,
+ TT_ObjCBlockLParen,
+ TT_ObjCDecl,
+ TT_ObjCDictLiteral,
+ TT_ObjCForIn,
+ TT_ObjCMethodExpr,
+ TT_ObjCMethodSpecifier,
+ TT_ObjCProperty,
+ TT_ObjCSelectorName,
+ TT_OverloadedOperator,
+ TT_OverloadedOperatorLParen,
+ TT_PointerOrReference,
+ TT_PureVirtualSpecifier,
+ TT_RangeBasedForLoopColon,
+ TT_StartOfName,
+ TT_TemplateCloser,
+ TT_TemplateOpener,
+ TT_TrailingUnaryOperator,
+ TT_UnaryOperator,
+ TT_Unknown
+};
+
/// \brief A wrapper around a \c Token storing information about the
/// whitespace characters preceeding it.
struct FormatToken {
FormatToken()
: NewlinesBefore(0), HasUnescapedNewline(false), LastNewlineOffset(0),
- TokenLength(0), IsFirst(false), MustBreakBefore(false) {}
+ TokenLength(0), IsFirst(false), MustBreakBefore(false),
+ Type(TT_Unknown), SpacesRequiredBefore(0), CanBreakBefore(false),
+ ClosesTemplateDeclaration(false), ParameterCount(0), TotalLength(0),
+ UnbreakableTailLength(0), BindingStrength(0), SplitPenalty(0),
+ LongestObjCSelectorName(0), FakeRParens(0), LastInChainOfCalls(false),
+ PartOfMultiVariableDeclStmt(false), MatchingParen(NULL), Previous(NULL),
+ Next(NULL) {}
/// \brief The \c Token.
Token Tok;
/// escaped newlines.
StringRef TokenText;
+ TokenType Type;
+
+ unsigned SpacesRequiredBefore;
+ bool CanBreakBefore;
+
+ bool ClosesTemplateDeclaration;
+
+ /// \brief Number of parameters, if this is "(", "[" or "<".
+ ///
+ /// This is initialized to 1 as we don't need to distinguish functions with
+ /// 0 parameters from functions with 1 parameter. Thus, we can simply count
+ /// the number of commas.
+ unsigned ParameterCount;
+
+ /// \brief The total length of the line up to and including this token.
+ unsigned TotalLength;
+
+ /// \brief The length of following tokens until the next natural split point,
+ /// or the next token that can be broken.
+ unsigned UnbreakableTailLength;
+
+ // FIXME: Come up with a 'cleaner' concept.
+ /// \brief The binding strength of a token. This is a combined value of
+ /// operator precedence, parenthesis nesting, etc.
+ unsigned BindingStrength;
+
+ /// \brief Penalty for inserting a line break before this token.
+ unsigned SplitPenalty;
+
+ /// \brief If this is the first ObjC selector name in an ObjC method
+ /// definition or call, this contains the length of the longest name.
+ unsigned LongestObjCSelectorName;
+
+ /// \brief Stores the number of required fake parentheses and the
+ /// corresponding operator precedence.
+ ///
+ /// If multiple fake parentheses start at a token, this vector stores them in
+ /// reverse order, i.e. inner fake parenthesis first.
+ SmallVector<prec::Level, 4> FakeLParens;
+ /// \brief Insert this many fake ) after this token for correct indentation.
+ unsigned FakeRParens;
+
+ /// \brief Is this the last "." or "->" in a builder-type call?
+ bool LastInChainOfCalls;
+
+ /// \brief Is this token part of a \c DeclStmt defining multiple variables?
+ ///
+ /// Only set if \c Type == \c TT_StartOfName.
+ bool PartOfMultiVariableDeclStmt;
+
+ bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
+
+ bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
+ return is(K1) || is(K2);
+ }
+
+ bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3) const {
+ return is(K1) || is(K2) || is(K3);
+ }
+
+ bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3,
+ tok::TokenKind K4, tok::TokenKind K5 = tok::NUM_TOKENS,
+ tok::TokenKind K6 = tok::NUM_TOKENS,
+ tok::TokenKind K7 = tok::NUM_TOKENS,
+ tok::TokenKind K8 = tok::NUM_TOKENS,
+ tok::TokenKind K9 = tok::NUM_TOKENS,
+ tok::TokenKind K10 = tok::NUM_TOKENS,
+ tok::TokenKind K11 = tok::NUM_TOKENS,
+ tok::TokenKind K12 = tok::NUM_TOKENS) const {
+ return is(K1) || is(K2) || is(K3) || is(K4) || is(K5) || is(K6) || is(K7) ||
+ is(K8) || is(K9) || is(K10) || is(K11) || is(K12);
+ }
+
+ bool isNot(tok::TokenKind Kind) const { return Tok.isNot(Kind); }
+
+ bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
+ return Tok.isObjCAtKeyword(Kind);
+ }
+
+ bool isAccessSpecifier(bool ColonRequired = true) const {
+ return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) &&
+ (!ColonRequired || (Next && Next->is(tok::colon)));
+ }
+
+ bool isObjCAccessSpecifier() const {
+ return is(tok::at) && Next && (Next->isObjCAtKeyword(tok::objc_public) ||
+ Next->isObjCAtKeyword(tok::objc_protected) ||
+ Next->isObjCAtKeyword(tok::objc_package) ||
+ Next->isObjCAtKeyword(tok::objc_private));
+ }
+
+ /// \brief Returns whether \p Tok is ([{ or a template opening <.
+ bool opensScope() const {
+ return isOneOf(tok::l_paren, tok::l_brace, tok::l_square) ||
+ Type == TT_TemplateOpener;
+
+ }
+ /// \brief Returns whether \p Tok is )]} or a template opening >.
+ bool closesScope() const {
+ return isOneOf(tok::r_paren, tok::r_brace, tok::r_square) ||
+ Type == TT_TemplateCloser;
+ }
+
+ bool isUnaryOperator() const {
+ switch (Tok.getKind()) {
+ case tok::plus:
+ case tok::plusplus:
+ case tok::minus:
+ case tok::minusminus:
+ case tok::exclaim:
+ case tok::tilde:
+ case tok::kw_sizeof:
+ case tok::kw_alignof:
+ return true;
+ default:
+ return false;
+ }
+ }
+ bool isBinaryOperator() const {
+ // Comma is a binary operator, but does not behave as such wrt. formatting.
+ return getPrecedence() > prec::Comma;
+ }
+ bool isTrailingComment() const {
+ return is(tok::comment) && (!Next || Next->NewlinesBefore > 0);
+ }
+
+ prec::Level getPrecedence() const {
+ return getBinOpPrecedence(Tok.getKind(), true, true);
+ }
+
+ /// \brief Returns the previous token ignoring comments.
+ FormatToken *getPreviousNoneComment() const {
+ FormatToken *Tok = Previous;
+ while (Tok != NULL && Tok->is(tok::comment))
+ Tok = Tok->Previous;
+ return Tok;
+ }
+
+ /// \brief Returns the next token ignoring comments.
+ const FormatToken *getNextNoneComment() const {
+ const FormatToken *Tok = Next;
+ while (Tok != NULL && Tok->is(tok::comment))
+ Tok = Tok->Next;
+ return Tok;
+ }
+
+ FormatToken *MatchingParen;
+
+ FormatToken *Previous;
+ FormatToken *Next;
+
private:
// Disallow copying.
FormatToken(const FormatToken &);
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces) {}
-void WhitespaceManager::replaceWhitespace(const AnnotatedToken &Tok,
+void WhitespaceManager::replaceWhitespace(const FormatToken &Tok,
unsigned Newlines, unsigned Spaces,
unsigned StartOfTokenColumn,
bool InPPDirective) {
Changes.push_back(
- Change(true, Tok.FormatTok->WhitespaceRange, Spaces, StartOfTokenColumn,
- Newlines, "", "", Tok.FormatTok->Tok.getKind(),
- InPPDirective && !Tok.FormatTok->IsFirst));
+ Change(true, Tok.WhitespaceRange, Spaces, StartOfTokenColumn, Newlines,
+ "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
}
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
/// \brief Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
- void replaceWhitespace(const AnnotatedToken &Tok, unsigned Newlines,
+ void replaceWhitespace(const FormatToken &Tok, unsigned Newlines,
unsigned Spaces, unsigned StartOfTokenColumn,
bool InPPDirective = false);