| //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief This file implements a token annotator, i.e. creates |
| /// \c AnnotatedTokens out of \c FormatTokens with required extra information. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H |
| #define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_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_InheritanceColon, |
| TT_LineComment, |
| TT_ObjCArrayLiteral, |
| TT_ObjCBlockLParen, |
| TT_ObjCDecl, |
| TT_ObjCForIn, |
| TT_ObjCMethodExpr, |
| TT_ObjCMethodSpecifier, |
| TT_ObjCProperty, |
| TT_ObjCSelectorName, |
| 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_BuilderTypeCall, |
| LT_PreprocessorDirective, |
| LT_VirtualFunctionDecl, |
| LT_ObjCDecl, // An @interface, @implementation, or @protocol line. |
| LT_ObjCMethodDecl, |
| LT_ObjCProperty // An @property line. |
| }; |
| |
| class AnnotatedToken { |
| public: |
| explicit AnnotatedToken(const FormatToken &FormatTok) |
| : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0), |
| CanBreakBefore(false), MustBreakBefore(false), |
| ClosesTemplateDeclaration(false), MatchingParen(NULL), |
| ParameterCount(0), BindingStrength(0), SplitPenalty(0), |
| LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0), |
| FakeRParens(0) { |
| } |
| |
| 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; |
| |
| 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; |
| |
| // 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 Insert this many fake ( before this token for correct indentation. |
| unsigned FakeLParens; |
| /// \brief Insert this many fake ) after this token for correct indentation. |
| unsigned FakeRParens; |
| |
| 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), |
| InPPDirective(Line.InPPDirective), |
| MustBeDeclaration(Line.MustBeDeclaration), |
| MightBeFunctionDecl(false) { |
| assert(!Line.Tokens.empty()); |
| AnnotatedToken *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]; |
| } |
| Last = Current; |
| } |
| AnnotatedLine(const AnnotatedLine &Other) |
| : First(Other.First), Type(Other.Type), Level(Other.Level), |
| InPPDirective(Other.InPPDirective), |
| MustBeDeclaration(Other.MustBeDeclaration), |
| MightBeFunctionDecl(Other.MightBeFunctionDecl) { |
| Last = &First; |
| while (!Last->Children.empty()) { |
| Last->Children[0].Parent = Last; |
| Last = &Last->Children[0]; |
| } |
| } |
| |
| AnnotatedToken First; |
| AnnotatedToken *Last; |
| |
| 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); |
| } |
| |
| /// \brief Determines extra information about the tokens comprising an |
| /// \c UnwrappedLine. |
| class TokenAnnotator { |
| public: |
| TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex, |
| IdentifierInfo &Ident_in) |
| : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Ident_in(Ident_in) { |
| } |
| |
| void annotate(AnnotatedLine &Line); |
| void calculateFormattingInformation(AnnotatedLine &Line); |
| |
| private: |
| /// \brief Calculate the penalty for splitting before \c Tok. |
| unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok); |
| |
| bool spaceRequiredBetween(const AnnotatedLine &Line, |
| const AnnotatedToken &Left, |
| const AnnotatedToken &Right); |
| |
| bool spaceRequiredBefore(const AnnotatedLine &Line, |
| const AnnotatedToken &Tok); |
| |
| bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right); |
| |
| const FormatStyle &Style; |
| SourceManager &SourceMgr; |
| Lexer &Lex; |
| |
| // Contextual keywords: |
| IdentifierInfo &Ident_in; |
| }; |
| |
| } // end namespace format |
| } // end namespace clang |
| |
| #endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H |