1 //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This file implements a token annotator, i.e. creates
12 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
17 #define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
19 #include "UnwrappedLineParser.h"
20 #include "clang/Basic/OperatorPrecedence.h"
21 #include "clang/Format/Format.h"
35 TT_CtorInitializerColon,
36 TT_ImplicitStringLiteral,
44 TT_ObjCMethodSpecifier,
47 TT_OverloadedOperatorLParen,
48 TT_PointerOrReference,
49 TT_PureVirtualSpecifier,
50 TT_RangeBasedForLoopColon,
54 TT_TrailingUnaryOperator,
63 LT_PreprocessorDirective,
64 LT_VirtualFunctionDecl,
65 LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
67 LT_ObjCProperty // An @property line.
70 class AnnotatedToken {
72 explicit AnnotatedToken(const FormatToken &FormatTok)
73 : FormatTok(FormatTok), Type(TT_Unknown), SpacesRequiredBefore(0),
74 CanBreakBefore(false), MustBreakBefore(false),
75 ClosesTemplateDeclaration(false), MatchingParen(NULL),
76 ParameterCount(1), BindingStrength(0), SplitPenalty(0),
77 LongestObjCSelectorName(0), Parent(NULL), FakeLParens(0),
81 bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
82 bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
84 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
85 return FormatTok.Tok.isObjCAtKeyword(Kind);
88 FormatToken FormatTok;
92 unsigned SpacesRequiredBefore;
96 bool ClosesTemplateDeclaration;
98 AnnotatedToken *MatchingParen;
100 /// \brief Number of parameters, if this is "(", "[" or "<".
102 /// This is initialized to 1 as we don't need to distinguish functions with
103 /// 0 parameters from functions with 1 parameter. Thus, we can simply count
104 /// the number of commas.
105 unsigned ParameterCount;
107 /// \brief The total length of the line up to and including this token.
108 unsigned TotalLength;
110 // FIXME: Come up with a 'cleaner' concept.
111 /// \brief The binding strength of a token. This is a combined value of
112 /// operator precedence, parenthesis nesting, etc.
113 unsigned BindingStrength;
115 /// \brief Penalty for inserting a line break before this token.
116 unsigned SplitPenalty;
118 /// \brief If this is the first ObjC selector name in an ObjC method
119 /// definition or call, this contains the length of the longest name.
120 unsigned LongestObjCSelectorName;
122 std::vector<AnnotatedToken> Children;
123 AnnotatedToken *Parent;
125 /// \brief Insert this many fake ( before this token for correct indentation.
126 unsigned FakeLParens;
127 /// \brief Insert this many fake ) after this token for correct indentation.
128 unsigned FakeRParens;
130 const AnnotatedToken *getPreviousNoneComment() const {
131 AnnotatedToken *Tok = Parent;
132 while (Tok != NULL && Tok->is(tok::comment))
138 class AnnotatedLine {
140 AnnotatedLine(const UnwrappedLine &Line)
141 : First(Line.Tokens.front()), Level(Line.Level),
142 InPPDirective(Line.InPPDirective),
143 MustBeDeclaration(Line.MustBeDeclaration) {
144 assert(!Line.Tokens.empty());
145 AnnotatedToken *Current = &First;
146 for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
147 E = Line.Tokens.end();
149 Current->Children.push_back(AnnotatedToken(*I));
150 Current->Children[0].Parent = Current;
151 Current = &Current->Children[0];
155 AnnotatedLine(const AnnotatedLine &Other)
156 : First(Other.First), Type(Other.Type), Level(Other.Level),
157 InPPDirective(Other.InPPDirective),
158 MustBeDeclaration(Other.MustBeDeclaration) {
160 while (!Last->Children.empty()) {
161 Last->Children[0].Parent = Last;
162 Last = &Last->Children[0];
166 AnnotatedToken First;
167 AnnotatedToken *Last;
172 bool MustBeDeclaration;
175 inline prec::Level getPrecedence(const AnnotatedToken &Tok) {
176 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
179 /// \brief Determines extra information about the tokens comprising an
180 /// \c UnwrappedLine.
181 class TokenAnnotator {
183 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
184 IdentifierInfo &Ident_in)
185 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Ident_in(Ident_in) {
188 void annotate(AnnotatedLine &Line);
189 void calculateFormattingInformation(AnnotatedLine &Line);
192 /// \brief Calculate the penalty for splitting before \c Tok.
193 unsigned splitPenalty(const AnnotatedLine &Line, const AnnotatedToken &Tok);
195 bool spaceRequiredBetween(const AnnotatedLine &Line,
196 const AnnotatedToken &Left,
197 const AnnotatedToken &Right);
199 bool spaceRequiredBefore(const AnnotatedLine &Line,
200 const AnnotatedToken &Tok);
202 bool canBreakBefore(const AnnotatedLine &Line, const AnnotatedToken &Right);
204 const FormatStyle &Style;
205 SourceManager &SourceMgr;
208 // Contextual keywords:
209 IdentifierInfo &Ident_in;
212 } // end namespace format
213 } // end namespace clang
215 #endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H