blob: 2b938363d5ae24d0065bfd770b294a276aa832bd [file] [log] [blame]
Daniel Jasper32d28ee2013-01-29 21:01:14 +00001//===--- 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
24namespace clang {
25class Lexer;
26class SourceManager;
27
28namespace format {
29
30enum TokenType {
31 TT_BinaryOperator,
32 TT_BlockComment,
33 TT_CastRParen,
34 TT_ConditionalExpr,
35 TT_CtorInitializerColon,
36 TT_ImplicitStringLiteral,
Daniel Jasper6cabab42013-02-14 08:42:54 +000037 TT_InheritanceColon,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000038 TT_LineComment,
Nico Weber051860e2013-02-10 02:08:05 +000039 TT_ObjCArrayLiteral,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000040 TT_ObjCBlockLParen,
41 TT_ObjCDecl,
Nico Weberc2e6d2a2013-02-11 15:32:15 +000042 TT_ObjCForIn,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000043 TT_ObjCMethodExpr,
Nico Weber051860e2013-02-10 02:08:05 +000044 TT_ObjCMethodSpecifier,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000045 TT_ObjCProperty,
Daniel Jasper63d7ced2013-02-05 10:07:47 +000046 TT_ObjCSelectorName,
Daniel Jasper2b4c9242013-02-11 08:01:18 +000047 TT_OverloadedOperatorLParen,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000048 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
59enum 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
70class AnnotatedToken {
71public:
72 explicit AnnotatedToken(const FormatToken &FormatTok)
Daniel Jasper729a7432013-02-11 12:36:37 +000073 : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
Daniel Jasper32d28ee2013-01-29 21:01:14 +000074 CanBreakBefore(false), MustBreakBefore(false),
75 ClosesTemplateDeclaration(false), MatchingParen(NULL),
Daniel Jasper9fc56f22013-02-14 15:01:34 +000076 ParameterCount(0), BindingStrength(0), SplitPenalty(0),
Daniel Jasper29f123b2013-02-08 15:28:42 +000077 LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
Daniel Jasper24849712013-03-01 16:48:32 +000078 FakeRParens(0), LastInChainOfCalls(false) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +000079 }
80
81 bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
Alexander Kornienkoe74de282013-03-13 14:41:29 +000082
83 bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
84 return is(K1) || is(K2);
85 }
86
87 bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3) const {
88 return is(K1) || is(K2) || is(K3);
89 }
90
91 bool isOneOf(
92 tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind K3,
93 tok::TokenKind K4, tok::TokenKind K5 = tok::NUM_TOKENS,
94 tok::TokenKind K6 = tok::NUM_TOKENS, tok::TokenKind K7 = tok::NUM_TOKENS,
95 tok::TokenKind K8 = tok::NUM_TOKENS, tok::TokenKind K9 = tok::NUM_TOKENS,
96 tok::TokenKind K10 = tok::NUM_TOKENS,
97 tok::TokenKind K11 = tok::NUM_TOKENS,
98 tok::TokenKind K12 = tok::NUM_TOKENS) const {
99 return is(K1) || is(K2) || is(K3) || is(K4) || is(K5) || is(K6) || is(K7) ||
100 is(K8) || is(K9) || is(K10) || is(K11) || is(K12);
101 }
102
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000103 bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
104
105 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
106 return FormatTok.Tok.isObjCAtKeyword(Kind);
107 }
108
109 FormatToken FormatTok;
110
111 TokenType Type;
112
Daniel Jasper729a7432013-02-11 12:36:37 +0000113 unsigned SpacesRequiredBefore;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000114 bool CanBreakBefore;
115 bool MustBreakBefore;
116
117 bool ClosesTemplateDeclaration;
118
119 AnnotatedToken *MatchingParen;
120
121 /// \brief Number of parameters, if this is "(", "[" or "<".
122 ///
123 /// This is initialized to 1 as we don't need to distinguish functions with
124 /// 0 parameters from functions with 1 parameter. Thus, we can simply count
125 /// the number of commas.
126 unsigned ParameterCount;
127
128 /// \brief The total length of the line up to and including this token.
129 unsigned TotalLength;
130
Daniel Jasper01786732013-02-04 07:21:18 +0000131 // FIXME: Come up with a 'cleaner' concept.
132 /// \brief The binding strength of a token. This is a combined value of
133 /// operator precedence, parenthesis nesting, etc.
134 unsigned BindingStrength;
135
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000136 /// \brief Penalty for inserting a line break before this token.
137 unsigned SplitPenalty;
138
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000139 /// \brief If this is the first ObjC selector name in an ObjC method
140 /// definition or call, this contains the length of the longest name.
141 unsigned LongestObjCSelectorName;
142
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000143 std::vector<AnnotatedToken> Children;
144 AnnotatedToken *Parent;
145
Daniel Jasper29f123b2013-02-08 15:28:42 +0000146 /// \brief Insert this many fake ( before this token for correct indentation.
147 unsigned FakeLParens;
Daniel Jasper087387a2013-02-08 16:49:27 +0000148 /// \brief Insert this many fake ) after this token for correct indentation.
Daniel Jasper29f123b2013-02-08 15:28:42 +0000149 unsigned FakeRParens;
150
Daniel Jasper24849712013-03-01 16:48:32 +0000151 /// \brief Is this the last "." or "->" in a builder-type call?
152 bool LastInChainOfCalls;
153
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000154 const AnnotatedToken *getPreviousNoneComment() const {
155 AnnotatedToken *Tok = Parent;
156 while (Tok != NULL && Tok->is(tok::comment))
157 Tok = Tok->Parent;
158 return Tok;
159 }
160};
161
162class AnnotatedLine {
163public:
164 AnnotatedLine(const UnwrappedLine &Line)
165 : First(Line.Tokens.front()), Level(Line.Level),
166 InPPDirective(Line.InPPDirective),
Daniel Jasper3c08a812013-02-24 18:54:32 +0000167 MustBeDeclaration(Line.MustBeDeclaration),
168 MightBeFunctionDecl(false) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000169 assert(!Line.Tokens.empty());
170 AnnotatedToken *Current = &First;
171 for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
172 E = Line.Tokens.end();
173 I != E; ++I) {
174 Current->Children.push_back(AnnotatedToken(*I));
175 Current->Children[0].Parent = Current;
176 Current = &Current->Children[0];
177 }
178 Last = Current;
179 }
180 AnnotatedLine(const AnnotatedLine &Other)
181 : First(Other.First), Type(Other.Type), Level(Other.Level),
182 InPPDirective(Other.InPPDirective),
Daniel Jasper3c08a812013-02-24 18:54:32 +0000183 MustBeDeclaration(Other.MustBeDeclaration),
184 MightBeFunctionDecl(Other.MightBeFunctionDecl) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000185 Last = &First;
186 while (!Last->Children.empty()) {
187 Last->Children[0].Parent = Last;
188 Last = &Last->Children[0];
189 }
190 }
191
192 AnnotatedToken First;
193 AnnotatedToken *Last;
194
195 LineType Type;
196 unsigned Level;
197 bool InPPDirective;
198 bool MustBeDeclaration;
Daniel Jasper3c08a812013-02-24 18:54:32 +0000199 bool MightBeFunctionDecl;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000200};
201
202inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
203 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
204}
205
206/// \brief Determines extra information about the tokens comprising an
207/// \c UnwrappedLine.
208class TokenAnnotator {
209public:
Nico Weberc2e6d2a2013-02-11 15:32:15 +0000210 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
211 IdentifierInfo &Ident_in)
212 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Ident_in(Ident_in) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000213 }
214
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000215 void annotate(AnnotatedLine &Line);
216 void calculateFormattingInformation(AnnotatedLine &Line);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000217
218private:
219 /// \brief Calculate the penalty for splitting before \c Tok.
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000220 unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000221
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000222 bool spaceRequiredBetween(const AnnotatedLine &Line,
223 const AnnotatedToken &Left,
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000224 const AnnotatedToken &Right);
225
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000226 bool spaceRequiredBefore(const AnnotatedLine &Line,
227 const AnnotatedToken &Tok);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000228
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000229 bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000230
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000231 const FormatStyle &Style;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000232 SourceManager &SourceMgr;
233 Lexer &Lex;
Nico Weberc2e6d2a2013-02-11 15:32:15 +0000234
235 // Contextual keywords:
236 IdentifierInfo &Ident_in;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000237};
238
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000239} // end namespace format
240} // end namespace clang
241
242#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H