]> granicus.if.org Git - clang/blob - lib/Format/TokenAnnotator.h
Move the token annotator into separate files.
[clang] / lib / Format / TokenAnnotator.h
1 //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file implements a token annotator, i.e. creates
12 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
17 #define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
18
19 #include "UnwrappedLineParser.h"
20 #include "clang/Basic/OperatorPrecedence.h"
21 #include "clang/Format/Format.h"
22 #include <string>
23
24 namespace clang {
25 class Lexer;
26 class SourceManager;
27
28 namespace format {
29
30 enum TokenType {
31   TT_BinaryOperator,
32   TT_BlockComment,
33   TT_CastRParen,
34   TT_ConditionalExpr,
35   TT_CtorInitializerColon,
36   TT_ImplicitStringLiteral,
37   TT_LineComment,
38   TT_ObjCBlockLParen,
39   TT_ObjCDecl,
40   TT_ObjCMethodSpecifier,
41   TT_ObjCMethodExpr,
42   TT_ObjCProperty,
43   TT_OverloadedOperator,
44   TT_PointerOrReference,
45   TT_PureVirtualSpecifier,
46   TT_RangeBasedForLoopColon,
47   TT_StartOfName,
48   TT_TemplateCloser,
49   TT_TemplateOpener,
50   TT_TrailingUnaryOperator,
51   TT_UnaryOperator,
52   TT_Unknown
53 };
54
55 enum LineType {
56   LT_Invalid,
57   LT_Other,
58   LT_BuilderTypeCall,
59   LT_PreprocessorDirective,
60   LT_VirtualFunctionDecl,
61   LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
62   LT_ObjCMethodDecl,
63   LT_ObjCProperty // An @property line.
64 };
65
66 class AnnotatedToken {
67 public:
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) {
73   }
74
75   bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
76   bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
77
78   bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
79     return FormatTok.Tok.isObjCAtKeyword(Kind);
80   }
81
82   FormatToken FormatTok;
83
84   TokenType Type;
85
86   bool SpaceRequiredBefore;
87   bool CanBreakBefore;
88   bool MustBreakBefore;
89
90   bool ClosesTemplateDeclaration;
91
92   AnnotatedToken *MatchingParen;
93
94   /// \brief Number of parameters, if this is "(", "[" or "<".
95   ///
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;
100
101   /// \brief The total length of the line up to and including this token.
102   unsigned TotalLength;
103
104   /// \brief Penalty for inserting a line break before this token.
105   unsigned SplitPenalty;
106
107   std::vector<AnnotatedToken> Children;
108   AnnotatedToken *Parent;
109
110   const AnnotatedToken *getPreviousNoneComment() const {
111     AnnotatedToken *Tok = Parent;
112     while (Tok != NULL && Tok->is(tok::comment))
113       Tok = Tok->Parent;
114     return Tok;
115   }
116 };
117
118 class AnnotatedLine {
119 public:
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();
128          I != E; ++I) {
129       Current->Children.push_back(AnnotatedToken(*I));
130       Current->Children[0].Parent = Current;
131       Current = &Current->Children[0];
132     }
133     Last = Current;
134   }
135   AnnotatedLine(const AnnotatedLine &Other)
136       : First(Other.First), Type(Other.Type), Level(Other.Level),
137         InPPDirective(Other.InPPDirective),
138         MustBeDeclaration(Other.MustBeDeclaration) {
139     Last = &First;
140     while (!Last->Children.empty()) {
141       Last->Children[0].Parent = Last;
142       Last = &Last->Children[0];
143     }
144   }
145
146   AnnotatedToken First;
147   AnnotatedToken *Last;
148
149   LineType Type;
150   unsigned Level;
151   bool InPPDirective;
152   bool MustBeDeclaration;
153 };
154
155 inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
156   return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
157 }
158
159 /// \brief Determines extra information about the tokens comprising an
160 /// \c UnwrappedLine.
161 class TokenAnnotator {
162 public:
163   TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
164                  AnnotatedLine &Line)
165       : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Line(Line) {
166   }
167
168   void annotate();
169   void calculateExtraInformation(AnnotatedToken &Current);
170
171 private:
172   /// \brief Calculate the penalty for splitting before \c Tok.
173   unsigned splitPenalty(const AnnotatedToken &Tok);
174
175   void determineTokenTypes(AnnotatedToken &Current, bool IsExpression,
176                            bool LookForFunctionName);
177
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);
181
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;
187     return PrevToken;
188   }
189
190   /// \brief Returns the next token ignoring comments.
191   const AnnotatedToken *getNextToken(const AnnotatedToken &Tok) {
192     if (Tok.Children.empty())
193       return NULL;
194     const AnnotatedToken *NextToken = &Tok.Children[0];
195     while (NextToken->is(tok::comment)) {
196       if (NextToken->Children.empty())
197         return NULL;
198       NextToken = &NextToken->Children[0];
199     }
200     return NextToken;
201   }
202
203   /// \brief Return the type of the given token assuming it is * or &.
204   TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsExpression);
205
206   TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok);
207
208   /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
209   TokenType determineIncrementUsage(const AnnotatedToken &Tok);
210
211   bool spaceRequiredBetween(const AnnotatedToken &Left,
212                             const AnnotatedToken &Right);
213
214   bool spaceRequiredBefore(const AnnotatedToken &Tok);
215
216   bool canBreakBefore(const AnnotatedToken &Right);
217
218   FormatStyle Style;
219   SourceManager &SourceMgr;
220   Lexer &Lex;
221   AnnotatedLine &Line;
222 };
223
224
225 } // end namespace format
226 } // end namespace clang
227
228 #endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H