blob: dc936e48b5ccef3bd22a7fcc16da5a2f6e6afc76 [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,
38 TT_ObjCBlockLParen,
39 TT_ObjCDecl,
40 TT_ObjCMethodSpecifier,
41 TT_ObjCMethodExpr,
42 TT_ObjCProperty,
Daniel Jasper1ac3e052013-02-05 10:07:47 +000043 TT_ObjCSelectorName,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000044 TT_OverloadedOperator,
45 TT_PointerOrReference,
46 TT_PureVirtualSpecifier,
47 TT_RangeBasedForLoopColon,
48 TT_StartOfName,
49 TT_TemplateCloser,
50 TT_TemplateOpener,
51 TT_TrailingUnaryOperator,
52 TT_UnaryOperator,
53 TT_Unknown
54};
55
56enum LineType {
57 LT_Invalid,
58 LT_Other,
59 LT_BuilderTypeCall,
60 LT_PreprocessorDirective,
61 LT_VirtualFunctionDecl,
62 LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
63 LT_ObjCMethodDecl,
64 LT_ObjCProperty // An @property line.
65};
66
67class AnnotatedToken {
68public:
69 explicit AnnotatedToken(const FormatToken &FormatTok)
70 : FormatTok(FormatTok), Type(TT_Unknown), SpaceRequiredBefore(false),
71 CanBreakBefore(false), MustBreakBefore(false),
72 ClosesTemplateDeclaration(false), MatchingParen(NULL),
Daniel Jasper1ac3e052013-02-05 10:07:47 +000073 ParameterCount(1), BindingStrength(0), SplitPenalty(0),
Daniel Jasper400adc62013-02-08 15:28:42 +000074 LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
75 FakeRParens(0) {
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000076 }
77
78 bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
79 bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
80
81 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
82 return FormatTok.Tok.isObjCAtKeyword(Kind);
83 }
84
85 FormatToken FormatTok;
86
87 TokenType Type;
88
89 bool SpaceRequiredBefore;
90 bool CanBreakBefore;
91 bool MustBreakBefore;
92
93 bool ClosesTemplateDeclaration;
94
95 AnnotatedToken *MatchingParen;
96
97 /// \brief Number of parameters, if this is "(", "[" or "<".
98 ///
99 /// This is initialized to 1 as we don't need to distinguish functions with
100 /// 0 parameters from functions with 1 parameter. Thus, we can simply count
101 /// the number of commas.
102 unsigned ParameterCount;
103
104 /// \brief The total length of the line up to and including this token.
105 unsigned TotalLength;
106
Daniel Jasper3a9370c2013-02-04 07:21:18 +0000107 // FIXME: Come up with a 'cleaner' concept.
108 /// \brief The binding strength of a token. This is a combined value of
109 /// operator precedence, parenthesis nesting, etc.
110 unsigned BindingStrength;
111
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000112 /// \brief Penalty for inserting a line break before this token.
113 unsigned SplitPenalty;
114
Daniel Jasper1ac3e052013-02-05 10:07:47 +0000115 /// \brief If this is the first ObjC selector name in an ObjC method
116 /// definition or call, this contains the length of the longest name.
117 unsigned LongestObjCSelectorName;
118
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000119 std::vector<AnnotatedToken> Children;
120 AnnotatedToken *Parent;
121
Daniel Jasper400adc62013-02-08 15:28:42 +0000122 /// \brief Insert this many fake ( before this token for correct indentation.
123 unsigned FakeLParens;
124 /// \brief Insert this many fake ) before this token for correct indentation.
125 unsigned FakeRParens;
126
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000127 const AnnotatedToken *getPreviousNoneComment() const {
128 AnnotatedToken *Tok = Parent;
129 while (Tok != NULL && Tok->is(tok::comment))
130 Tok = Tok->Parent;
131 return Tok;
132 }
133};
134
135class AnnotatedLine {
136public:
137 AnnotatedLine(const UnwrappedLine &Line)
138 : First(Line.Tokens.front()), Level(Line.Level),
139 InPPDirective(Line.InPPDirective),
140 MustBeDeclaration(Line.MustBeDeclaration) {
141 assert(!Line.Tokens.empty());
142 AnnotatedToken *Current = &First;
143 for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
144 E = Line.Tokens.end();
145 I != E; ++I) {
146 Current->Children.push_back(AnnotatedToken(*I));
147 Current->Children[0].Parent = Current;
148 Current = &Current->Children[0];
149 }
150 Last = Current;
151 }
152 AnnotatedLine(const AnnotatedLine &Other)
153 : First(Other.First), Type(Other.Type), Level(Other.Level),
154 InPPDirective(Other.InPPDirective),
155 MustBeDeclaration(Other.MustBeDeclaration) {
156 Last = &First;
157 while (!Last->Children.empty()) {
158 Last->Children[0].Parent = Last;
159 Last = &Last->Children[0];
160 }
161 }
162
163 AnnotatedToken First;
164 AnnotatedToken *Last;
165
166 LineType Type;
167 unsigned Level;
168 bool InPPDirective;
169 bool MustBeDeclaration;
170};
171
172inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
173 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
174}
175
176/// \brief Determines extra information about the tokens comprising an
177/// \c UnwrappedLine.
178class TokenAnnotator {
179public:
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000180 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex)
181 : Style(Style), SourceMgr(SourceMgr), Lex(Lex) {
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000182 }
183
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000184 void annotate(AnnotatedLine &Line);
185 void calculateFormattingInformation(AnnotatedLine &Line);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000186
187private:
188 /// \brief Calculate the penalty for splitting before \c Tok.
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000189 unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000190
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000191 bool spaceRequiredBetween(const AnnotatedLine &Line,
192 const AnnotatedToken &Left,
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000193 const AnnotatedToken &Right);
194
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000195 bool spaceRequiredBefore(const AnnotatedLine &Line,
196 const AnnotatedToken &Tok);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000197
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000198 bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000199
Daniel Jasper7fce3ab2013-02-06 14:22:40 +0000200 const FormatStyle &Style;
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000201 SourceManager &SourceMgr;
202 Lexer &Lex;
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000203};
204
Daniel Jasper7a6d09b2013-01-29 21:01:14 +0000205} // end namespace format
206} // end namespace clang
207
208#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H