@@ -43,26 +43,35 @@ enum class PrintNameContext {
43
43
// / not escaped.
44
44
FunctionParameterExternal,
45
45
FunctionParameterLocal,
46
+ // / Tuple element context, similar to \c FunctionParameterExternal.
47
+ TupleElement,
48
+ // / Attributes, which are escaped as 'Normal', but differentiated for
49
+ // / the purposes of printName* callbacks.
50
+ Attribute,
46
51
};
47
52
48
- // / Describes the kind of parameter-like entity being printed.
53
+ // / Describes the kind of structured entity being printed.
54
+ // /
55
+ // / This includes printables with sub-structure that cannot be completely
56
+ // / handled by the printDeclPre/printDeclPost callbacks.
49
57
// / E.g.
50
58
// / \code
51
59
// / func foo(<FunctionParameter>x: Int = 2</FunctionParameter>, ...)
52
60
// / \endcode
53
- enum class PrintParameterKind {
61
+ enum class PrintStructureKind {
62
+ GenericParameter,
63
+ GenericRequirement,
54
64
FunctionParameter,
65
+ FunctionType,
66
+ FunctionReturnType,
67
+ BuiltinAttribute,
68
+ TupleElement,
55
69
};
56
70
57
71
// / An abstract class used to print an AST.
58
72
class ASTPrinter {
59
73
unsigned CurrentIndentation = 0 ;
60
74
unsigned PendingNewlines = 0 ;
61
- // / The queue of pending printDeclPre callbacks that will be run when we print
62
- // / a non-whitespace character.
63
- SmallVector<const Decl *, 4 > PendingDeclPreCallbacks;
64
- const Decl *PendingDeclLocCallback = nullptr ;
65
- Optional<PrintNameContext> PendingNamePreCallback;
66
75
const NominalTypeDecl *SynthesizeTarget = nullptr ;
67
76
68
77
void printTextImpl (StringRef Text);
@@ -117,10 +126,14 @@ class ASTPrinter {
117
126
virtual void printSynthesizedExtensionPost (const ExtensionDecl *ED,
118
127
const NominalTypeDecl *NTD) {}
119
128
120
- // / Called before printing a parameter-like entity.
121
- virtual void printParameterPre (PrintParameterKind Kind) {}
122
- // / Called after printing a parameter-like entity.
123
- virtual void printParameterPost (PrintParameterKind Kind) {}
129
+ // / Called before printing a structured entity.
130
+ // /
131
+ // / Callers should use callPrintStructurePre().
132
+ virtual void printStructurePre (PrintStructureKind Kind,
133
+ const Decl *D = nullptr ) {}
134
+ // / Called after printing a structured entity.
135
+ virtual void printStructurePost (PrintStructureKind Kind,
136
+ const Decl *D = nullptr ) {}
124
137
125
138
// / Called before printing a name in the given context.
126
139
virtual void printNamePre (PrintNameContext Context) {}
@@ -153,6 +166,14 @@ class ASTPrinter {
153
166
printNamePost (PrintNameContext::Keyword);
154
167
}
155
168
169
+ void printAttrName (StringRef Name, bool needAt = false ) {
170
+ callPrintNamePre (PrintNameContext::Attribute);
171
+ if (needAt)
172
+ *this << " @" ;
173
+ *this << Name;
174
+ printNamePost (PrintNameContext::Attribute);
175
+ }
176
+
156
177
void printName (Identifier Name,
157
178
PrintNameContext Context = PrintNameContext::Normal);
158
179
@@ -171,51 +192,52 @@ class ASTPrinter {
171
192
PendingNewlines++;
172
193
}
173
194
195
+ void forceNewlines () {
196
+ if (PendingNewlines > 0 ) {
197
+ llvm::SmallString<16 > Str;
198
+ for (unsigned i = 0 ; i != PendingNewlines; ++i)
199
+ Str += ' \n ' ;
200
+ PendingNewlines = 0 ;
201
+ printText (Str);
202
+ printIndent ();
203
+ }
204
+ }
205
+
174
206
virtual void printIndent ();
175
207
176
208
// MARK: Callback interface wrappers that perform ASTPrinter bookkeeping.
177
209
178
- // / Schedule a \c printDeclPre callback to be called as soon as a
179
- // / non-whitespace character is printed.
180
- void callPrintDeclPre (const Decl *D) {
181
- PendingDeclPreCallbacks.emplace_back (D);
182
- }
210
+ // / Make a callback to printDeclPre(), performing any necessary bookeeping.
211
+ void callPrintDeclPre (const Decl *D);
183
212
184
213
// / Make a callback to printDeclPost(), performing any necessary bookeeping.
185
214
void callPrintDeclPost (const Decl *D) {
186
- if (!PendingDeclPreCallbacks.empty () &&
187
- PendingDeclPreCallbacks.back () == D) {
188
- // Nothing printed for D; skip both pre and post callbacks.
189
- // Ideally we wouldn't get as far as setting up the callback if we aren't
190
- // going to print anything, but currently that would mean walking the
191
- // children of top-level code decls to determine.
192
- PendingDeclPreCallbacks.pop_back ();
193
- return ;
194
- }
195
215
printDeclPost (D);
196
216
}
197
217
198
218
// / Make a callback to avoidPrintDeclPost(), performing any necessary
199
219
// / bookkeeping.
200
220
void callAvoidPrintDeclPost (const Decl *D) {
201
- assert ((PendingDeclPreCallbacks.empty () ||
202
- PendingDeclPreCallbacks.back () != D) &&
203
- " printDeclPre should not be called on avoided decl" );
204
221
avoidPrintDeclPost (D);
205
222
}
206
223
207
- // / Schedule a \c printDeclLoc callback to be called as soon as a
208
- // / non-whitespace character is printed.
224
+ // / Make a callback to printDeclLoc(), performing any necessary bookeeping.
209
225
void callPrintDeclLoc (const Decl *D) {
210
- assert (!PendingDeclLocCallback && " unexpected nested callPrintDeclLoc " );
211
- PendingDeclLocCallback = D ;
226
+ forceNewlines ( );
227
+ printDeclLoc (D) ;
212
228
}
213
229
214
- // / Schedule a \c printNamePre callback to be called as soon as a
215
- // / non-whitespace character is printed.
230
+ // / Make a callback to printNamePre(), performing any necessary bookeeping.
216
231
void callPrintNamePre (PrintNameContext Context) {
217
- assert (!PendingNamePreCallback && " unexpected nested callPrintNamePre" );
218
- PendingNamePreCallback = Context;
232
+ forceNewlines ();
233
+ printNamePre (Context);
234
+ }
235
+
236
+ // / Make a callback to printStructurePre(), performing any necessary
237
+ // / bookkeeping.
238
+ void callPrintStructurePre (PrintStructureKind Kind, const Decl *D = nullptr ) {
239
+ forceNewlines ();
240
+ printStructurePre (Kind, D);
219
241
}
220
242
221
243
// / To sanitize a malformed utf8 string to a well-formed one.
0 commit comments