///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
-#define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
+#ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
+#define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
#include "UnwrappedLineParser.h"
-#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Format/Format.h"
#include <string>
namespace clang {
-class Lexer;
class SourceManager;
namespace format {
-enum TokenType {
- TT_BinaryOperator,
- TT_BlockComment,
- TT_CastRParen,
- TT_ConditionalExpr,
- TT_CtorInitializerColon,
- TT_ImplicitStringLiteral,
- TT_LineComment,
- TT_ObjCBlockLParen,
- TT_ObjCDecl,
- TT_ObjCMethodSpecifier,
- TT_ObjCMethodExpr,
- TT_ObjCProperty,
- TT_OverloadedOperator,
- 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_BuilderTypeCall,
LT_PreprocessorDirective,
LT_VirtualFunctionDecl,
LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
LT_ObjCProperty // An @property line.
};
-class AnnotatedToken {
-public:
- explicit AnnotatedToken(const FormatToken &FormatTok)
- : FormatTok(FormatTok), Type(TT_Unknown), SpaceRequiredBefore(false),
- CanBreakBefore(false), MustBreakBefore(false),
- ClosesTemplateDeclaration(false), MatchingParen(NULL),
- ParameterCount(1), 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;
- 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 Penalty for inserting a line break before this token.
- unsigned SplitPenalty;
-
- std::vector<AnnotatedToken> Children;
- AnnotatedToken *Parent;
-
- const AnnotatedToken *getPreviousNoneComment() const {
- AnnotatedToken *Tok = Parent;
- while (Tok != NULL && Tok->is(tok::comment))
- Tok = Tok->Parent;
- return Tok;
- }
-};
-
class AnnotatedLine {
public:
AnnotatedLine(const UnwrappedLine &Line)
- : First(Line.Tokens.front()), Level(Line.Level),
+ : First(Line.Tokens.front().Tok), Level(Line.Level),
InPPDirective(Line.InPPDirective),
- MustBeDeclaration(Line.MustBeDeclaration) {
+ MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
+ Affected(false), LeadingEmptyLinesAffected(false),
+ ChildrenAffected(false) {
assert(!Line.Tokens.empty());
- AnnotatedToken *Current = &First;
- for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
- E = Line.Tokens.end();
+
+ // Calculate Next and Previous for all tokens. Note that we must overwrite
+ // Next and Previous for every token, as previous formatting runs might have
+ // left them in a different state.
+ First->Previous = nullptr;
+ FormatToken *Current = First;
+ for (std::list<UnwrappedLineNode>::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];
+ const UnwrappedLineNode &Node = *I;
+ Current->Next = I->Tok;
+ I->Tok->Previous = Current;
+ Current = Current->Next;
+ Current->Children.clear();
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator
+ I = Node.Children.begin(),
+ E = Node.Children.end();
+ I != E; ++I) {
+ Children.push_back(new AnnotatedLine(*I));
+ Current->Children.push_back(Children.back());
+ }
}
Last = Current;
+ Last->Next = nullptr;
}
- AnnotatedLine(const AnnotatedLine &Other)
- : First(Other.First), Type(Other.Type), Level(Other.Level),
- InPPDirective(Other.InPPDirective),
- MustBeDeclaration(Other.MustBeDeclaration) {
- Last = &First;
- while (!Last->Children.empty()) {
- Last->Children[0].Parent = Last;
- Last = &Last->Children[0];
+
+ ~AnnotatedLine() {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i) {
+ delete Children[i];
}
}
- AnnotatedToken First;
- AnnotatedToken *Last;
+ FormatToken *First;
+ FormatToken *Last;
+
+ SmallVector<AnnotatedLine *, 0> Children;
LineType Type;
unsigned Level;
bool InPPDirective;
bool MustBeDeclaration;
-};
+ bool MightBeFunctionDecl;
-inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
- return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
-}
+ /// \c True if this line should be formatted, i.e. intersects directly or
+ /// indirectly with one of the input ranges.
+ bool Affected;
+
+ /// \c True if the leading empty lines of this line intersect with one of the
+ /// input ranges.
+ bool LeadingEmptyLinesAffected;
+
+ /// \c True if a one of this line's children intersects with an input range.
+ bool ChildrenAffected;
+
+private:
+ // Disallow copying.
+ AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
+ void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
+};
/// \brief Determines extra information about the tokens comprising an
/// \c UnwrappedLine.
class TokenAnnotator {
public:
- TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
- AnnotatedLine &Line)
- : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Line(Line) {
- }
+ TokenAnnotator(const FormatStyle &Style, IdentifierInfo &Ident_in)
+ : Style(Style), Ident_in(Ident_in) {}
+
+ /// \brief Adapts the indent levels of comment lines to the indent of the
+ /// subsequent line.
+ // FIXME: Can/should this be done in the UnwrappedLineParser?
+ void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
- void annotate();
- void calculateExtraInformation(AnnotatedToken &Current);
+ void annotate(AnnotatedLine &Line);
+ void calculateFormattingInformation(AnnotatedLine &Line);
private:
/// \brief Calculate the penalty for splitting before \c Tok.
- unsigned splitPenalty(const AnnotatedToken &Tok);
+ unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
+ bool InFunctionDecl);
- void determineTokenTypes(AnnotatedToken &Current, bool IsExpression,
- bool LookForFunctionName);
+ bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
+ const FormatToken &Right);
- /// \brief Starting from \p Current, this searches backwards for an
- /// identifier which could be the start of a function name and marks it.
- void findFunctionName(AnnotatedToken *Current);
+ bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
- /// \brief Returns the previous token ignoring comments.
- const AnnotatedToken *getPreviousToken(const AnnotatedToken &Tok) {
- const AnnotatedToken *PrevToken = Tok.Parent;
- while (PrevToken != NULL && PrevToken->is(tok::comment))
- PrevToken = PrevToken->Parent;
- return PrevToken;
- }
+ bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
- /// \brief Returns the next token ignoring comments.
- const AnnotatedToken *getNextToken(const AnnotatedToken &Tok) {
- if (Tok.Children.empty())
- return NULL;
- const AnnotatedToken *NextToken = &Tok.Children[0];
- while (NextToken->is(tok::comment)) {
- if (NextToken->Children.empty())
- return NULL;
- NextToken = &NextToken->Children[0];
- }
- return NextToken;
- }
+ bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
- /// \brief Return the type of the given token assuming it is * or &.
- TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsExpression);
+ void printDebugInfo(const AnnotatedLine &Line);
- TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok);
+ void calculateUnbreakableTailLengths(AnnotatedLine &Line);
- /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
- TokenType determineIncrementUsage(const AnnotatedToken &Tok);
+ const FormatStyle &Style;
- bool spaceRequiredBetween(const AnnotatedToken &Left,
- const AnnotatedToken &Right);
-
- bool spaceRequiredBefore(const AnnotatedToken &Tok);
-
- bool canBreakBefore(const AnnotatedToken &Right);
-
- FormatStyle Style;
- SourceManager &SourceMgr;
- Lexer &Lex;
- AnnotatedLine &Line;
+ // Contextual keywords:
+ IdentifierInfo &Ident_in;
};
-
} // end namespace format
} // end namespace clang
-#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
+#endif