clang  6.0.0svn
TokenAnnotator.h
Go to the documentation of this file.
1 //===--- 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_LIB_FORMAT_TOKENANNOTATOR_H
17 #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
18 
19 #include "UnwrappedLineParser.h"
20 #include "clang/Format/Format.h"
21 
22 namespace clang {
23 class SourceManager;
24 
25 namespace format {
26 
27 enum LineType {
30  LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
32  LT_ObjCProperty, // An @property line.
36 };
37 
39 public:
41  : First(Line.Tokens.front().Tok), Level(Line.Level),
47  assert(!Line.Tokens.empty());
48 
49  // Calculate Next and Previous for all tokens. Note that we must overwrite
50  // Next and Previous for every token, as previous formatting runs might have
51  // left them in a different state.
52  First->Previous = nullptr;
53  FormatToken *Current = First;
54  for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
55  E = Line.Tokens.end();
56  I != E; ++I) {
57  const UnwrappedLineNode &Node = *I;
58  Current->Next = I->Tok;
59  I->Tok->Previous = Current;
60  Current = Current->Next;
61  Current->Children.clear();
62  for (const auto &Child : Node.Children) {
63  Children.push_back(new AnnotatedLine(Child));
64  Current->Children.push_back(Children.back());
65  }
66  }
67  Last = Current;
68  Last->Next = nullptr;
69  }
70 
72  for (unsigned i = 0, e = Children.size(); i != e; ++i) {
73  delete Children[i];
74  }
75  FormatToken *Current = First;
76  while (Current) {
77  Current->Children.clear();
78  Current->Role.reset();
79  Current = Current->Next;
80  }
81  }
82 
83  /// \c true if this line starts with the given tokens in order, ignoring
84  /// comments.
85  template <typename... Ts> bool startsWith(Ts... Tokens) const {
86  return First && First->startsSequence(Tokens...);
87  }
88 
89  /// \c true if this line ends with the given tokens in reversed order,
90  /// ignoring comments.
91  /// For example, given tokens [T1, T2, T3, ...], the function returns true if
92  /// this line is like "... T3 T2 T1".
93  template <typename... Ts> bool endsWith(Ts... Tokens) const {
94  return Last && Last->endsSequence(Tokens...);
95  }
96 
97  /// \c true if this line looks like a function definition instead of a
98  /// function declaration. Asserts MightBeFunctionDecl.
100  assert(MightBeFunctionDecl);
101  // FIXME: Line.Last points to other characters than tok::semi
102  // and tok::lbrace.
103  return !Last->isOneOf(tok::semi, tok::comment);
104  }
105 
108 
110 
112  unsigned Level;
118 
119  /// \c True if this line should be formatted, i.e. intersects directly or
120  /// indirectly with one of the input ranges.
121  bool Affected;
122 
123  /// \c True if the leading empty lines of this line intersect with one of the
124  /// input ranges.
126 
127  /// \c True if one of this line's children intersects with an input range.
129 
130 private:
131  // Disallow copying.
132  AnnotatedLine(const AnnotatedLine &) = delete;
133  void operator=(const AnnotatedLine &) = delete;
134 };
135 
136 /// \brief Determines extra information about the tokens comprising an
137 /// \c UnwrappedLine.
139 public:
141  : Style(Style), Keywords(Keywords) {}
142 
143  /// \brief Adapts the indent levels of comment lines to the indent of the
144  /// subsequent line.
145  // FIXME: Can/should this be done in the UnwrappedLineParser?
146  void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
147 
148  void annotate(AnnotatedLine &Line);
149  void calculateFormattingInformation(AnnotatedLine &Line);
150 
151 private:
152  /// \brief Calculate the penalty for splitting before \c Tok.
153  unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
154  bool InFunctionDecl);
155 
156  bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
157  const FormatToken &Right);
158 
159  bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
160 
161  bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
162 
163  bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
164 
165  bool mustBreakForReturnType(const AnnotatedLine &Line) const;
166 
167  void printDebugInfo(const AnnotatedLine &Line);
168 
169  void calculateUnbreakableTailLengths(AnnotatedLine &Line);
170 
171  const FormatStyle &Style;
172 
173  const AdditionalKeywords &Keywords;
174 };
175 
176 } // end namespace format
177 } // end namespace clang
178 
179 #endif
bool endsSequence(A K1, Ts... Tokens) const
true if this token ends a sequence with the given tokens in order, following the Previous pointers...
Definition: FormatToken.h:325
SmallVector< UnwrappedLine, 0 > Children
bool endsWith(Ts... Tokens) const
true if this line ends with the given tokens in reversed order, ignoring comments.
std::unique_ptr< TokenRole > Role
A token can have a special role that can carry extra information about the token&#39;s formatting...
Definition: FormatToken.h:204
static LLVM_ATTRIBUTE_UNUSED void printDebugInfo(const UnwrappedLine &Line, StringRef Prefix="")
bool LeadingEmptyLinesAffected
True if the leading empty lines of this line intersect with one of the input ranges.
FormatToken * Next
The next token in the unwrapped line.
Definition: FormatToken.h:283
FormatToken * Previous
The previous token in the unwrapped line.
Definition: FormatToken.h:280
const FormatToken & Tok
bool ChildrenAffected
True if one of this line&#39;s children intersects with an input range.
An unwrapped line is a sequence of Token, that we would like to put on a single line if there was no ...
bool mightBeFunctionDefinition() const
true if this line looks like a function definition instead of a function declaration.
bool isOneOf(A K1, B K2) const
Definition: FormatToken.h:306
Determines extra information about the tokens comprising an UnwrappedLine.
std::list< UnwrappedLineNode > Tokens
The Tokens comprising this UnwrappedLine.
const AnnotatedLine * Line
SmallVector< AnnotatedLine *, 0 > Children
A wrapper around a Token storing information about the whitespace characters preceding it...
Definition: FormatToken.h:120
TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
bool Affected
True if this line should be formatted, i.e.
#define false
Definition: stdbool.h:33
Various functions to configurably format source code.
Encapsulates keywords that are context sensitive or for languages not properly supported by Clang&#39;s l...
Definition: FormatToken.h:634
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
bool startsWith(Ts... Tokens) const
true if this line starts with the given tokens in order, ignoring comments.
The FormatStyle is used to configure the formatting to follow specific guidelines.
Definition: Format.h:46
ast_type_traits::DynTypedNode Node
Dataflow Directional Tag Classes.
AnnotatedLine(const UnwrappedLine &Line)
SmallVector< AnnotatedLine *, 1 > Children
If this token starts a block, this contains all the unwrapped lines in it.
Definition: FormatToken.h:287
bool startsSequence(A K1, Ts... Tokens) const
true if this token starts a sequence with the given tokens in order, following the Next pointers...
Definition: FormatToken.h:318
const FormatStyle & Style