TokenAnnotator.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
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_FORMAT_TOKEN_ANNOTATOR_H
17#define LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
18
19#include "UnwrappedLineParser.h"
20#include "clang/Format/Format.h"
21#include <string>
22
23namespace clang {
24class SourceManager;
25
26namespace format {
27
28enum LineType {
29  LT_Invalid,
30  LT_Other,
31  LT_PreprocessorDirective,
32  LT_VirtualFunctionDecl,
33  LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
34  LT_ObjCMethodDecl,
35  LT_ObjCProperty // An @property line.
36};
37
38class AnnotatedLine {
39public:
40  AnnotatedLine(const UnwrappedLine &Line)
41      : First(Line.Tokens.front().Tok), Level(Line.Level),
42        InPPDirective(Line.InPPDirective),
43        MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
44        StartsDefinition(false), Affected(false),
45        LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
46    assert(!Line.Tokens.empty());
47
48    // Calculate Next and Previous for all tokens. Note that we must overwrite
49    // Next and Previous for every token, as previous formatting runs might have
50    // left them in a different state.
51    First->Previous = nullptr;
52    FormatToken *Current = First;
53    for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
54                                                      E = Line.Tokens.end();
55         I != E; ++I) {
56      const UnwrappedLineNode &Node = *I;
57      Current->Next = I->Tok;
58      I->Tok->Previous = Current;
59      Current = Current->Next;
60      Current->Children.clear();
61      for (SmallVectorImpl<UnwrappedLine>::const_iterator
62               I = Node.Children.begin(),
63               E = Node.Children.end();
64           I != E; ++I) {
65        Children.push_back(new AnnotatedLine(*I));
66        Current->Children.push_back(Children.back());
67      }
68    }
69    Last = Current;
70    Last->Next = nullptr;
71  }
72
73  ~AnnotatedLine() {
74    for (unsigned i = 0, e = Children.size(); i != e; ++i) {
75      delete Children[i];
76    }
77  }
78
79  FormatToken *First;
80  FormatToken *Last;
81
82  SmallVector<AnnotatedLine *, 0> Children;
83
84  LineType Type;
85  unsigned Level;
86  bool InPPDirective;
87  bool MustBeDeclaration;
88  bool MightBeFunctionDecl;
89  bool StartsDefinition;
90
91  /// \c True if this line should be formatted, i.e. intersects directly or
92  /// indirectly with one of the input ranges.
93  bool Affected;
94
95  /// \c True if the leading empty lines of this line intersect with one of the
96  /// input ranges.
97  bool LeadingEmptyLinesAffected;
98
99  /// \c True if a one of this line's children intersects with an input range.
100  bool ChildrenAffected;
101
102private:
103  // Disallow copying.
104  AnnotatedLine(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
105  void operator=(const AnnotatedLine &) LLVM_DELETED_FUNCTION;
106};
107
108/// \brief Determines extra information about the tokens comprising an
109/// \c UnwrappedLine.
110class TokenAnnotator {
111public:
112  TokenAnnotator(const FormatStyle &Style, IdentifierInfo &Ident_in)
113      : Style(Style), Ident_in(Ident_in) {}
114
115  /// \brief Adapts the indent levels of comment lines to the indent of the
116  /// subsequent line.
117  // FIXME: Can/should this be done in the UnwrappedLineParser?
118  void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
119
120  void annotate(AnnotatedLine &Line);
121  void calculateFormattingInformation(AnnotatedLine &Line);
122
123private:
124  /// \brief Calculate the penalty for splitting before \c Tok.
125  unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
126                        bool InFunctionDecl);
127
128  bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
129                            const FormatToken &Right);
130
131  bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Tok);
132
133  bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
134
135  bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
136
137  void printDebugInfo(const AnnotatedLine &Line);
138
139  void calculateUnbreakableTailLengths(AnnotatedLine &Line);
140
141  const FormatStyle &Style;
142
143  // Contextual keywords:
144  IdentifierInfo &Ident_in;
145};
146
147} // end namespace format
148} // end namespace clang
149
150#endif // LLVM_CLANG_FORMAT_TOKEN_ANNOTATOR_H
151