blob: 506f271dc5d15de106cf4062710c536243bae03c [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,
37 TT_LineComment,
Nico Weber051860e2013-02-10 02:08:05 +000038 TT_ObjCArrayLiteral,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000039 TT_ObjCBlockLParen,
40 TT_ObjCDecl,
Nico Weberc2e6d2a2013-02-11 15:32:15 +000041 TT_ObjCForIn,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000042 TT_ObjCMethodExpr,
Nico Weber051860e2013-02-10 02:08:05 +000043 TT_ObjCMethodSpecifier,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000044 TT_ObjCProperty,
Daniel Jasper63d7ced2013-02-05 10:07:47 +000045 TT_ObjCSelectorName,
Daniel Jasper2b4c9242013-02-11 08:01:18 +000046 TT_OverloadedOperatorLParen,
Daniel Jasper32d28ee2013-01-29 21:01:14 +000047 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
58enum 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
69class AnnotatedToken {
70public:
71 explicit AnnotatedToken(const FormatToken &FormatTok)
Daniel Jasper729a7432013-02-11 12:36:37 +000072 : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
Daniel Jasper32d28ee2013-01-29 21:01:14 +000073 CanBreakBefore(false), MustBreakBefore(false),
74 ClosesTemplateDeclaration(false), MatchingParen(NULL),
Daniel Jasper63d7ced2013-02-05 10:07:47 +000075 ParameterCount(1), BindingStrength(0), SplitPenalty(0),
Daniel Jasper29f123b2013-02-08 15:28:42 +000076 LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
77 FakeRParens(0) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +000078 }
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
Daniel Jasper729a7432013-02-11 12:36:37 +000091 unsigned SpacesRequiredBefore;
Daniel Jasper32d28ee2013-01-29 21:01:14 +000092 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
Daniel Jasper01786732013-02-04 07:21:18 +0000109 // 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
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000114 /// \brief Penalty for inserting a line break before this token.
115 unsigned SplitPenalty;
116
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000117 /// \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
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000121 std::vector<AnnotatedToken> Children;
122 AnnotatedToken *Parent;
123
Daniel Jasper29f123b2013-02-08 15:28:42 +0000124 /// \brief Insert this many fake ( before this token for correct indentation.
125 unsigned FakeLParens;
Daniel Jasper087387a2013-02-08 16:49:27 +0000126 /// \brief Insert this many fake ) after this token for correct indentation.
Daniel Jasper29f123b2013-02-08 15:28:42 +0000127 unsigned FakeRParens;
128
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000129 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
137class AnnotatedLine {
138public:
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
174inline 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.
180class TokenAnnotator {
181public:
Nico Weberc2e6d2a2013-02-11 15:32:15 +0000182 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
183 IdentifierInfo &Ident_in)
184 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Ident_in(Ident_in) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000185 }
186
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000187 void annotate(AnnotatedLine &Line);
188 void calculateFormattingInformation(AnnotatedLine &Line);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000189
190private:
191 /// \brief Calculate the penalty for splitting before \c Tok.
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000192 unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000193
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000194 bool spaceRequiredBetween(const AnnotatedLine &Line,
195 const AnnotatedToken &Left,
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000196 const AnnotatedToken &Right);
197
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000198 bool spaceRequiredBefore(const AnnotatedLine &Line,
199 const AnnotatedToken &Tok);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000200
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000201 bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000202
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000203 const FormatStyle &Style;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000204 SourceManager &SourceMgr;
205 Lexer &Lex;
Nico Weberc2e6d2a2013-02-11 15:32:15 +0000206
207 // Contextual keywords:
208 IdentifierInfo &Ident_in;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000209};
210
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000211} // end namespace format
212} // end namespace clang
213
214#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H