]> granicus.if.org Git - clang/blob - lib/Format/TokenAnnotator.h
Formatter: Detect ObjC message expressions after 'in' in loop
[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_ObjCArrayLiteral,
39   TT_ObjCBlockLParen,
40   TT_ObjCDecl,
41   TT_ObjCForIn,
42   TT_ObjCMethodExpr,
43   TT_ObjCMethodSpecifier,
44   TT_ObjCProperty,
45   TT_ObjCSelectorName,
46   TT_OverloadedOperatorLParen,
47   TT_PointerOrReference,
48   TT_PureVirtualSpecifier,
49   TT_RangeBasedForLoopColon,
50   TT_StartOfName,
51   TT_TemplateCloser,
52   TT_TemplateOpener,
53   TT_TrailingUnaryOperator,
54   TT_UnaryOperator,
55   TT_Unknown
56 };
57
58 enum LineType {
59   LT_Invalid,
60   LT_Other,
61   LT_BuilderTypeCall,
62   LT_PreprocessorDirective,
63   LT_VirtualFunctionDecl,
64   LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
65   LT_ObjCMethodDecl,
66   LT_ObjCProperty // An @property line.
67 };
68
69 class AnnotatedToken {
70 public:
71   explicit AnnotatedToken(const FormatToken &FormatTok)
72       : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
73         CanBreakBefore(false), MustBreakBefore(false),
74         ClosesTemplateDeclaration(false), MatchingParen(NULL),
75         ParameterCount(1), BindingStrength(0), SplitPenalty(0),
76         LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
77         FakeRParens(0) {
78   }
79
80   bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
81   bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
82
83   bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
84     return FormatTok.Tok.isObjCAtKeyword(Kind);
85   }
86
87   FormatToken FormatTok;
88
89   TokenType Type;
90
91   unsigned SpacesRequiredBefore;
92   bool CanBreakBefore;
93   bool MustBreakBefore;
94
95   bool ClosesTemplateDeclaration;
96
97   AnnotatedToken *MatchingParen;
98
99   /// \brief Number of parameters, if this is "(", "[" or "<".
100   ///
101   /// This is initialized to 1 as we don't need to distinguish functions with
102   /// 0 parameters from functions with 1 parameter. Thus, we can simply count
103   /// the number of commas.
104   unsigned ParameterCount;
105
106   /// \brief The total length of the line up to and including this token.
107   unsigned TotalLength;
108
109   // FIXME: Come up with a 'cleaner' concept.
110   /// \brief The binding strength of a token. This is a combined value of
111   /// operator precedence, parenthesis nesting, etc.
112   unsigned BindingStrength;
113
114   /// \brief Penalty for inserting a line break before this token.
115   unsigned SplitPenalty;
116
117   /// \brief If this is the first ObjC selector name in an ObjC method
118   /// definition or call, this contains the length of the longest name.
119   unsigned LongestObjCSelectorName;
120
121   std::vector<AnnotatedToken> Children;
122   AnnotatedToken *Parent;
123
124   /// \brief Insert this many fake ( before this token for correct indentation.
125   unsigned FakeLParens;
126   /// \brief Insert this many fake ) after this token for correct indentation.
127   unsigned FakeRParens;
128
129   const AnnotatedToken *getPreviousNoneComment() const {
130     AnnotatedToken *Tok = Parent;
131     while (Tok != NULL && Tok->is(tok::comment))
132       Tok = Tok->Parent;
133     return Tok;
134   }
135 };
136
137 class AnnotatedLine {
138 public:
139   AnnotatedLine(const UnwrappedLine &Line)
140       : First(Line.Tokens.front()), Level(Line.Level),
141         InPPDirective(Line.InPPDirective),
142         MustBeDeclaration(Line.MustBeDeclaration) {
143     assert(!Line.Tokens.empty());
144     AnnotatedToken *Current = &First;
145     for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
146                                                 E = Line.Tokens.end();
147          I != E; ++I) {
148       Current->Children.push_back(AnnotatedToken(*I));
149       Current->Children[0].Parent = Current;
150       Current = &Current->Children[0];
151     }
152     Last = Current;
153   }
154   AnnotatedLine(const AnnotatedLine &Other)
155       : First(Other.First), Type(Other.Type), Level(Other.Level),
156         InPPDirective(Other.InPPDirective),
157         MustBeDeclaration(Other.MustBeDeclaration) {
158     Last = &First;
159     while (!Last->Children.empty()) {
160       Last->Children[0].Parent = Last;
161       Last = &Last->Children[0];
162     }
163   }
164
165   AnnotatedToken First;
166   AnnotatedToken *Last;
167
168   LineType Type;
169   unsigned Level;
170   bool InPPDirective;
171   bool MustBeDeclaration;
172 };
173
174 inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
175   return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
176 }
177
178 /// \brief Determines extra information about the tokens comprising an
179 /// \c UnwrappedLine.
180 class TokenAnnotator {
181 public:
182   TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
183                  IdentifierInfo &Ident_in)
184       : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Ident_in(Ident_in) {
185   }
186
187   void annotate(AnnotatedLine &Line);
188   void calculateFormattingInformation(AnnotatedLine &Line);
189
190 private:
191   /// \brief Calculate the penalty for splitting before \c Tok.
192   unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
193
194   bool spaceRequiredBetween(const AnnotatedLine &Line,
195                             const AnnotatedToken &Left,
196                             const AnnotatedToken &Right);
197
198   bool spaceRequiredBefore(const AnnotatedLine &Line,
199                            const AnnotatedToken &Tok);
200
201   bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
202
203   const FormatStyle &Style;
204   SourceManager &SourceMgr;
205   Lexer &Lex;
206
207   // Contextual keywords:
208   IdentifierInfo &Ident_in;
209 };
210
211 } // end namespace format
212 } // end namespace clang
213
214 #endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H