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