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