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