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