1 //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This file implements a token annotator, i.e. creates
12 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
17 #define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
19 #include "UnwrappedLineParser.h"
20 #include "clang/Basic/OperatorPrecedence.h"
21 #include "clang/Format/Format.h"
35 TT_CtorInitializerColon,
36 TT_ImplicitStringLiteral,
40 TT_ObjCMethodSpecifier,
43 TT_OverloadedOperator,
44 TT_PointerOrReference,
45 TT_PureVirtualSpecifier,
46 TT_RangeBasedForLoopColon,
50 TT_TrailingUnaryOperator,
59 LT_PreprocessorDirective,
60 LT_VirtualFunctionDecl,
61 LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
63 LT_ObjCProperty // An @property line.
66 class AnnotatedToken {
68 explicit AnnotatedToken(const FormatToken &FormatTok)
69 : FormatTok(FormatTok), Type(TT_Unknown), SpaceRequiredBefore(false),
70 CanBreakBefore(false), MustBreakBefore(false),
71 ClosesTemplateDeclaration(false), MatchingParen(NULL),
72 ParameterCount(1), Parent(NULL) {
75 bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
76 bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
78 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
79 return FormatTok.Tok.isObjCAtKeyword(Kind);
82 FormatToken FormatTok;
86 bool SpaceRequiredBefore;
90 bool ClosesTemplateDeclaration;
92 AnnotatedToken *MatchingParen;
94 /// \brief Number of parameters, if this is "(", "[" or "<".
96 /// This is initialized to 1 as we don't need to distinguish functions with
97 /// 0 parameters from functions with 1 parameter. Thus, we can simply count
98 /// the number of commas.
99 unsigned ParameterCount;
101 /// \brief The total length of the line up to and including this token.
102 unsigned TotalLength;
104 /// \brief Penalty for inserting a line break before this token.
105 unsigned SplitPenalty;
107 std::vector<AnnotatedToken> Children;
108 AnnotatedToken *Parent;
110 const AnnotatedToken *getPreviousNoneComment() const {
111 AnnotatedToken *Tok = Parent;
112 while (Tok != NULL && Tok->is(tok::comment))
118 class AnnotatedLine {
120 AnnotatedLine(const UnwrappedLine &Line)
121 : First(Line.Tokens.front()), Level(Line.Level),
122 InPPDirective(Line.InPPDirective),
123 MustBeDeclaration(Line.MustBeDeclaration) {
124 assert(!Line.Tokens.empty());
125 AnnotatedToken *Current = &First;
126 for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
127 E = Line.Tokens.end();
129 Current->Children.push_back(AnnotatedToken(*I));
130 Current->Children[0].Parent = Current;
131 Current = &Current->Children[0];
135 AnnotatedLine(const AnnotatedLine &Other)
136 : First(Other.First), Type(Other.Type), Level(Other.Level),
137 InPPDirective(Other.InPPDirective),
138 MustBeDeclaration(Other.MustBeDeclaration) {
140 while (!Last->Children.empty()) {
141 Last->Children[0].Parent = Last;
142 Last = &Last->Children[0];
146 AnnotatedToken First;
147 AnnotatedToken *Last;
152 bool MustBeDeclaration;
155 inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
156 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
159 /// \brief Determines extra information about the tokens comprising an
160 /// \c UnwrappedLine.
161 class TokenAnnotator {
163 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
165 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Line(Line) {
169 void calculateExtraInformation(AnnotatedToken &Current);
172 /// \brief Calculate the penalty for splitting before \c Tok.
173 unsigned splitPenalty(const AnnotatedToken &Tok);
175 void determineTokenTypes(AnnotatedToken &Current, bool IsExpression,
176 bool LookForFunctionName);
178 /// \brief Starting from \p Current, this searches backwards for an
179 /// identifier which could be the start of a function name and marks it.
180 void findFunctionName(AnnotatedToken *Current);
182 /// \brief Returns the previous token ignoring comments.
183 const AnnotatedToken *getPreviousToken(const AnnotatedToken &Tok) {
184 const AnnotatedToken *PrevToken = Tok.Parent;
185 while (PrevToken != NULL && PrevToken->is(tok::comment))
186 PrevToken = PrevToken->Parent;
190 /// \brief Returns the next token ignoring comments.
191 const AnnotatedToken *getNextToken(const AnnotatedToken &Tok) {
192 if (Tok.Children.empty())
194 const AnnotatedToken *NextToken = &Tok.Children[0];
195 while (NextToken->is(tok::comment)) {
196 if (NextToken->Children.empty())
198 NextToken = &NextToken->Children[0];
203 /// \brief Return the type of the given token assuming it is * or &.
204 TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsExpression);
206 TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok);
208 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
209 TokenType determineIncrementUsage(const AnnotatedToken &Tok);
211 bool spaceRequiredBetween(const AnnotatedToken &Left,
212 const AnnotatedToken &Right);
214 bool spaceRequiredBefore(const AnnotatedToken &Tok);
216 bool canBreakBefore(const AnnotatedToken &Right);
219 SourceManager &SourceMgr;
225 } // end namespace format
226 } // end namespace clang
228 #endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H