1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmldomastdumper_p.h"
5#include "qqmldomerrormessage_p.h"
6#include <QtQml/private/qqmljsast_p.h>
7#include <QtCore/QDebug>
8#include <QtCore/QString>
9#include <QtCore/QTextStream>
10
11QT_BEGIN_NAMESPACE
12
13namespace QQmlJS {
14namespace Dom {
15using namespace AST;
16/*!
17\internal
18\enum QQmlJS::AstDumperOption
19
20This enum type specifies the options for the AstDumper.
21The values can be combined with the '|' operator, and checked using the '&' operator.
22
23\value None
24 Default dumping options
25\value NoLocations
26 Does not dump SourceLocations, allowing one to compare equivalent AST
27 generated by code formatted differently
28\value NoAnnotations
29 Does not dump annotations
30\value DumpNode
31 Does dump a <Node></Node> in preVisit/postVisit
32*/
33
34/*!
35\internal
36\class QQmlJS::AstDumper
37\brief Dumps or compares AST in an xml like format, mostly for testing/debugging
38
39Initialize it with a lambda that dumps a string, and configure it with .setX methods.
40If \l{indent} is set to a non zero value the xml is indented by that amount, and
41\l{baseIndent} is the initial indent.
42If \l{emitNode} is true the node tag is emitted in the preVisit/postVisit.
43If \l{emitLocation} is true the SourceLocations are emitted.
44If \l{emitAnnotations} is true annotations are emitted
45
46The implementation has unnecessary roundtrips to QString, but it is supposed to be used
47for debugging purposes...
48
49Probably you will not use the visitor at all but rather the static method diff or
50the qDebug() and ostream operator << that use the visitor...
51
52\fn AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, AstDumperOptions opt, int indent)
53
54\brief compares the two AST::Node n1 and n2 and returns a string describing their first difference
55
56If there are no differences the empty string is returned, so .isEmpty() can be use to check
57for no differences.
58\l{nContext} decides how much context is printed out.
59
60*/
61
62// no export, just a supporting class...
63class AstDumper: public AST::BaseVisitor
64{
65public:
66 AstDumper(const std::function<void(QStringView)> &dumper,
67 AstDumperOptions options = AstDumperOption::None, int indent = 1, int baseIndent = 0,
68 function_ref<QStringView(SourceLocation)> loc2str = &noStr)
69 : dumper(dumper), options(options), indent(indent), baseIndent(baseIndent), loc2str(loc2str)
70 {
71 }
72
73private:
74 void start(QStringView str) {
75 dumper(QString::fromLatin1(ba: " ").repeated(times: baseIndent));
76 dumper(u"<");
77 dumper(str);
78 dumper(u">\n");
79 baseIndent += indent;
80 }
81
82 void stop(QStringView str) {
83 baseIndent -= indent;
84 dumper(QString::fromLatin1(ba: " ").repeated(times: baseIndent));
85 dumper(u"</");
86 dumper(str);
87 dumper(u">\n");
88 }
89
90 QString quotedString(const QString &s) {
91 QString res(s);
92 return QStringLiteral(u"\"") + res
93 .replace(before: QLatin1String("\\"), after: QLatin1String("\\\\"))
94 .replace(before: QLatin1String("\""), after: QLatin1String("\\\"")) + QLatin1String("\"");
95 }
96
97 QString quotedString(QStringView s) {
98 return quotedString(s: s.toString());
99 }
100
101 QString loc(const SourceLocation &s, bool trim = false) {
102 QString tokenStr;
103 if (s.length > 0)
104 tokenStr = loc2str(s).toString()
105 .replace(before: QLatin1String("\\"), after: QLatin1String("\\\\"))
106 .replace(before: QLatin1String("\""),after: QLatin1String("\\\""));
107 if (trim)
108 tokenStr = tokenStr.trimmed();
109 if (noLocations() || s == SourceLocation())
110 return QLatin1String("\"%1\"").arg(args&: tokenStr);
111 else {
112 return QLatin1String("\"off:%1 len:%2 l:%3 c:%4 %5\"").arg(args: QString::number(s.offset), args: QString::number(s.length), args: QString::number(s.startLine), args: QString::number(s.startColumn), args&: tokenStr);
113 }
114 }
115
116 QString semicolonToken(const SourceLocation &s)
117 {
118 if (options & AstDumperOption::SloppyCompare)
119 return QString();
120 return QLatin1String(" semicolonToken=") + loc(s);
121 }
122
123 QString boolStr(bool v) { return (v ? quotedString(s: u"true"): quotedString(s: u"false")); }
124public:
125 bool preVisit(Node *) override { if (dumpNode()) start(str: u"Node"); return true; }
126 void postVisit(Node *) override { if (dumpNode()) stop(str: u"Node"); }
127
128 // Ui
129 bool visit(UiProgram *) override { start(str: u"UiProgram"); return true; }
130 void endVisit(AST::UiProgram *) override { stop(str: u"UiProgram"); }
131
132 bool visit(UiHeaderItemList *) override { start(str: u"UiHeaderItemList"); return true; }
133 void endVisit(AST::UiHeaderItemList *) override { stop(str: u"UiHeaderItemList"); }
134
135#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
136 bool visit(UiPragmaValueList *el) override {
137 start(str: QLatin1String("UiPragmaValueList value=%1").arg(args&: el->value));
138 return true;
139 }
140 void endVisit(AST::UiPragmaValueList *) override { stop(str: u"UiPragmaValueList"); }
141#endif
142
143 bool visit(UiPragma *el) override {
144 start(str: QLatin1String("UiPragma name=%1 pragmaToken=%2%3")
145 .arg(args: quotedString(s: el->name), args: loc(s: el->pragmaToken),
146 args: semicolonToken(s: el->semicolonToken)));
147 return true;
148 }
149 void endVisit(AST::UiPragma *) override { stop(str: u"UiPragma"); }
150
151 bool visit(UiImport *el) override {
152 start(str: QLatin1String("UiImport fileName=%1 importId=%2 importToken=%3 fileNameToken=%4 "
153 "asToken=%5 importIdToken=%6%7")
154 .arg(args: quotedString(s: el->fileName), args: quotedString(s: el->importId),
155 args: loc(s: el->importToken), args: loc(s: el->fileNameToken), args: loc(s: el->asToken),
156 args: loc(s: el->importIdToken), args: semicolonToken(s: el->semicolonToken)));
157 return true;
158 }
159 void endVisit(AST::UiImport *el) override {
160 Node::accept(node: el->version, visitor: this);
161 stop(str: u"UiImport");
162 }
163
164 bool visit(UiPublicMember *el) override {
165 QString typeStr = ((el->type == UiPublicMember::Signal) ? QLatin1String("Signal") :
166 (el->type == UiPublicMember::Property) ? QLatin1String("Property") : QLatin1String("Unexpected(%1)").arg(args: QString::number(el->type)));
167 start(str: QLatin1String("UiPublicMember type=%1 typeModifier=%2 name=%3 isDefaultMember=%4 "
168 "isReadonlyMember=%5 isRequired=%6 "
169 "defaultToken=%7 readonlyToken=%8 propertyToken=%9 requiredToken=%10 "
170 "finalToken=%11 typeModifierToken=%12 typeToken=%13 "
171 "identifierToken=%14 colonToken=%15%16")
172 .arg(args: quotedString(s: typeStr), args: quotedString(s: el->typeModifier),
173 args: quotedString(s: el->name), args: boolStr(v: el->isDefaultMember()),
174 args: boolStr(v: el->isReadonly()), args: boolStr(v: el->isRequired()),
175 args: loc(s: el->defaultToken()), args: loc(s: el->readonlyToken()),
176 args: loc(s: el->propertyToken()), args: loc(s: el->requiredToken()),
177 args: loc(s: el->finalToken()), args: loc(s: el->typeModifierToken), args: loc(s: el->typeToken),
178 args: loc(s: el->identifierToken), args: loc(s: el->colonToken),
179 args: semicolonToken(s: el->semicolonToken)));
180 if (!noAnnotations()) // put annotations inside the node they refer to
181 Node::accept(node: el->annotations, visitor: this);
182 Node::accept(node: el->memberType, visitor: this);
183 return true;
184 }
185 void endVisit(AST::UiPublicMember *el) override {
186 Node::accept(node: el->parameters, visitor: this);
187 stop(str: u"UiPublicMember");
188 }
189
190 bool visit(AST::UiSourceElement *el) override {
191 start(str: u"UiSourceElement");
192 if (!noAnnotations()) // put annotations inside the node they refer to
193 Node::accept(node: el->annotations, visitor: this);
194 return true;
195 }
196 void endVisit(AST::UiSourceElement *) override { stop(str: u"UiSourceElement"); }
197
198 bool visit(AST::UiObjectDefinition *el) override {
199 start(str: u"UiObjectDefinition");
200 if (!noAnnotations()) // put annotations inside the node they refer to
201 Node::accept(node: el->annotations, visitor: this);
202 return true;
203 }
204 void endVisit(AST::UiObjectDefinition *) override { stop(str: u"UiObjectDefinition"); }
205
206 bool visit(AST::UiObjectInitializer *el) override {
207 start(str: QLatin1String("UiObjectInitializer lbraceToken=%1 rbraceToken=%2")
208 .arg(args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken)));
209 return true;
210 }
211 void endVisit(AST::UiObjectInitializer *) override { stop(str: u"UiObjectInitializer"); }
212
213 bool visit(AST::UiObjectBinding *el) override {
214 start(str: QLatin1String("UiObjectBinding colonToken=%1 hasOnToken=%2")
215 .arg(args: loc(s: el->colonToken), args: boolStr(v: el->hasOnToken)));
216 if (!noAnnotations()) // put annotations inside the node they refer to
217 Node::accept(node: el->annotations, visitor: this);
218 return true;
219 }
220 void endVisit(AST::UiObjectBinding *) override { stop(str: u"UiObjectBinding"); }
221
222 bool visit(AST::UiScriptBinding *el) override {
223 start(str: QLatin1String("UiScriptBinding colonToken=%1")
224 .arg(args: loc(s: el->colonToken)));
225 if (!noAnnotations()) // put annotations inside the node they refer to
226 Node::accept(node: el->annotations, visitor: this);
227 return true;
228 }
229 void endVisit(AST::UiScriptBinding *) override { stop(str: u"UiScriptBinding"); }
230
231 bool visit(AST::UiArrayBinding *el) override {
232 start(str: QLatin1String("UiArrayBinding colonToken=%1 lbracketToken=%2 rbracketToken=%3")
233 .arg(args: loc(s: el->colonToken), args: loc(s: el->lbracketToken), args: loc(s: el->rbracketToken)));
234 if (!noAnnotations()) // put annotations inside the node they refer to
235 Node::accept(node: el->annotations, visitor: this);
236 return true;
237 }
238 void endVisit(AST::UiArrayBinding *) override { stop(str: u"UiArrayBinding"); }
239
240 bool visit(AST::UiParameterList *el) override {
241 start(str: QLatin1String("UiParameterList name=%1 commaToken=%2 propertyTypeToken=%3 identifierToken=%4 colonToken=%5")
242 .arg(args: quotedString(s: el->name), args: loc(s: el->commaToken), args: loc(s: el->propertyTypeToken), args: loc(s: el->identifierToken), args: loc(s: el->colonToken)));
243 Node::accept(node: el->type, visitor: this);
244 return true;
245 }
246 void endVisit(AST::UiParameterList *el) override {
247 stop(str: u"UiParameterList");
248 Node::accept(node: el->next, visitor: this); // put other args at the same level as this one...
249 }
250
251 bool visit(AST::UiObjectMemberList *) override { start(str: u"UiObjectMemberList"); return true; }
252 void endVisit(AST::UiObjectMemberList *) override { stop(str: u"UiObjectMemberList"); }
253
254 bool visit(AST::UiArrayMemberList *el) override {
255 start(str: QLatin1String("UiArrayMemberList commaToken=%1")
256 .arg(args: loc(s: el->commaToken)));
257 return true;
258 }
259 void endVisit(AST::UiArrayMemberList *) override { stop(str: u"UiArrayMemberList"); }
260
261 bool visit(AST::UiQualifiedId *el) override {
262 start(str: QLatin1String("UiQualifiedId name=%1 identifierToken=%2")
263 .arg(args: quotedString(s: el->name), args: loc(s: el->identifierToken)));
264 Node::accept(node: el->next, visitor: this);
265 return true;
266 }
267 void endVisit(AST::UiQualifiedId *) override { stop(str: u"UiQualifiedId"); }
268
269 bool visit(AST::UiEnumDeclaration *el) override {
270 start(str: QLatin1String("UiEnumDeclaration enumToken=%1 rbraceToken=%2 name=%3")
271 .arg(args: loc(s: el->enumToken), args: loc(s: el->rbraceToken), args: quotedString(s: el->name)));
272 if (!noAnnotations()) // put annotations inside the node they refer to
273 Node::accept(node: el->annotations, visitor: this);
274 return true;
275 }
276 void endVisit(AST::UiEnumDeclaration *) override { stop(str: u"UiEnumDeclaration"); }
277
278 bool visit(AST::UiEnumMemberList *el) override {
279 start(str: QLatin1String("UiEnumMemberList member=%1 value=%2 memberToken=%3 valueToken=%4")
280 .arg(args: quotedString(s: el->member), args: quotedString(s: QString::number(el->value)), args: loc(s: el->memberToken), args: loc(s: el->valueToken)));
281 return true;
282 }
283 void endVisit(AST::UiEnumMemberList *el) override {
284 stop(str: u"UiEnumMemberList");
285 Node::accept(node: el->next, visitor: this); // put other enum members at the same level as this one...
286 }
287
288 bool visit(AST::UiVersionSpecifier *el) override {
289 start(str: QLatin1String("UiVersionSpecifier majorVersion=%1 minorVersion=%2 majorToken=%3 minorToken=%4")
290 .arg(args: quotedString(s: QString::number(el->version.majorVersion())),
291 args: quotedString(s: QString::number(el->version.minorVersion())),
292 args: loc(s: el->majorToken), args: loc(s: el->minorToken)));
293 return true;
294 }
295 void endVisit(AST::UiVersionSpecifier *) override { stop(str: u"UiVersionSpecifier"); }
296
297 bool visit(AST::UiInlineComponent *el) override {
298 start(str: QLatin1String("UiInlineComponent name=%1 componentToken=%2")
299 .arg(args: quotedString(s: el->name), args: loc(s: el->componentToken)));
300 if (!noAnnotations()) // put annotations inside the node they refer to
301 Node::accept(node: el->annotations, visitor: this);
302 return true;
303 }
304 void endVisit(AST::UiInlineComponent *) override { stop(str: u"UiInlineComponent"); }
305
306 bool visit(UiRequired *el) override {
307 start(str: QLatin1String("UiRequired name=%1 requiredToken=%2%3")
308 .arg(args: quotedString(s: el->name), args: loc(s: el->requiredToken),
309 args: semicolonToken(s: el->semicolonToken)));
310 return true;
311 }
312 void endVisit(UiRequired *) override { stop(str: u"UiRequired"); }
313
314 bool visit(UiAnnotation *) override {
315 start(str: u"UiAnnotation");
316 return true;
317 }
318 void endVisit(UiAnnotation *) override { stop(str: u"UiAnnotation"); }
319
320 bool visit(UiAnnotationList *) override {
321 start(str: u"UiAnnotationList");
322 return true;
323 }
324 void endVisit(UiAnnotationList *) override { stop(str: u"UiAnnotationList"); }
325
326 // QQmlJS
327 bool visit(AST::TypeExpression *) override {
328 start(str: u"TypeExpression");
329 return true;
330 }
331 void endVisit(AST::TypeExpression *) override { stop(str: u"TypeExpression"); }
332
333 bool visit(AST::ThisExpression *el) override {
334 start(str: QLatin1String("ThisExpression thisToken=%1")
335 .arg(args: loc(s: el->thisToken)));
336 return true;
337 }
338 void endVisit(AST::ThisExpression *) override { stop(str: u"ThisExpression"); }
339
340 bool visit(AST::IdentifierExpression *el) override {
341 start(str: QLatin1String("IdentifierExpression name=%1 identifierToken=%2")
342 .arg(args: quotedString(s: el->name), args: loc(s: el->identifierToken)));
343 return true;
344 }
345 void endVisit(AST::IdentifierExpression *) override { stop(str: u"IdentifierExpression"); }
346
347 bool visit(AST::NullExpression *el) override {
348 start(str: QLatin1String("NullExpression nullToken=%1")
349 .arg(args: loc(s: el->nullToken)));
350 return true;
351 }
352 void endVisit(AST::NullExpression *) override { stop(str: u"NullExpression"); }
353
354 bool visit(AST::TrueLiteral *el) override {
355 start(str: QLatin1String("TrueLiteral trueToken=%1")
356 .arg(args: loc(s: el->trueToken)));
357 return true;
358 }
359 void endVisit(AST::TrueLiteral *) override { stop(str: u"TrueLiteral"); }
360
361 bool visit(AST::FalseLiteral *el) override {
362 start(str: QLatin1String("FalseLiteral falseToken=%1")
363 .arg(args: loc(s: el->falseToken)));
364 return true;
365 }
366 void endVisit(AST::FalseLiteral *) override { stop(str: u"FalseLiteral"); }
367
368 bool visit(AST::SuperLiteral *el) override {
369 start(str: QLatin1String("SuperLiteral superToken=%1")
370 .arg(args: loc(s: el->superToken)));
371 return true;
372 }
373 void endVisit(AST::SuperLiteral *) override { stop(str: u"SuperLiteral"); }
374
375 bool visit(AST::StringLiteral *el) override {
376 start(str: QLatin1String("StringLiteral value=%1 literalToken=%2")
377 .arg(args: quotedString(s: el->value), args: loc(s: el->literalToken)));
378 return true;
379 }
380 void endVisit(AST::StringLiteral *) override { stop(str: u"StringLiteral"); }
381
382 bool visit(AST::TemplateLiteral *el) override {
383 start(str: QLatin1String("TemplateLiteral value=%1 rawValue=%2 literalToken=%3")
384 .arg(args: quotedString(s: el->value), args: quotedString(s: el->rawValue), args: loc(s: el->literalToken)));
385 Node::accept(node: el->expression, visitor: this);
386 return true;
387 }
388 void endVisit(AST::TemplateLiteral *) override { stop(str: u"TemplateLiteral"); }
389
390 bool visit(AST::NumericLiteral *el) override {
391 start(str: QLatin1String("NumericLiteral value=%1 literalToken=%2")
392 .arg(args: quotedString(s: QString::number(el->value)), args: loc(s: el->literalToken)));
393 return true;
394 }
395 void endVisit(AST::NumericLiteral *) override { stop(str: u"NumericLiteral"); }
396
397 bool visit(AST::RegExpLiteral *el) override {
398 start(str: QLatin1String("RegExpLiteral pattern=%1 flags=%2 literalToken=%3")
399 .arg(args: quotedString(s: el->pattern), args: quotedString(s: QString::number(el->flags, base: 16)), args: loc(s: el->literalToken)));
400 return true;
401 }
402 void endVisit(AST::RegExpLiteral *) override { stop(str: u"RegExpLiteral"); }
403
404 bool visit(AST::ArrayPattern *el) override {
405 start(str: QLatin1String("ArrayPattern lbracketToken=%1 commaToken=%2 rbracketToken=%3 parseMode=%4")
406 .arg(args: loc(s: el->lbracketToken),args: loc(s: el->commaToken),args: loc(s: el->rbracketToken), args: quotedString(s: QString::number(el->parseMode, base: 16))));
407 return true;
408 }
409 void endVisit(AST::ArrayPattern *) override { stop(str: u"ArrayPattern"); }
410
411 bool visit(AST::ObjectPattern *el) override {
412 start(str: QLatin1String("ObjectPattern lbraceToken=%1 rbraceToken=%2 parseMode=%3")
413 .arg(args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken), args: quotedString(s: QString::number(el->parseMode, base: 16))));
414 return true;
415 }
416 void endVisit(AST::ObjectPattern *) override { stop(str: u"ObjectPattern"); }
417
418 bool visit(AST::PatternElementList *) override { start(str: u"PatternElementList"); return true; }
419 void endVisit(AST::PatternElementList *) override { stop(str: u"PatternElementList"); }
420
421 bool visit(AST::PatternPropertyList *) override { start(str: u"PatternPropertyList"); return true; }
422 void endVisit(AST::PatternPropertyList *) override { stop(str: u"PatternPropertyList"); }
423
424 bool visit(AST::PatternElement *el) override {
425 start(str: QLatin1String("PatternElement identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5")
426 .arg(args: loc(s: el->identifierToken), args: quotedString(s: el->bindingIdentifier), args: quotedString(s: QString::number(el->type, base: 16)),
427 args: quotedString(s: QString::number(static_cast<int>(el->scope), base: 16)), args: boolStr(v: el->isForDeclaration)));
428 return true;
429 }
430 void endVisit(AST::PatternElement *) override { stop(str: u"PatternElement"); }
431
432 bool visit(AST::PatternProperty *el) override {
433 start(str: QLatin1String("PatternProperty identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5 colonToken=%6")
434 .arg(args: loc(s: el->identifierToken), args: quotedString(s: el->bindingIdentifier), args: quotedString(s: QString::number(el->type, base: 16)),
435 args: quotedString(s: QString::number(static_cast<int>(el->scope), base: 16)), args: boolStr(v: el->isForDeclaration), args: loc(s: el->colonToken)));
436 return true;
437 }
438 void endVisit(AST::PatternProperty *) override { stop(str: u"PatternProperty"); }
439
440 bool visit(AST::Elision *el) override {
441 start(str: QLatin1String("Elision commaToken=%1")
442 .arg(args: loc(s: el->commaToken)));
443 return true;
444 }
445 void endVisit(AST::Elision *el) override {
446 stop(str: u"Elision");
447 Node::accept(node: el->next, visitor: this); // emit other elisions at the same level
448 }
449
450 bool visit(AST::NestedExpression *el) override {
451 start(str: QLatin1String("NestedExpression lparenToken=%1 rparenToken=%2")
452 .arg(args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
453 return true;
454 }
455 void endVisit(AST::NestedExpression *) override { stop(str: u"NestedExpression"); }
456
457 bool visit(AST::IdentifierPropertyName *el) override {
458 if (options & AstDumperOption::SloppyCompare)
459 start(str: QLatin1String("StringLiteralOrIdentifierPropertyName id=%1")
460 .arg(args: quotedString(s: el->id)));
461 else
462 start(str: QLatin1String("IdentifierPropertyName id=%1 propertyNameToken=%2")
463 .arg(args: quotedString(s: el->id), args: loc(s: el->propertyNameToken)));
464 return true;
465 }
466 void endVisit(AST::IdentifierPropertyName *) override {
467 if (options & AstDumperOption::SloppyCompare)
468 stop(str: u"StringLiteralOrIdentifierPropertyName");
469 else
470 stop(str: u"IdentifierPropertyName");
471 }
472
473 bool visit(AST::StringLiteralPropertyName *el) override {
474 if (options & AstDumperOption::SloppyCompare)
475 start(str: QLatin1String("StringLiteralOrIdentifierPropertyName id=%1")
476 .arg(args: quotedString(s: el->id)));
477 else
478 start(str: QLatin1String("StringLiteralPropertyName id=%1 propertyNameToken=%2")
479 .arg(args: quotedString(s: el->id), args: loc(s: el->propertyNameToken)));
480 return true;
481 }
482 void endVisit(AST::StringLiteralPropertyName *) override {
483 if (options & AstDumperOption::SloppyCompare)
484 stop(str: u"StringLiteralOrIdentifierPropertyName");
485 else
486 stop(str: u"StringLiteralPropertyName");
487 }
488
489 bool visit(AST::NumericLiteralPropertyName *el) override {
490 start(str: QLatin1String("NumericLiteralPropertyName id=%1 propertyNameToken=%2")
491 .arg(args: quotedString(s: QString::number(el->id)),args: loc(s: el->propertyNameToken)));
492 return true;
493 }
494 void endVisit(AST::NumericLiteralPropertyName *) override { stop(str: u"NumericLiteralPropertyName"); }
495
496 bool visit(AST::ComputedPropertyName *) override {
497 start(str: u"ComputedPropertyName");
498 return true;
499 }
500 void endVisit(AST::ComputedPropertyName *) override { stop(str: u"ComputedPropertyName"); }
501
502 bool visit(AST::ArrayMemberExpression *el) override {
503 start(str: QLatin1String("ArrayMemberExpression lbraketToken=%1 rbraketToken=%2")
504 .arg(args: loc(s: el->lbracketToken), args: loc(s: el->rbracketToken)));
505 return true;
506 }
507 void endVisit(AST::ArrayMemberExpression *) override { stop(str: u"ArrayMemberExpression"); }
508
509 bool visit(AST::FieldMemberExpression *el) override {
510 start(str: QLatin1String("FieldMemberExpression name=%1 dotToken=%2 identifierToken=%3")
511 .arg(args: quotedString(s: el->name), args: loc(s: el->dotToken), args: loc(s: el->identifierToken)));
512 return true;
513 }
514 void endVisit(AST::FieldMemberExpression *) override { stop(str: u"FieldMemberExpression"); }
515
516 bool visit(AST::TaggedTemplate *) override {
517 start(str: u"TaggedTemplate");
518 return true;
519 }
520 void endVisit(AST::TaggedTemplate *) override { stop(str: u"TaggedTemplate"); }
521
522 bool visit(AST::NewMemberExpression *el) override {
523 start(str: QLatin1String("NewMemberExpression newToken=%1 lparenToken=%2 rparenToken=%3")
524 .arg(args: loc(s: el->newToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
525 return true;
526 }
527 void endVisit(AST::NewMemberExpression *) override { stop(str: u"NewMemberExpression"); }
528
529 bool visit(AST::NewExpression *el) override {
530 start(str: QLatin1String("NewExpression newToken=%1")
531 .arg(args: loc(s: el->newToken)));
532 return true;
533 }
534 void endVisit(AST::NewExpression *) override { stop(str: u"NewExpression"); }
535
536 bool visit(AST::CallExpression *el) override {
537 start(str: QLatin1String("CallExpression lparenToken=%1 rparenToken=%2")
538 .arg(args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
539 return true;
540 }
541 void endVisit(AST::CallExpression *) override { stop(str: u"CallExpression"); }
542
543 bool visit(AST::ArgumentList *el) override {
544 start(str: QLatin1String("ArgumentList commaToken=%1 isSpreadElement=%2")
545 .arg(args: loc(s: el->commaToken), args: boolStr(v: el->isSpreadElement)));
546 return true;
547 }
548 void endVisit(AST::ArgumentList *) override { stop(str: u"ArgumentList"); }
549
550 bool visit(AST::PostIncrementExpression *el) override {
551 start(str: QLatin1String("PostIncrementExpression incrementToken=%1")
552 .arg(args: loc(s: el->incrementToken)));
553 return true;
554 }
555 void endVisit(AST::PostIncrementExpression *) override { stop(str: u"PostIncrementExpression"); }
556
557 bool visit(AST::PostDecrementExpression *el) override {
558 start(str: QLatin1String("PostDecrementExpression decrementToken=%1")
559 .arg(args: loc(s: el->decrementToken)));
560 return true;
561 }
562 void endVisit(AST::PostDecrementExpression *) override { stop(str: u"PostDecrementExpression"); }
563
564 bool visit(AST::DeleteExpression *el) override {
565 start(str: QLatin1String("DeleteExpression deleteToken=%1")
566 .arg(args: loc(s: el->deleteToken)));
567 return true;
568 }
569 void endVisit(AST::DeleteExpression *) override { stop(str: u"DeleteExpression"); }
570
571 bool visit(AST::VoidExpression *el) override {
572 start(str: QLatin1String("VoidExpression voidToken=%1")
573 .arg(args: loc(s: el->voidToken)));
574 return true;
575 }
576 void endVisit(AST::VoidExpression *) override { stop(str: u"VoidExpression"); }
577
578 bool visit(AST::TypeOfExpression *el) override {
579 start(str: QLatin1String("TypeOfExpression typeofToken=%1")
580 .arg(args: loc(s: el->typeofToken)));
581 return true;
582 }
583 void endVisit(AST::TypeOfExpression *) override { stop(str: u"TypeOfExpression"); }
584
585 bool visit(AST::PreIncrementExpression *el) override {
586 start(str: QLatin1String("PreIncrementExpression incrementToken=%1")
587 .arg(args: loc(s: el->incrementToken)));
588 return true;
589 }
590 void endVisit(AST::PreIncrementExpression *) override { stop(str: u"PreIncrementExpression"); }
591
592 bool visit(AST::PreDecrementExpression *el) override {
593 start(str: QLatin1String("PreDecrementExpression decrementToken=%1")
594 .arg(args: loc(s: el->decrementToken)));
595 return true;
596 }
597 void endVisit(AST::PreDecrementExpression *) override { stop(str: u"PreDecrementExpression"); }
598
599 bool visit(AST::UnaryPlusExpression *el) override {
600 start(str: QLatin1String("UnaryPlusExpression plusToken=%1")
601 .arg(args: loc(s: el->plusToken)));
602 return true;
603 }
604 void endVisit(AST::UnaryPlusExpression *) override { stop(str: u"UnaryPlusExpression"); }
605
606 bool visit(AST::UnaryMinusExpression *el) override {
607 start(str: QLatin1String("UnaryMinusExpression minusToken=%1")
608 .arg(args: loc(s: el->minusToken)));
609 return true;
610 }
611 void endVisit(AST::UnaryMinusExpression *) override { stop(str: u"UnaryMinusExpression"); }
612
613 bool visit(AST::TildeExpression *el) override {
614 start(str: QLatin1String("TildeExpression tildeToken=%1")
615 .arg(args: loc(s: el->tildeToken)));
616 return true;
617 }
618 void endVisit(AST::TildeExpression *) override { stop(str: u"TildeExpression"); }
619
620 bool visit(AST::NotExpression *el) override {
621 start(str: QLatin1String("NotExpression notToken=%1")
622 .arg(args: loc(s: el->notToken)));
623 return true;
624 }
625 void endVisit(AST::NotExpression *) override { stop(str: u"NotExpression"); }
626
627 bool visit(AST::BinaryExpression *el) override {
628 start(str: QLatin1String("BinaryExpression op=%1 operatorToken=%2")
629 .arg(args: quotedString(s: QString::number(el->op,base: 16)), args: loc(s: el->operatorToken)));
630 return true;
631 }
632 void endVisit(AST::BinaryExpression *) override { stop(str: u"BinaryExpression"); }
633
634 bool visit(AST::ConditionalExpression *el) override {
635 start(str: QLatin1String("ConditionalExpression questionToken=%1 colonToken=%2")
636 .arg(args: loc(s: el->questionToken), args: loc(s: el->colonToken)));
637 return true;
638 }
639 void endVisit(AST::ConditionalExpression *) override { stop(str: u"ConditionalExpression"); }
640
641 bool visit(AST::CommaExpression *el) override {
642 start(str: QLatin1String("Expression commaToken=%1")
643 .arg(args: loc(s: el->commaToken)));
644 return true;
645 }
646 void endVisit(AST::CommaExpression *) override { stop(str: u"Expression"); }
647
648 bool visit(AST::Block *el) override {
649 start(str: QLatin1String("Block lbraceToken=%1 rbraceToken=%2")
650 .arg(args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken)));
651 return true;
652 }
653 void endVisit(AST::Block *) override { stop(str: u"Block"); }
654
655 bool visit(AST::StatementList *) override {
656 start(str: u"StatementList");
657 return true;
658 }
659 void endVisit(AST::StatementList *) override { stop(str: u"StatementList"); }
660
661 bool visit(AST::VariableStatement *el) override {
662 start(str: QLatin1String("VariableStatement declarationKindToken=%1")
663 .arg(args: loc(s: el->declarationKindToken)));
664 return true;
665 }
666 void endVisit(AST::VariableStatement *) override { stop(str: u"VariableStatement"); }
667
668 bool visit(AST::VariableDeclarationList *el) override {
669 start(str: QLatin1String("VariableDeclarationList commaToken=%1")
670 .arg(args: loc(s: el->commaToken)));
671 return true;
672 }
673 void endVisit(AST::VariableDeclarationList *) override { stop(str: u"VariableDeclarationList"); }
674
675 bool visit(AST::EmptyStatement *el) override {
676 start(str: QLatin1String("EmptyStatement%1").arg(args: semicolonToken(s: el->semicolonToken)));
677 return true;
678 }
679 void endVisit(AST::EmptyStatement *) override { stop(str: u"EmptyStatement"); }
680
681 bool visit(AST::ExpressionStatement *el) override {
682 if (options & AstDumperOption::SloppyCompare)
683 start(str: u"ExpressionStatement");
684 else
685 start(str: QLatin1String("ExpressionStatement%1").arg(args: semicolonToken(s: el->semicolonToken)));
686 return true;
687 }
688 void endVisit(AST::ExpressionStatement *) override { stop(str: u"ExpressionStatement"); }
689
690 bool visit(AST::IfStatement *el) override {
691 start(str: QLatin1String("IfStatement ifToken=%1 lparenToken=%2 rparenToken=%3 elseToken=%4")
692 .arg(args: loc(s: el->ifToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken), args: loc(s: el->elseToken)));
693 return true;
694 }
695 void endVisit(AST::IfStatement *) override { stop(str: u"IfStatement"); }
696
697 bool visit(AST::DoWhileStatement *el) override {
698 start(str: QLatin1String(
699 "DoWhileStatement doToken=%1 whileToken=%2 lparenToken=%3 rparenToken=%4%5")
700 .arg(args: loc(s: el->doToken), args: loc(s: el->whileToken), args: loc(s: el->lparenToken),
701 args: loc(s: el->rparenToken), args: semicolonToken(s: el->semicolonToken)));
702 return true;
703 }
704 void endVisit(AST::DoWhileStatement *) override { stop(str: u"DoWhileStatement"); }
705
706 bool visit(AST::WhileStatement *el) override {
707 start(str: QLatin1String("WhileStatement whileToken=%1 lparenToken=%2 rparenToken=%3")
708 .arg(args: loc(s: el->whileToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
709 return true;
710 }
711 void endVisit(AST::WhileStatement *) override { stop(str: u"WhileStatement"); }
712
713 bool visit(AST::ForStatement *el) override {
714 if (options & AstDumperOption::SloppyCompare)
715 start(str: QLatin1String("ForStatement forToken=%1 lparenToken=%2 rparenToken=%5")
716 .arg(args: loc(s: el->forToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
717 else
718 start(str: QLatin1String("ForStatement forToken=%1 lparenToken=%2 firstSemicolonToken=%3 "
719 "secondSemicolonToken=%4 rparenToken=%5")
720 .arg(args: loc(s: el->forToken), args: loc(s: el->lparenToken),
721 args: loc(s: el->firstSemicolonToken), args: loc(s: el->secondSemicolonToken),
722 args: loc(s: el->rparenToken)));
723 return true;
724 }
725 void endVisit(AST::ForStatement *) override { stop(str: u"ForStatement"); }
726
727 bool visit(AST::ForEachStatement *el) override {
728 start(str: QLatin1String("ForEachStatement forToken=%1 lparenToken=%2 inOfToken=%3 rparenToken=%4 type=%5")
729 .arg(args: loc(s: el->forToken), args: loc(s: el->lparenToken), args: loc(s: el->inOfToken), args: loc(s: el->rparenToken), args: quotedString(s: QString::number(static_cast<int>(el->type), base: 16))));
730 return true;
731 }
732 void endVisit(AST::ForEachStatement *) override { stop(str: u"ForEachStatement"); }
733
734 bool visit(AST::ContinueStatement *el) override {
735 start(str: QLatin1String("ContinueStatement label=%1 continueToken=%2 identifierToken=%3%4")
736 .arg(args: quotedString(s: el->label), args: loc(s: el->continueToken),
737 args: loc(s: el->identifierToken), args: semicolonToken(s: el->semicolonToken)));
738 return true;
739 }
740 void endVisit(AST::ContinueStatement *) override { stop(str: u"ContinueStatement"); }
741
742 bool visit(AST::BreakStatement *el) override {
743 start(str: QLatin1String("BreakStatement label=%1 breakToken=%2 identifierToken=%3%4")
744 .arg(args: quotedString(s: el->label), args: loc(s: el->breakToken), args: loc(s: el->identifierToken),
745 args: semicolonToken(s: el->semicolonToken)));
746 return true;
747 }
748 void endVisit(AST::BreakStatement *) override { stop(str: u"BreakStatement"); }
749
750 bool visit(AST::ReturnStatement *el) override {
751 start(str: QLatin1String("ReturnStatement returnToken=%1%2")
752 .arg(args: loc(s: el->returnToken), args: semicolonToken(s: el->semicolonToken)));
753 return true;
754 }
755 void endVisit(AST::ReturnStatement *) override { stop(str: u"ReturnStatement"); }
756
757 bool visit(AST::YieldExpression *el) override {
758 start(str: QLatin1String("YieldExpression isYieldStar=%1 yieldToken=%2")
759 .arg(args: boolStr(v: el->isYieldStar), args: loc(s: el->yieldToken)));
760 return true;
761 }
762 void endVisit(AST::YieldExpression *) override { stop(str: u"YieldExpression"); }
763
764 bool visit(AST::WithStatement *el) override {
765 start(str: QLatin1String("WithStatement withToken=%1 lparenToken=%2 rparenToken=%3")
766 .arg(args: loc(s: el->withToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
767 return true;
768 }
769 void endVisit(AST::WithStatement *) override { stop(str: u"WithStatement"); }
770
771 bool visit(AST::SwitchStatement *el) override {
772 start(str: QLatin1String("SwitchStatement switchToken=%1 lparenToken=%2 rparenToken=%3")
773 .arg(args: loc(s: el->switchToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken)));
774 return true;
775 }
776 void endVisit(AST::SwitchStatement *) override { stop(str: u"SwitchStatement"); }
777
778 bool visit(AST::CaseBlock *el) override {
779 start(str: QLatin1String("CaseBlock lbraceToken=%1 rbraceToken=%2")
780 .arg(args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken)));
781 return true;
782 }
783 void endVisit(AST::CaseBlock *) override { stop(str: u"CaseBlock"); }
784
785 bool visit(AST::CaseClauses *) override {
786 start(str: u"CaseClauses");
787 return true;
788 }
789 void endVisit(AST::CaseClauses *) override { stop(str: u"CaseClauses"); }
790
791 bool visit(AST::CaseClause *el) override {
792 start(str: QLatin1String("CaseClause caseToken=%1 colonToken=%2")
793 .arg(args: loc(s: el->caseToken), args: loc(s: el->colonToken)));
794 return true;
795 }
796 void endVisit(AST::CaseClause *) override { stop(str: u"CaseClause"); }
797
798 bool visit(AST::DefaultClause *el) override {
799 start(str: QLatin1String("DefaultClause defaultToken=%1 colonToken=%2")
800 .arg(args: loc(s: el->defaultToken), args: loc(s: el->colonToken)));
801 return true;
802 }
803 void endVisit(AST::DefaultClause *) override { stop(str: u"DefaultClause"); }
804
805 bool visit(AST::LabelledStatement *el) override {
806 start(str: QLatin1String("LabelledStatement label=%1 identifierToken=%2 colonToken=%3")
807 .arg(args: quotedString(s: el->label), args: loc(s: el->identifierToken), args: loc(s: el->colonToken)));
808 return true;
809 }
810 void endVisit(AST::LabelledStatement *) override { stop(str: u"LabelledStatement"); }
811
812 bool visit(AST::ThrowStatement *el) override {
813 start(str: QLatin1String("ThrowStatement throwToken=%1%2")
814 .arg(args: loc(s: el->throwToken), args: semicolonToken(s: el->semicolonToken)));
815 return true;
816 }
817 void endVisit(AST::ThrowStatement *) override { stop(str: u"ThrowStatement"); }
818
819 bool visit(AST::TryStatement *el) override {
820 start(str: QLatin1String("TryStatement tryToken=%1")
821 .arg(args: loc(s: el->tryToken)));
822 return true;
823 }
824 void endVisit(AST::TryStatement *) override { stop(str: u"TryStatement"); }
825
826 bool visit(AST::Catch *el) override {
827 start(str: QLatin1String("Catch catchToken=%1 lparenToken=%2 identifierToken=%3 rparenToken=%4")
828 .arg(args: loc(s: el->catchToken), args: loc(s: el->lparenToken), args: loc(s: el->identifierToken), args: loc(s: el->rparenToken)));
829 return true;
830 }
831 void endVisit(AST::Catch *) override { stop(str: u"Catch"); }
832
833 bool visit(AST::Finally *el) override {
834 start(str: QLatin1String("Finally finallyToken=%1")
835 .arg(args: loc(s: el->finallyToken)));
836 return true;
837 }
838 void endVisit(AST::Finally *) override { stop(str: u"Finally"); }
839
840 bool visit(AST::FunctionDeclaration *el) override {
841 start(str: QLatin1String("FunctionDeclaration name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 "
842 "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9")
843 .arg(args: quotedString(s: el->name), args: boolStr(v: el->isArrowFunction), args: boolStr(v: el->isGenerator),
844 args: loc(s: el->functionToken, trim: options & AstDumperOption::SloppyCompare),
845 args: loc(s: el->identifierToken), args: loc(s: el->lparenToken), args: loc(s: el->rparenToken), args: loc(s: el->lbraceToken),
846 args: loc(s: el->rbraceToken)));
847 return true;
848 }
849 void endVisit(AST::FunctionDeclaration *) override { stop(str: u"FunctionDeclaration"); }
850
851 bool visit(AST::FunctionExpression *el) override {
852
853 QString parentheses = options & AstDumperOption::NoLocations
854 ? QLatin1String()
855 : QLatin1String(" lparenToken=%1 rparenToken=%2")
856 .arg(args: loc(s: el->lparenToken), args: loc(s: el->rparenToken));
857
858 start(str: QLatin1String("FunctionExpression name=%1 isArrowFunction=%2 isGenerator=%3 "
859 "functionToken=%4 "
860 "identifierToken=%5%6 lbraceToken=%7 "
861 "rbraceToken=%8")
862 .arg(args: quotedString(s: el->name), args: boolStr(v: el->isArrowFunction),
863 args: boolStr(v: el->isGenerator),
864 args: loc(s: el->functionToken, trim: options & AstDumperOption::SloppyCompare),
865 args: loc(s: el->identifierToken), args&: parentheses, args: loc(s: el->lbraceToken),
866 args: loc(s: el->rbraceToken)));
867 return true;
868 }
869 void endVisit(AST::FunctionExpression *) override { stop(str: u"FunctionExpression"); }
870
871 bool visit(AST::FormalParameterList *) override {
872 start(str: u"FormalParameterList");
873 return true;
874 }
875 void endVisit(AST::FormalParameterList *) override { stop(str: u"FormalParameterList"); }
876
877 bool visit(AST::ClassExpression *el) override {
878 start(str: QLatin1String("ClassExpression name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5")
879 .arg(args: quotedString(s: el->name), args: loc(s: el->classToken), args: loc(s: el->identifierToken), args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken)));
880 return true;
881 }
882 void endVisit(AST::ClassExpression *) override { stop(str: u"ClassExpression"); }
883
884 bool visit(AST::ClassDeclaration *el) override {
885 start(str: QLatin1String("ClassDeclaration name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5")
886 .arg(args: quotedString(s: el->name), args: loc(s: el->classToken), args: loc(s: el->identifierToken), args: loc(s: el->lbraceToken), args: loc(s: el->rbraceToken)));
887 return true;
888 }
889 void endVisit(AST::ClassDeclaration *) override { stop(str: u"ClassDeclaration"); }
890
891 bool visit(AST::ClassElementList *el) override {
892 start(str: QLatin1String("ClassElementList isStatic=%1")
893 .arg(args: boolStr(v: el->isStatic)));
894 return true;
895 }
896 void endVisit(AST::ClassElementList *) override { stop(str: u"ClassElementList"); }
897
898 bool visit(AST::Program *) override {
899 start(str: u"Program");
900 return true;
901 }
902 void endVisit(AST::Program *) override { stop(str: u"Program"); }
903
904 bool visit(AST::NameSpaceImport *el) override {
905 start(str: QLatin1String("NameSpaceImport starToken=%1 importedBindingToken=%2 importedBinding=%3")
906 .arg(args: loc(s: el->starToken), args: loc(s: el->importedBindingToken), args: quotedString(s: el->importedBinding)));
907 return true;
908 }
909 void endVisit(AST::NameSpaceImport *) override { stop(str: u"NameSpaceImport"); }
910
911 bool visit(AST::ImportSpecifier *el) override {
912 start(str: QLatin1String("ImportSpecifier identifierToken=%1 importedBindingToken=%2 identifier=%3 importedBinding=%4")
913 .arg(args: loc(s: el->identifierToken), args: loc(s: el->importedBindingToken), args: quotedString(s: el->identifier), args: quotedString(s: el->importedBinding)));
914 return true;
915 }
916 void endVisit(AST::ImportSpecifier *) override { stop(str: u"ImportSpecifier"); }
917
918 bool visit(AST::ImportsList *el) override {
919 start(str: QLatin1String("ImportsList importSpecifierToken=%1")
920 .arg(args: loc(s: el->importSpecifierToken)));
921 return true;
922 }
923 void endVisit(AST::ImportsList *) override { stop(str: u"ImportsList"); }
924
925 bool visit(AST::NamedImports *el) override {
926 start(str: QLatin1String("NamedImports leftBraceToken=%1 rightBraceToken=%2")
927 .arg(args: loc(s: el->leftBraceToken), args: loc(s: el->rightBraceToken)));
928 return true;
929 }
930 void endVisit(AST::NamedImports *) override { stop(str: u"NamedImports"); }
931
932 bool visit(AST::FromClause *el) override {
933 start(str: QLatin1String("FromClause fromToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3")
934 .arg(args: loc(s: el->fromToken), args: loc(s: el->moduleSpecifierToken), args: quotedString(s: el->moduleSpecifier)));
935 return true;
936 }
937 void endVisit(AST::FromClause *) override { stop(str: u"FromClause"); }
938
939 bool visit(AST::ImportClause *el) override {
940 start(str: QLatin1String("ImportClause importedDefaultBindingToken=%1 importedDefaultBinding=%2")
941 .arg(args: loc(s: el->importedDefaultBindingToken), args: quotedString(s: el->importedDefaultBinding)));
942 return true;
943 }
944 void endVisit(AST::ImportClause *) override { stop(str: u"ImportClause"); }
945
946 bool visit(AST::ImportDeclaration *el) override {
947 start(str: QLatin1String("ImportDeclaration importToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3")
948 .arg(args: loc(s: el->importToken), args: loc(s: el->moduleSpecifierToken), args: quotedString(s: el->moduleSpecifier)));
949 return true;
950 }
951 void endVisit(AST::ImportDeclaration *) override { stop(str: u"ImportDeclaration"); }
952
953 bool visit(AST::ExportSpecifier *el) override {
954 start(str: QLatin1String("ExportSpecifier identifierToken=%1 exportedIdentifierToken=%2 identifier=%3 exportedIdentifier=%4")
955 .arg(args: loc(s: el->identifierToken), args: loc(s: el->exportedIdentifierToken), args: quotedString(s: el->identifier), args: quotedString(s: el->exportedIdentifier)));
956 return true;
957 }
958 void endVisit(AST::ExportSpecifier *) override { stop(str: u"ExportSpecifier"); }
959
960 bool visit(AST::ExportsList *) override {
961 start(str: u"ExportsList");
962 return true;
963 }
964 void endVisit(AST::ExportsList *) override { stop(str: u"ExportsList"); }
965
966 bool visit(AST::ExportClause *el) override {
967 start(str: QLatin1String("ExportClause leftBraceToken=%1 rightBraceToken=%2")
968 .arg(args: loc(s: el->leftBraceToken), args: loc(s: el->rightBraceToken)));
969 return true;
970 }
971 void endVisit(AST::ExportClause *) override { stop(str: u"ExportClause"); }
972
973 bool visit(AST::ExportDeclaration *el) override {
974 start(str: QLatin1String("ExportDeclaration exportToken=%1 exportDefault=%3")
975 .arg(args: loc(s: el->exportToken), args: boolStr(v: el->exportDefault)));
976 return true;
977 }
978 void endVisit(AST::ExportDeclaration *) override { stop(str: u"ExportDeclaration"); }
979
980 bool visit(AST::ESModule *) override {
981 start(str: u"ESModule");
982 return true;
983 }
984 void endVisit(AST::ESModule *) override { stop(str: u"ESModule"); }
985
986 bool visit(AST::DebuggerStatement *el) override {
987 start(str: QLatin1String("DebuggerStatement debuggerToken=%1%2")
988 .arg(args: loc(s: el->debuggerToken), args: semicolonToken(s: el->semicolonToken)));
989 return true;
990 }
991 void endVisit(AST::DebuggerStatement *) override { stop(str: u"DebuggerStatement"); }
992
993 bool visit(AST::Type *) override {
994 start(str: u"Type");
995 return true;
996 }
997 void endVisit(AST::Type *) override { stop(str: u"Type"); }
998
999 bool visit(AST::TypeAnnotation *el) override {
1000 start(str: QLatin1String("TypeAnnotation colonToken=%1")
1001 .arg(args: loc(s: el->colonToken)));
1002 return true;
1003 }
1004 void endVisit(AST::TypeAnnotation *) override { stop(str: u"TypeAnnotation"); }
1005
1006 void throwRecursionDepthError() override {
1007 qCWarning(domLog) << "Maximum statement or expression depth exceeded in AstDumper";
1008 }
1009
1010private:
1011 // attributes
1012 std::function <void (QStringView)> dumper;
1013 AstDumperOptions options = AstDumperOption::None;
1014 int indent = 0;
1015 int baseIndent = 0;
1016 function_ref<QStringView(SourceLocation)> loc2str;
1017 bool dumpNode(){
1018 return options & AstDumperOption::DumpNode;
1019 }
1020 bool noLocations() {
1021 return options & AstDumperOption::NoLocations;
1022 }
1023 bool noAnnotations() {
1024 return options & AstDumperOption::NoAnnotations;
1025 }
1026};
1027
1028QDebug operator<<(QDebug d, AST::Node *n) {
1029 QDebug noQuote = d.noquote().nospace();
1030 AstDumper visitor([&noQuote](QStringView s){ noQuote << s; });
1031 Node::accept(node: n, visitor: &visitor);
1032 return d;
1033}
1034
1035QString lineDiff(QString s1, QString s2, int nContext) {
1036 QTextStream d1(&s1), d2(&s2);
1037 QList<QString> preLines(nContext);
1038 int nLine = 0;
1039 bool same = true;
1040 QString l1, l2;
1041 while (same && !d1.atEnd() && !d2.atEnd()) {
1042 l1=d1.readLine();
1043 l2=d2.readLine();
1044 if (l1 == l2)
1045 preLines[nLine++ % nContext] = l1;
1046 else
1047 same = false;
1048 }
1049 QString res;
1050 QTextStream ss(&res);
1051 if (!same || !d1.atEnd() || !d2.atEnd()) {
1052 for (int iline = qMin(a: nLine, b: nContext); iline > 0; --iline) {
1053 ss << QLatin1String(" ") << preLines[(nLine - iline) % nContext] << QLatin1String("\n");
1054 }
1055 int iline = 0;
1056 if (!same) {
1057 ss << QLatin1String("-") << l1 << QLatin1String("\n");
1058 ++iline;
1059 }
1060 if (same && nContext == 0)
1061 nContext = 1;
1062 for (;iline < nContext && !d1.atEnd(); iline ++) {
1063 l1 = d1.readLine();
1064 ss << QLatin1String("-") << l1 << QLatin1String("\n");
1065 }
1066 iline = 0;
1067 if (!same) {
1068 ss << QLatin1String("+") << l2 << QLatin1String("\n");
1069 ++iline;
1070 }
1071 for (;iline < nContext && !d2.atEnd(); iline ++) {
1072 l2 = d2.readLine();
1073 ss << QLatin1String("+") << l2 << QLatin1String("\n");
1074 }
1075 }
1076 return res;
1077}
1078
1079QString astNodeDiff(AST::Node *n1, AST::Node *n2, int nContext, AstDumperOptions opt, int indent,
1080 function_ref<QStringView(SourceLocation)>loc2str1,
1081 function_ref<QStringView(SourceLocation)>loc2str2) {
1082 QString s1, s2;
1083 QTextStream d1(&s1), d2(&s2);
1084 AstDumper visitor1=AstDumper([&d1](QStringView s){ d1 << s; }, opt, indent, 0, loc2str1);
1085 AstDumper visitor2=AstDumper([&d2](QStringView s){ d2 << s; }, opt, indent, 0, loc2str2);
1086 Node::accept(node: n1, visitor: &visitor1);
1087 Node::accept(node: n2, visitor: &visitor2);
1088 d1.flush();
1089 d2.flush();
1090 return lineDiff(s1, s2, nContext);
1091}
1092
1093void astNodeDumper(const Sink &s, Node *n, AstDumperOptions opt, int indent, int baseIndent,
1094 function_ref<QStringView(SourceLocation)>loc2str)
1095{
1096 AstDumper visitor=AstDumper(s, opt, indent, baseIndent, loc2str);
1097 Node::accept(node: n, visitor: &visitor);
1098}
1099
1100QString astNodeDump(Node *n, AstDumperOptions opt, int indent, int baseIndent,
1101 function_ref<QStringView(SourceLocation)>loc2str)
1102{
1103 return dumperToString(
1104 writer: [n, opt, indent, baseIndent, loc2str = std::move(loc2str)](const Sink &s) {
1105 astNodeDumper(s, n, opt, indent, baseIndent, loc2str: std::move(loc2str));
1106 });
1107}
1108
1109} // end namespace Dom
1110} // end namespace QQmlJS
1111
1112QT_END_NAMESPACE
1113

source code of qtdeclarative/src/qmldom/qqmldomastdumper.cpp