annotate clang/lib/Format/TokenAnnotator.h @ 173:0572611fdcc8 llvm10 llvm12

reorgnization done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 11:55:54 +0900
parents 1d019706d866
children 5f17cb93ff66
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- TokenAnnotator.h - Format C++ code ---------------------*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 ///
anatofuz
parents:
diff changeset
9 /// \file
anatofuz
parents:
diff changeset
10 /// This file implements a token annotator, i.e. creates
anatofuz
parents:
diff changeset
11 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
anatofuz
parents:
diff changeset
12 ///
anatofuz
parents:
diff changeset
13 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
14
anatofuz
parents:
diff changeset
15 #ifndef LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
anatofuz
parents:
diff changeset
16 #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
anatofuz
parents:
diff changeset
17
anatofuz
parents:
diff changeset
18 #include "UnwrappedLineParser.h"
anatofuz
parents:
diff changeset
19 #include "clang/Format/Format.h"
anatofuz
parents:
diff changeset
20
anatofuz
parents:
diff changeset
21 namespace clang {
anatofuz
parents:
diff changeset
22 class SourceManager;
anatofuz
parents:
diff changeset
23
anatofuz
parents:
diff changeset
24 namespace format {
anatofuz
parents:
diff changeset
25
anatofuz
parents:
diff changeset
26 enum LineType {
anatofuz
parents:
diff changeset
27 LT_Invalid,
anatofuz
parents:
diff changeset
28 LT_ImportStatement,
anatofuz
parents:
diff changeset
29 LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
anatofuz
parents:
diff changeset
30 LT_ObjCMethodDecl,
anatofuz
parents:
diff changeset
31 LT_ObjCProperty, // An @property line.
anatofuz
parents:
diff changeset
32 LT_Other,
anatofuz
parents:
diff changeset
33 LT_PreprocessorDirective,
anatofuz
parents:
diff changeset
34 LT_VirtualFunctionDecl
anatofuz
parents:
diff changeset
35 };
anatofuz
parents:
diff changeset
36
anatofuz
parents:
diff changeset
37 class AnnotatedLine {
anatofuz
parents:
diff changeset
38 public:
anatofuz
parents:
diff changeset
39 AnnotatedLine(const UnwrappedLine &Line)
anatofuz
parents:
diff changeset
40 : First(Line.Tokens.front().Tok), Level(Line.Level),
anatofuz
parents:
diff changeset
41 MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
anatofuz
parents:
diff changeset
42 MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
anatofuz
parents:
diff changeset
43 InPPDirective(Line.InPPDirective),
anatofuz
parents:
diff changeset
44 MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
anatofuz
parents:
diff changeset
45 IsMultiVariableDeclStmt(false), Affected(false),
anatofuz
parents:
diff changeset
46 LeadingEmptyLinesAffected(false), ChildrenAffected(false),
anatofuz
parents:
diff changeset
47 FirstStartColumn(Line.FirstStartColumn) {
anatofuz
parents:
diff changeset
48 assert(!Line.Tokens.empty());
anatofuz
parents:
diff changeset
49
anatofuz
parents:
diff changeset
50 // Calculate Next and Previous for all tokens. Note that we must overwrite
anatofuz
parents:
diff changeset
51 // Next and Previous for every token, as previous formatting runs might have
anatofuz
parents:
diff changeset
52 // left them in a different state.
anatofuz
parents:
diff changeset
53 First->Previous = nullptr;
anatofuz
parents:
diff changeset
54 FormatToken *Current = First;
anatofuz
parents:
diff changeset
55 for (std::list<UnwrappedLineNode>::const_iterator I = ++Line.Tokens.begin(),
anatofuz
parents:
diff changeset
56 E = Line.Tokens.end();
anatofuz
parents:
diff changeset
57 I != E; ++I) {
anatofuz
parents:
diff changeset
58 const UnwrappedLineNode &Node = *I;
anatofuz
parents:
diff changeset
59 Current->Next = I->Tok;
anatofuz
parents:
diff changeset
60 I->Tok->Previous = Current;
anatofuz
parents:
diff changeset
61 Current = Current->Next;
anatofuz
parents:
diff changeset
62 Current->Children.clear();
anatofuz
parents:
diff changeset
63 for (const auto &Child : Node.Children) {
anatofuz
parents:
diff changeset
64 Children.push_back(new AnnotatedLine(Child));
anatofuz
parents:
diff changeset
65 Current->Children.push_back(Children.back());
anatofuz
parents:
diff changeset
66 }
anatofuz
parents:
diff changeset
67 }
anatofuz
parents:
diff changeset
68 Last = Current;
anatofuz
parents:
diff changeset
69 Last->Next = nullptr;
anatofuz
parents:
diff changeset
70 }
anatofuz
parents:
diff changeset
71
anatofuz
parents:
diff changeset
72 ~AnnotatedLine() {
anatofuz
parents:
diff changeset
73 for (unsigned i = 0, e = Children.size(); i != e; ++i) {
anatofuz
parents:
diff changeset
74 delete Children[i];
anatofuz
parents:
diff changeset
75 }
anatofuz
parents:
diff changeset
76 FormatToken *Current = First;
anatofuz
parents:
diff changeset
77 while (Current) {
anatofuz
parents:
diff changeset
78 Current->Children.clear();
anatofuz
parents:
diff changeset
79 Current->Role.reset();
anatofuz
parents:
diff changeset
80 Current = Current->Next;
anatofuz
parents:
diff changeset
81 }
anatofuz
parents:
diff changeset
82 }
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 /// \c true if this line starts with the given tokens in order, ignoring
anatofuz
parents:
diff changeset
85 /// comments.
anatofuz
parents:
diff changeset
86 template <typename... Ts> bool startsWith(Ts... Tokens) const {
anatofuz
parents:
diff changeset
87 return First && First->startsSequence(Tokens...);
anatofuz
parents:
diff changeset
88 }
anatofuz
parents:
diff changeset
89
anatofuz
parents:
diff changeset
90 /// \c true if this line ends with the given tokens in reversed order,
anatofuz
parents:
diff changeset
91 /// ignoring comments.
anatofuz
parents:
diff changeset
92 /// For example, given tokens [T1, T2, T3, ...], the function returns true if
anatofuz
parents:
diff changeset
93 /// this line is like "... T3 T2 T1".
anatofuz
parents:
diff changeset
94 template <typename... Ts> bool endsWith(Ts... Tokens) const {
anatofuz
parents:
diff changeset
95 return Last && Last->endsSequence(Tokens...);
anatofuz
parents:
diff changeset
96 }
anatofuz
parents:
diff changeset
97
anatofuz
parents:
diff changeset
98 /// \c true if this line looks like a function definition instead of a
anatofuz
parents:
diff changeset
99 /// function declaration. Asserts MightBeFunctionDecl.
anatofuz
parents:
diff changeset
100 bool mightBeFunctionDefinition() const {
anatofuz
parents:
diff changeset
101 assert(MightBeFunctionDecl);
anatofuz
parents:
diff changeset
102 // Try to determine if the end of a stream of tokens is either the
anatofuz
parents:
diff changeset
103 // Definition or the Declaration for a function. It does this by looking for
anatofuz
parents:
diff changeset
104 // the ';' in foo(); and using that it ends with a ; to know this is the
anatofuz
parents:
diff changeset
105 // Definition, however the line could end with
anatofuz
parents:
diff changeset
106 // foo(); /* comment */
anatofuz
parents:
diff changeset
107 // or
anatofuz
parents:
diff changeset
108 // foo(); // comment
anatofuz
parents:
diff changeset
109 // or
anatofuz
parents:
diff changeset
110 // foo() // comment
anatofuz
parents:
diff changeset
111 // endsWith() ignores the comment.
anatofuz
parents:
diff changeset
112 return !endsWith(tok::semi);
anatofuz
parents:
diff changeset
113 }
anatofuz
parents:
diff changeset
114
anatofuz
parents:
diff changeset
115 /// \c true if this line starts a namespace definition.
anatofuz
parents:
diff changeset
116 bool startsWithNamespace() const {
anatofuz
parents:
diff changeset
117 return startsWith(tok::kw_namespace) || startsWith(TT_NamespaceMacro) ||
anatofuz
parents:
diff changeset
118 startsWith(tok::kw_inline, tok::kw_namespace) ||
anatofuz
parents:
diff changeset
119 startsWith(tok::kw_export, tok::kw_namespace);
anatofuz
parents:
diff changeset
120 }
anatofuz
parents:
diff changeset
121
anatofuz
parents:
diff changeset
122 FormatToken *First;
anatofuz
parents:
diff changeset
123 FormatToken *Last;
anatofuz
parents:
diff changeset
124
anatofuz
parents:
diff changeset
125 SmallVector<AnnotatedLine *, 0> Children;
anatofuz
parents:
diff changeset
126
anatofuz
parents:
diff changeset
127 LineType Type;
anatofuz
parents:
diff changeset
128 unsigned Level;
anatofuz
parents:
diff changeset
129 size_t MatchingOpeningBlockLineIndex;
anatofuz
parents:
diff changeset
130 size_t MatchingClosingBlockLineIndex;
anatofuz
parents:
diff changeset
131 bool InPPDirective;
anatofuz
parents:
diff changeset
132 bool MustBeDeclaration;
anatofuz
parents:
diff changeset
133 bool MightBeFunctionDecl;
anatofuz
parents:
diff changeset
134 bool IsMultiVariableDeclStmt;
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 /// \c True if this line should be formatted, i.e. intersects directly or
anatofuz
parents:
diff changeset
137 /// indirectly with one of the input ranges.
anatofuz
parents:
diff changeset
138 bool Affected;
anatofuz
parents:
diff changeset
139
anatofuz
parents:
diff changeset
140 /// \c True if the leading empty lines of this line intersect with one of the
anatofuz
parents:
diff changeset
141 /// input ranges.
anatofuz
parents:
diff changeset
142 bool LeadingEmptyLinesAffected;
anatofuz
parents:
diff changeset
143
anatofuz
parents:
diff changeset
144 /// \c True if one of this line's children intersects with an input range.
anatofuz
parents:
diff changeset
145 bool ChildrenAffected;
anatofuz
parents:
diff changeset
146
anatofuz
parents:
diff changeset
147 unsigned FirstStartColumn;
anatofuz
parents:
diff changeset
148
anatofuz
parents:
diff changeset
149 private:
anatofuz
parents:
diff changeset
150 // Disallow copying.
anatofuz
parents:
diff changeset
151 AnnotatedLine(const AnnotatedLine &) = delete;
anatofuz
parents:
diff changeset
152 void operator=(const AnnotatedLine &) = delete;
anatofuz
parents:
diff changeset
153 };
anatofuz
parents:
diff changeset
154
anatofuz
parents:
diff changeset
155 /// Determines extra information about the tokens comprising an
anatofuz
parents:
diff changeset
156 /// \c UnwrappedLine.
anatofuz
parents:
diff changeset
157 class TokenAnnotator {
anatofuz
parents:
diff changeset
158 public:
anatofuz
parents:
diff changeset
159 TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
anatofuz
parents:
diff changeset
160 : Style(Style), Keywords(Keywords) {}
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 /// Adapts the indent levels of comment lines to the indent of the
anatofuz
parents:
diff changeset
163 /// subsequent line.
anatofuz
parents:
diff changeset
164 // FIXME: Can/should this be done in the UnwrappedLineParser?
anatofuz
parents:
diff changeset
165 void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines);
anatofuz
parents:
diff changeset
166
anatofuz
parents:
diff changeset
167 void annotate(AnnotatedLine &Line);
anatofuz
parents:
diff changeset
168 void calculateFormattingInformation(AnnotatedLine &Line);
anatofuz
parents:
diff changeset
169
anatofuz
parents:
diff changeset
170 private:
anatofuz
parents:
diff changeset
171 /// Calculate the penalty for splitting before \c Tok.
anatofuz
parents:
diff changeset
172 unsigned splitPenalty(const AnnotatedLine &Line, const FormatToken &Tok,
anatofuz
parents:
diff changeset
173 bool InFunctionDecl);
anatofuz
parents:
diff changeset
174
anatofuz
parents:
diff changeset
175 bool spaceRequiredBeforeParens(const FormatToken &Right) const;
anatofuz
parents:
diff changeset
176
anatofuz
parents:
diff changeset
177 bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
anatofuz
parents:
diff changeset
178 const FormatToken &Right);
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Right);
anatofuz
parents:
diff changeset
181
anatofuz
parents:
diff changeset
182 bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
anatofuz
parents:
diff changeset
183
anatofuz
parents:
diff changeset
184 bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
anatofuz
parents:
diff changeset
185
anatofuz
parents:
diff changeset
186 bool mustBreakForReturnType(const AnnotatedLine &Line) const;
anatofuz
parents:
diff changeset
187
anatofuz
parents:
diff changeset
188 void printDebugInfo(const AnnotatedLine &Line);
anatofuz
parents:
diff changeset
189
anatofuz
parents:
diff changeset
190 void calculateUnbreakableTailLengths(AnnotatedLine &Line);
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 const FormatStyle &Style;
anatofuz
parents:
diff changeset
193
anatofuz
parents:
diff changeset
194 const AdditionalKeywords &Keywords;
anatofuz
parents:
diff changeset
195 };
anatofuz
parents:
diff changeset
196
anatofuz
parents:
diff changeset
197 } // end namespace format
anatofuz
parents:
diff changeset
198 } // end namespace clang
anatofuz
parents:
diff changeset
199
anatofuz
parents:
diff changeset
200 #endif