blob: c19b486c1c2306e57398ce4829373564e1ae8d9e [file] [log] [blame]
Daniel Jasper7a6d09b2013-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 Weber2a726b62013-02-10 02:08:05 +000038 TT_ObjCArrayLiteral,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000039 TT_ObjCBlockLParen,
40 TT_ObjCDecl,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000041 TT_ObjCMethodExpr,
Nico Weber2a726b62013-02-10 02:08:05 +000042 TT_ObjCMethodSpecifier,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000043 TT_ObjCProperty,
Daniel Jasper1ac3e052013-02-05 10:07:47 +000044 TT_ObjCSelectorName,
Daniel Jasper35d2dc72013-02-11 08:01:18 +000045 TT_OverloadedOperatorLParen,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000046 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
57enum 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
68class AnnotatedToken {
69public:
70 explicit AnnotatedToken(const FormatToken &FormatTok)
Daniel Jaspereef30492013-02-11 12:36:37 +000071 : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000072 CanBreakBefore(false), MustBreakBefore(false),
73 ClosesTemplateDeclaration(false), MatchingParen(NULL),
Daniel Jasper1ac3e052013-02-05 10:07:47 +000074 ParameterCount(1), BindingStrength(0), SplitPenalty(0),
Daniel Jasper400adc62013-02-08 15:28:42 +000075 LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
76 FakeRParens(0) {
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000077 }
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
Daniel Jaspereef30492013-02-11 12:36:37 +000090 unsigned SpacesRequiredBefore;
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000091 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
Daniel Jasper3a9370c2013-02-04 07:21:18 +0000108 // 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
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000113 /// \brief Penalty for inserting a line break before this token.
114 unsigned SplitPenalty;
115
Daniel Jasper1ac3e052013-02-05 10:07:47 +0000116 /// \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
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000120 std::vector<AnnotatedToken> Children;
121 AnnotatedToken *Parent;
122
Daniel Jasper400adc62013-02-08 15:28:42 +0000123 /// \brief Insert this many fake ( before this token for correct indentation.
124 unsigned FakeLParens;
Daniel Jasper8360a862013-02-08 16:49:27 +0000125 /// \brief Insert this many fake ) after this token for correct indentation.
Daniel Jasper400adc62013-02-08 15:28:42 +0000126 unsigned FakeRParens;
127
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000128 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
136class AnnotatedLine {
137public:
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
173inline 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.
179class TokenAnnotator {
180public:
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000181 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex)
182 : Style(Style), SourceMgr(SourceMgr), Lex(Lex) {
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000183 }
184
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000185 void annotate(AnnotatedLine &Line);
186 void calculateFormattingInformation(AnnotatedLine &Line);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000187
188private:
189 /// \brief Calculate the penalty for splitting before \c Tok.
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000190 unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000191
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000192 bool spaceRequiredBetween(const AnnotatedLine &Line,
193 const AnnotatedToken &Left,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000194 const AnnotatedToken &Right);
195
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000196 bool spaceRequiredBefore(const AnnotatedLine &Line,
197 const AnnotatedToken &Tok);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000198
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000199 bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000200
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000201 const FormatStyle &Style;
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000202 SourceManager &SourceMgr;
203 Lexer &Lex;
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000204};
205
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000206} // end namespace format
207} // end namespace clang
208
209#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H