1// Copyright (C) 2021 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 "qqmldomreformatter_p.h"
5#include "qqmldomcomments_p.h"
6
7#include <QtQml/private/qqmljsast_p.h>
8#include <QtQml/private/qqmljsastvisitor_p.h>
9#include <QtQml/private/qqmljsengine_p.h>
10#include <QtQml/private/qqmljslexer_p.h>
11
12#include <QString>
13
14#include <limits>
15
16QT_BEGIN_NAMESPACE
17namespace QQmlJS {
18namespace Dom {
19
20using namespace AST;
21
22class Rewriter : protected BaseVisitor
23{
24 OutWriter &lw;
25 std::shared_ptr<AstComments> comments;
26 std::function<QStringView(SourceLocation)> loc2Str;
27 QHash<Node *, QList<std::function<void()>>> postOps;
28 int expressionDepth = 0;
29
30 bool addSemicolons() const { return expressionDepth > 0; }
31
32public:
33 Rewriter(OutWriter &lw, std::shared_ptr<AstComments> comments,
34 std::function<QStringView(SourceLocation)> loc2Str, Node *node)
35 : lw(lw), comments(comments), loc2Str(loc2Str)
36 {
37 accept(node);
38 }
39
40protected:
41 bool preVisit(Node *n) override
42 {
43 if (CommentedElement *c = comments->commentForNode(n)) {
44 c->writePre(lw);
45 postOps[n].append(t: [c, this]() { c->writePost(lw); });
46 }
47 return true;
48 }
49 void postVisit(Node *n) override
50 {
51 for (auto &op : postOps[n]) {
52 op();
53 }
54 postOps.remove(key: n);
55 }
56
57 void accept(Node *node) { Node::accept(node, visitor: this); }
58
59 void lnAcceptIndented(Node *node)
60 {
61 int indent = lw.increaseIndent(level: 1);
62 lw.ensureNewline();
63 accept(node);
64 lw.decreaseIndent(level: 1, expectedIndent: indent);
65 }
66
67 void out(const char *str) { lw.write(v: QString::fromLatin1(ba: str)); }
68
69 void out(QStringView str) { lw.write(v: str); }
70
71 void out(const SourceLocation &loc)
72 {
73 if (loc.length != 0)
74 out(str: loc2Str(loc));
75 }
76
77 void newLine() { lw.ensureNewline(); }
78
79 bool acceptBlockOrIndented(Node *ast, bool finishWithSpaceOrNewline = false)
80 {
81 if (cast<Block *>(ast)) {
82 out(str: " ");
83 accept(node: ast);
84 if (finishWithSpaceOrNewline)
85 out(str: " ");
86 return true;
87 } else {
88 if (finishWithSpaceOrNewline)
89 postOps[ast].append(t: [this]() { this->newLine(); });
90 lnAcceptIndented(node: ast);
91 return false;
92 }
93 }
94
95#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
96 // we are not supposed to handle the ui
97 bool visit(UiPragmaValueList *) override
98 {
99 Q_ASSERT(false);
100 return false;
101 }
102#endif
103 bool visit(UiPragma *) override
104 {
105 Q_ASSERT(false);
106 return false;
107 }
108 bool visit(UiEnumDeclaration *) override
109 {
110 Q_ASSERT(false);
111 return false;
112 }
113 bool visit(UiEnumMemberList *) override
114 {
115 Q_ASSERT(false);
116 return false;
117 }
118 bool visit(UiImport *) override
119 {
120 Q_ASSERT(false);
121 return false;
122 }
123 bool visit(UiObjectDefinition *) override
124 {
125 Q_ASSERT(false);
126 return false;
127 }
128 bool visit(UiObjectInitializer *) override
129 {
130 Q_ASSERT(false);
131 return false;
132 }
133 bool visit(UiParameterList *) override
134 {
135 Q_ASSERT(false);
136 return false;
137 }
138 bool visit(UiPublicMember *) override
139 {
140 Q_ASSERT(false);
141 return false;
142 }
143 bool visit(UiObjectBinding *) override
144 {
145 Q_ASSERT(false);
146 return false;
147 }
148 bool visit(UiScriptBinding *) override
149 {
150 Q_ASSERT(false);
151 return false;
152 }
153 bool visit(UiArrayBinding *) override
154 {
155 Q_ASSERT(false);
156 return false;
157 }
158 bool visit(UiHeaderItemList *) override
159 {
160 Q_ASSERT(false);
161 return false;
162 }
163 bool visit(UiObjectMemberList *) override
164 {
165 Q_ASSERT(false);
166 return false;
167 }
168 bool visit(UiArrayMemberList *) override
169 {
170 Q_ASSERT(false);
171 return false;
172 }
173 bool visit(UiQualifiedId *) override
174 {
175 Q_ASSERT(false);
176 return false;
177 }
178 bool visit(UiProgram *) override
179 {
180 Q_ASSERT(false);
181 return false;
182 }
183 bool visit(UiSourceElement *) override
184 {
185 Q_ASSERT(false);
186 return false;
187 }
188 bool visit(UiVersionSpecifier *) override
189 {
190 Q_ASSERT(false);
191 return false;
192 }
193 bool visit(UiInlineComponent *) override
194 {
195 Q_ASSERT(false);
196 return false;
197 }
198 bool visit(UiAnnotation *) override
199 {
200 Q_ASSERT(false);
201 return false;
202 }
203 bool visit(UiAnnotationList *) override
204 {
205 Q_ASSERT(false);
206 return false;
207 }
208 bool visit(UiRequired *) override
209 {
210 Q_ASSERT(false);
211 return false;
212 }
213
214 bool visit(ThisExpression *ast) override
215 {
216 out(loc: ast->thisToken);
217 return true;
218 }
219 bool visit(NullExpression *ast) override
220 {
221 out(loc: ast->nullToken);
222 return true;
223 }
224 bool visit(TrueLiteral *ast) override
225 {
226 out(loc: ast->trueToken);
227 return true;
228 }
229 bool visit(FalseLiteral *ast) override
230 {
231 out(loc: ast->falseToken);
232 return true;
233 }
234 bool visit(IdentifierExpression *ast) override
235 {
236 out(loc: ast->identifierToken);
237 return true;
238 }
239 bool visit(StringLiteral *ast) override
240 {
241 // correctly handle multiline literals
242 if (ast->literalToken.length == 0)
243 return true;
244 QStringView str = loc2Str(ast->literalToken);
245 if (lw.indentNextlines && str.contains(c: QLatin1Char('\n'))) {
246 out(str: str.mid(pos: 0, n: 1));
247 lw.indentNextlines = false;
248 out(str: str.mid(pos: 1));
249 lw.indentNextlines = true;
250 } else {
251 out(str);
252 }
253 return true;
254 }
255 bool visit(NumericLiteral *ast) override
256 {
257 out(loc: ast->literalToken);
258 return true;
259 }
260 bool visit(RegExpLiteral *ast) override
261 {
262 out(loc: ast->literalToken);
263 return true;
264 }
265
266 bool visit(ArrayPattern *ast) override
267 {
268 out(loc: ast->lbracketToken);
269 int baseIndent = lw.increaseIndent(level: 1);
270 if (ast->elements)
271 accept(node: ast->elements);
272 out(loc: ast->commaToken);
273 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
274 out(loc: ast->rbracketToken);
275 return false;
276 }
277
278 bool visit(ObjectPattern *ast) override
279 {
280 out(loc: ast->lbraceToken);
281 ++expressionDepth;
282 if (ast->properties) {
283 lnAcceptIndented(node: ast->properties);
284 newLine();
285 }
286 --expressionDepth;
287 out(loc: ast->rbraceToken);
288 return false;
289 }
290
291 bool visit(PatternElementList *ast) override
292 {
293 for (PatternElementList *it = ast; it; it = it->next) {
294 if (it->elision)
295 accept(node: it->elision);
296 if (it->elision && it->element)
297 out(str: ", ");
298 if (it->element)
299 accept(node: it->element);
300 if (it->next)
301 out(str: ", ");
302 }
303 return false;
304 }
305
306 bool visit(PatternPropertyList *ast) override
307 {
308 for (PatternPropertyList *it = ast; it; it = it->next) {
309 PatternProperty *assignment = AST::cast<PatternProperty *>(ast: it->property);
310 if (assignment) {
311 preVisit(n: assignment);
312 const bool isStringLike = [this](const SourceLocation &loc) {
313 const auto name = loc2Str(loc);
314 if (name.first() == name.last()) {
315 if (name.first() == QStringLiteral("\'")
316 || name.first() == QStringLiteral("\""))
317 return true;
318 }
319 return false;
320 }(assignment->name->propertyNameToken);
321
322 if (isStringLike)
323 out(str: "\"");
324
325 accept(node: assignment->name);
326 if (isStringLike)
327 out(str: "\"");
328
329 bool useInitializer = false;
330 const bool bindingIdentifierExist = !assignment->bindingIdentifier.isEmpty();
331 if (assignment->colonToken.length > 0) {
332 out(str: ": ");
333 useInitializer = true;
334 if (bindingIdentifierExist)
335 out(str: assignment->bindingIdentifier);
336 }
337
338 if (assignment->initializer) {
339 if (bindingIdentifierExist) {
340 out(str: " = ");
341 useInitializer = true;
342 }
343 if (useInitializer)
344 accept(node: assignment->initializer);
345 }
346
347 if (it->next) {
348 out(str: ",");
349 newLine();
350 }
351 postVisit(n: assignment);
352 continue;
353 }
354
355 PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(ast: it->next);
356 if (getterSetter && getterSetter->property) {
357 switch (getterSetter->property->type) {
358 case PatternElement::Getter:
359 out(str: "get");
360 break;
361 case PatternElement::Setter:
362 out(str: "set");
363 break;
364 default:
365 break;
366 }
367
368 accept(node: getterSetter->property->name);
369 out(str: "(");
370 // accept(getterSetter->formals); // TODO
371 out(str: ")");
372 out(str: " {");
373 // accept(getterSetter->functionBody); // TODO
374 out(str: " }");
375 }
376 }
377 return false;
378 }
379
380 bool visit(NestedExpression *ast) override
381 {
382 out(loc: ast->lparenToken);
383 int baseIndent = lw.increaseIndent(level: 1);
384 accept(node: ast->expression);
385 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
386 out(loc: ast->rparenToken);
387 return false;
388 }
389
390 bool visit(IdentifierPropertyName *ast) override
391 {
392 out(str: ast->id.toString());
393 return true;
394 }
395 bool visit(StringLiteralPropertyName *ast) override
396 {
397 out(str: ast->id.toString());
398 return true;
399 }
400 bool visit(NumericLiteralPropertyName *ast) override
401 {
402 out(str: QString::number(ast->id));
403 return true;
404 }
405
406 bool visit(TemplateLiteral *ast) override
407 {
408 // correctly handle multiline literals
409 if (ast->literalToken.length != 0) {
410 QStringView str = loc2Str(ast->literalToken);
411 if (lw.indentNextlines && str.contains(c: QLatin1Char('\n'))) {
412 out(str: str.mid(pos: 0, n: 1));
413 lw.indentNextlines = false;
414 out(str: str.mid(pos: 1));
415 lw.indentNextlines = true;
416 } else {
417 out(str);
418 }
419 }
420 accept(node: ast->expression);
421 return true;
422 }
423
424 bool visit(ArrayMemberExpression *ast) override
425 {
426 accept(node: ast->base);
427 out(loc: ast->lbracketToken);
428 int indent = lw.increaseIndent(level: 1);
429 accept(node: ast->expression);
430 lw.decreaseIndent(level: 1, expectedIndent: indent);
431 out(loc: ast->rbracketToken);
432 return false;
433 }
434
435 bool visit(FieldMemberExpression *ast) override
436 {
437 accept(node: ast->base);
438 out(loc: ast->dotToken);
439 out(loc: ast->identifierToken);
440 return false;
441 }
442
443 bool visit(NewMemberExpression *ast) override
444 {
445 out(str: "new "); // ast->newToken
446 accept(node: ast->base);
447 out(loc: ast->lparenToken);
448 accept(node: ast->arguments);
449 out(loc: ast->rparenToken);
450 return false;
451 }
452
453 bool visit(NewExpression *ast) override
454 {
455 out(str: "new "); // ast->newToken
456 accept(node: ast->expression);
457 return false;
458 }
459
460 bool visit(CallExpression *ast) override
461 {
462 accept(node: ast->base);
463 out(loc: ast->lparenToken);
464 int baseIndent = lw.increaseIndent(level: 1);
465 accept(node: ast->arguments);
466 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
467 out(loc: ast->rparenToken);
468 return false;
469 }
470
471 bool visit(PostIncrementExpression *ast) override
472 {
473 accept(node: ast->base);
474 out(loc: ast->incrementToken);
475 return false;
476 }
477
478 bool visit(PostDecrementExpression *ast) override
479 {
480 accept(node: ast->base);
481 out(loc: ast->decrementToken);
482 return false;
483 }
484
485 bool visit(PreIncrementExpression *ast) override
486 {
487 out(loc: ast->incrementToken);
488 accept(node: ast->expression);
489 return false;
490 }
491
492 bool visit(PreDecrementExpression *ast) override
493 {
494 out(loc: ast->decrementToken);
495 accept(node: ast->expression);
496 return false;
497 }
498
499 bool visit(DeleteExpression *ast) override
500 {
501 out(str: "delete "); // ast->deleteToken
502 accept(node: ast->expression);
503 return false;
504 }
505
506 bool visit(VoidExpression *ast) override
507 {
508 out(str: "void "); // ast->voidToken
509 accept(node: ast->expression);
510 return false;
511 }
512
513 bool visit(TypeOfExpression *ast) override
514 {
515 out(str: "typeof "); // ast->typeofToken
516 accept(node: ast->expression);
517 return false;
518 }
519
520 bool visit(UnaryPlusExpression *ast) override
521 {
522 out(loc: ast->plusToken);
523 accept(node: ast->expression);
524 return false;
525 }
526
527 bool visit(UnaryMinusExpression *ast) override
528 {
529 out(loc: ast->minusToken);
530 accept(node: ast->expression);
531 return false;
532 }
533
534 bool visit(TildeExpression *ast) override
535 {
536 out(loc: ast->tildeToken);
537 accept(node: ast->expression);
538 return false;
539 }
540
541 bool visit(NotExpression *ast) override
542 {
543 out(loc: ast->notToken);
544 accept(node: ast->expression);
545 return false;
546 }
547
548 bool visit(BinaryExpression *ast) override
549 {
550 accept(node: ast->left);
551 out(str: " ");
552 out(loc: ast->operatorToken);
553 out(str: " ");
554 accept(node: ast->right);
555 return false;
556 }
557
558 bool visit(ConditionalExpression *ast) override
559 {
560 accept(node: ast->expression);
561 out(str: " ? "); // ast->questionToken
562 accept(node: ast->ok);
563 out(str: " : "); // ast->colonToken
564 accept(node: ast->ko);
565 return false;
566 }
567
568 bool visit(Block *ast) override
569 {
570 out(loc: ast->lbraceToken);
571 ++expressionDepth;
572 lnAcceptIndented(node: ast->statements);
573 newLine();
574 --expressionDepth;
575 out(loc: ast->rbraceToken);
576 return false;
577 }
578
579 bool visit(VariableStatement *ast) override
580 {
581 out(loc: ast->declarationKindToken);
582 out(str: " ");
583 accept(node: ast->declarations);
584 if (addSemicolons())
585 out(str: ";");
586 return false;
587 }
588
589
590 void outputScope(VariableScope scope) {
591 switch (scope) {
592 case VariableScope::Const:
593 out(str: "const ");
594 break;
595 case VariableScope::Let:
596 out(str: "let ");
597 break;
598 case VariableScope::Var:
599 out(str: "var ");
600 break;
601 default:
602 break;
603 }
604 }
605
606 bool visit(PatternElement *ast) override
607 {
608 if (ast->isForDeclaration) {
609 outputScope(scope: ast->scope);
610 }
611 switch (ast->type) {
612 case PatternElement::Literal:
613 case PatternElement::Method:
614 case PatternElement::Binding:
615 break;
616 case PatternElement::Getter:
617 out(str: "get ");
618 break;
619 case PatternElement::Setter:
620 out(str: "set ");
621 break;
622 case PatternElement::SpreadElement:
623 out(str: "...");
624 break;
625 }
626
627 accept(node: ast->bindingTarget);
628 if (!ast->destructuringPattern())
629 out(loc: ast->identifierToken);
630 if (ast->initializer) {
631 if (ast->isVariableDeclaration() || ast->type == AST::PatternElement::Binding)
632 out(str: " = ");
633 accept(node: ast->initializer);
634 }
635 return false;
636 }
637
638 bool visit(EmptyStatement *ast) override
639 {
640 out(loc: ast->semicolonToken);
641 return false;
642 }
643
644 bool visit(IfStatement *ast) override
645 {
646 out(loc: ast->ifToken);
647 out(str: " ");
648 out(loc: ast->lparenToken);
649 preVisit(n: ast->expression);
650 ast->expression->accept0(visitor: this);
651 out(loc: ast->rparenToken);
652 postVisit(n: ast->expression);
653 acceptBlockOrIndented(ast: ast->ok, finishWithSpaceOrNewline: ast->ko);
654 if (ast->ko) {
655 out(loc: ast->elseToken);
656 if (cast<Block *>(ast: ast->ko) || cast<IfStatement *>(ast: ast->ko)) {
657 out(str: " ");
658 accept(node: ast->ko);
659 } else {
660 lnAcceptIndented(node: ast->ko);
661 }
662 }
663 return false;
664 }
665
666 bool visit(DoWhileStatement *ast) override
667 {
668 out(loc: ast->doToken);
669 acceptBlockOrIndented(ast: ast->statement, finishWithSpaceOrNewline: true);
670 out(loc: ast->whileToken);
671 out(str: " ");
672 out(loc: ast->lparenToken);
673 accept(node: ast->expression);
674 out(loc: ast->rparenToken);
675 return false;
676 }
677
678 bool visit(WhileStatement *ast) override
679 {
680 out(loc: ast->whileToken);
681 out(str: " ");
682 out(loc: ast->lparenToken);
683 accept(node: ast->expression);
684 out(loc: ast->rparenToken);
685 acceptBlockOrIndented(ast: ast->statement);
686 return false;
687 }
688
689 bool visit(ForStatement *ast) override
690 {
691 out(loc: ast->forToken);
692 out(str: " ");
693 out(loc: ast->lparenToken);
694 if (ast->initialiser) {
695 accept(node: ast->initialiser);
696 } else if (ast->declarations) {
697 outputScope(scope: ast->declarations->declaration->scope);
698 accept(node: ast->declarations);
699 }
700 out(str: "; "); // ast->firstSemicolonToken
701 accept(node: ast->condition);
702 out(str: "; "); // ast->secondSemicolonToken
703 accept(node: ast->expression);
704 out(loc: ast->rparenToken);
705 acceptBlockOrIndented(ast: ast->statement);
706 return false;
707 }
708
709 bool visit(ForEachStatement *ast) override
710 {
711 out(loc: ast->forToken);
712 out(str: " ");
713 out(loc: ast->lparenToken);
714 accept(node: ast->lhs);
715 out(str: " ");
716 out(loc: ast->inOfToken);
717 out(str: " ");
718 accept(node: ast->expression);
719 out(loc: ast->rparenToken);
720 acceptBlockOrIndented(ast: ast->statement);
721 return false;
722 }
723
724 bool visit(ContinueStatement *ast) override
725 {
726 out(loc: ast->continueToken);
727 if (!ast->label.isNull()) {
728 out(str: " ");
729 out(loc: ast->identifierToken);
730 }
731 if (addSemicolons())
732 out(str: ";");
733 return false;
734 }
735
736 bool visit(BreakStatement *ast) override
737 {
738 out(loc: ast->breakToken);
739 if (!ast->label.isNull()) {
740 out(str: " ");
741 out(loc: ast->identifierToken);
742 }
743 if (addSemicolons())
744 out(str: ";");
745 return false;
746 }
747
748 bool visit(ReturnStatement *ast) override
749 {
750 out(loc: ast->returnToken);
751 if (ast->expression) {
752 if (ast->returnToken.length != 0)
753 out(str: " ");
754 accept(node: ast->expression);
755 }
756 if (ast->returnToken.length > 0 && addSemicolons())
757 out(str: ";");
758 return false;
759 }
760
761 bool visit(ThrowStatement *ast) override
762 {
763 out(loc: ast->throwToken);
764 if (ast->expression) {
765 out(str: " ");
766 accept(node: ast->expression);
767 }
768 if (addSemicolons())
769 out(str: ";");
770 return false;
771 }
772
773 bool visit(WithStatement *ast) override
774 {
775 out(loc: ast->withToken);
776 out(str: " ");
777 out(loc: ast->lparenToken);
778 accept(node: ast->expression);
779 out(loc: ast->rparenToken);
780 acceptBlockOrIndented(ast: ast->statement);
781 return false;
782 }
783
784 bool visit(SwitchStatement *ast) override
785 {
786 out(loc: ast->switchToken);
787 out(str: " ");
788 out(loc: ast->lparenToken);
789 accept(node: ast->expression);
790 out(loc: ast->rparenToken);
791 out(str: " ");
792 accept(node: ast->block);
793 return false;
794 }
795
796 bool visit(CaseBlock *ast) override
797 {
798 out(loc: ast->lbraceToken);
799 ++expressionDepth;
800 newLine();
801 accept(node: ast->clauses);
802 if (ast->clauses && ast->defaultClause)
803 newLine();
804 accept(node: ast->defaultClause);
805 if (ast->moreClauses)
806 newLine();
807 accept(node: ast->moreClauses);
808 newLine();
809 --expressionDepth;
810 out(loc: ast->rbraceToken);
811 return false;
812 }
813
814 bool visit(CaseClause *ast) override
815 {
816 out(str: "case "); // ast->caseToken
817 accept(node: ast->expression);
818 out(loc: ast->colonToken);
819 if (ast->statements)
820 lnAcceptIndented(node: ast->statements);
821 return false;
822 }
823
824 bool visit(DefaultClause *ast) override
825 {
826 out(loc: ast->defaultToken);
827 out(loc: ast->colonToken);
828 lnAcceptIndented(node: ast->statements);
829 return false;
830 }
831
832 bool visit(LabelledStatement *ast) override
833 {
834 out(loc: ast->identifierToken);
835 out(str: ": "); // ast->colonToken
836 accept(node: ast->statement);
837 return false;
838 }
839
840 bool visit(TryStatement *ast) override
841 {
842 out(str: "try "); // ast->tryToken
843 accept(node: ast->statement);
844 if (ast->catchExpression) {
845 out(str: " ");
846 accept(node: ast->catchExpression);
847 }
848 if (ast->finallyExpression) {
849 out(str: " ");
850 accept(node: ast->finallyExpression);
851 }
852 return false;
853 }
854
855 bool visit(Catch *ast) override
856 {
857 out(loc: ast->catchToken);
858 out(str: " ");
859 out(loc: ast->lparenToken);
860 out(loc: ast->identifierToken);
861 out(str: ") "); // ast->rparenToken
862 accept(node: ast->statement);
863 return false;
864 }
865
866 bool visit(Finally *ast) override
867 {
868 out(str: "finally "); // ast->finallyToken
869 accept(node: ast->statement);
870 return false;
871 }
872
873 bool visit(FunctionDeclaration *ast) override
874 {
875 return visit(ast: static_cast<FunctionExpression *>(ast));
876 }
877
878 bool visit(FunctionExpression *ast) override
879 {
880 if (!ast->isArrowFunction) {
881 out(str: "function "); // ast->functionToken
882 if (!ast->name.isNull())
883 out(loc: ast->identifierToken);
884 }
885 out(loc: ast->lparenToken);
886 const bool needParentheses = ast->formals &&
887 (ast->formals->next ||
888 (ast->formals->element && ast->formals->element->bindingTarget));
889 if (ast->isArrowFunction && needParentheses)
890 out(str: "(");
891 int baseIndent = lw.increaseIndent(level: 1);
892 accept(node: ast->formals);
893 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
894 if (ast->isArrowFunction && needParentheses)
895 out(str: ")");
896 out(loc: ast->rparenToken);
897 if (ast->isArrowFunction && !ast->formals)
898 out(str: "()");
899 out(str: " ");
900 if (ast->isArrowFunction)
901 out(str: "=> ");
902 out(loc: ast->lbraceToken);
903 if (ast->lbraceToken.length != 0)
904 ++expressionDepth;
905 if (ast->body) {
906 if (ast->body->next || ast->lbraceToken.length != 0) {
907 lnAcceptIndented(node: ast->body);
908 newLine();
909 } else {
910 // print a single statement in one line. E.g. x => x * 2
911 baseIndent = lw.increaseIndent(level: 1);
912 accept(node: ast->body);
913 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
914 }
915 }
916 if (ast->lbraceToken.length != 0)
917 --expressionDepth;
918 out(loc: ast->rbraceToken);
919 return false;
920 }
921
922 bool visit(Elision *ast) override
923 {
924 for (Elision *it = ast; it; it = it->next) {
925 if (it->next)
926 out(str: ", "); // ast->commaToken
927 }
928 return false;
929 }
930
931 bool visit(ArgumentList *ast) override
932 {
933 for (ArgumentList *it = ast; it; it = it->next) {
934 if (it->isSpreadElement)
935 out(str: "...");
936 accept(node: it->expression);
937 if (it->next) {
938 out(str: ", "); // it->commaToken
939 }
940 }
941 return false;
942 }
943
944 bool visit(StatementList *ast) override
945 {
946 ++expressionDepth;
947 for (StatementList *it = ast; it; it = it->next) {
948 // ### work around parser bug: skip empty statements with wrong tokens
949 if (EmptyStatement *emptyStatement = cast<EmptyStatement *>(ast: it->statement)) {
950 if (loc2Str(emptyStatement->semicolonToken) != QLatin1String(";"))
951 continue;
952 }
953
954 accept(node: it->statement);
955 if (it->next)
956 newLine();
957 }
958 --expressionDepth;
959 return false;
960 }
961
962 bool visit(VariableDeclarationList *ast) override
963 {
964 for (VariableDeclarationList *it = ast; it; it = it->next) {
965 accept(node: it->declaration);
966 if (it->next)
967 out(str: ", "); // it->commaToken
968 }
969 return false;
970 }
971
972 bool visit(CaseClauses *ast) override
973 {
974 for (CaseClauses *it = ast; it; it = it->next) {
975 accept(node: it->clause);
976 if (it->next)
977 newLine();
978 }
979 return false;
980 }
981
982 bool visit(FormalParameterList *ast) override
983 {
984 for (FormalParameterList *it = ast; it; it = it->next) {
985 // compare FormalParameterList::finish
986 if (auto id = it->element->bindingIdentifier.toString(); !id.isEmpty())
987 out(str: id);
988 if (it->element->bindingTarget)
989 accept(node: it->element->bindingTarget);
990 if (it->next)
991 out(str: ", ");
992 }
993 return false;
994 }
995
996 // to check
997 bool visit(TypeExpression *) override { return true; }
998 bool visit(SuperLiteral *) override
999 {
1000 out(str: "super");
1001 return true;
1002 }
1003 bool visit(PatternProperty *) override { return true; }
1004 bool visit(ComputedPropertyName *) override
1005 {
1006 out(str: "[");
1007 return true;
1008 }
1009 bool visit(TaggedTemplate *) override { return true; }
1010 bool visit(Expression *el) override
1011 {
1012 accept(node: el->left);
1013 out(str: ", ");
1014 accept(node: el->right);
1015 return false;
1016 }
1017 bool visit(ExpressionStatement *el) override
1018 {
1019 if (addSemicolons())
1020 postOps[el->expression].append(t: [this]() { out(str: ";"); });
1021 return true;
1022 }
1023 bool visit(YieldExpression *) override { return true; }
1024 bool visit(ClassExpression *) override { return true; }
1025
1026 // Return false because we want to omit default function calls in accept0 implementation.
1027 bool visit(ClassDeclaration *ast) override
1028 {
1029 preVisit(n: ast);
1030 out(loc: ast->classToken);
1031 out(str: " ");
1032 out(str: ast->name);
1033 if (ast->heritage) {
1034 out(str: " extends ");
1035 accept(node: ast->heritage);
1036 }
1037 out(str: " {");
1038 int baseIndent = lw.increaseIndent();
1039 for (ClassElementList *it = ast->elements; it; it = it->next) {
1040 PatternProperty *property = it->property;
1041 lw.newline();
1042 preVisit(n: property);
1043 if (it->isStatic)
1044 out(str: "static ");
1045 if (property->type == PatternProperty::Getter)
1046 out(str: "get ");
1047 else if (property->type == PatternProperty::Setter)
1048 out(str: "set ");
1049 FunctionExpression *f = AST::cast<FunctionExpression *>(ast: property->initializer);
1050 const bool scoped = f->lbraceToken.length != 0;
1051 out(loc: f->functionToken);
1052 out(loc: f->lparenToken);
1053 accept(node: f->formals);
1054 out(loc: f->rparenToken);
1055 out(loc: f->lbraceToken);
1056 if (scoped)
1057 ++expressionDepth;
1058 if (f->body) {
1059 if (f->body->next || scoped) {
1060 lnAcceptIndented(node: f->body);
1061 lw.newline();
1062 } else {
1063 baseIndent = lw.increaseIndent(level: 1);
1064 accept(node: f->body);
1065 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
1066 }
1067 }
1068 if (scoped)
1069 --expressionDepth;
1070 out(loc: f->rbraceToken);
1071 lw.newline();
1072 postVisit(n: property);
1073 }
1074 lw.decreaseIndent(level: 1, expectedIndent: baseIndent);
1075 out(str: "}");
1076 postVisit(n: ast);
1077 return false;
1078 }
1079
1080 bool visit(ClassElementList *) override { return true; }
1081 bool visit(Program *) override { return true; }
1082 bool visit(NameSpaceImport *) override { return true; }
1083 bool visit(ImportSpecifier *) override { return true; }
1084 bool visit(ImportsList *) override { return true; }
1085 bool visit(NamedImports *) override { return true; }
1086 bool visit(FromClause *) override { return true; }
1087 bool visit(ImportClause *) override { return true; }
1088 bool visit(ImportDeclaration *) override { return true; }
1089 bool visit(ExportSpecifier *) override { return true; }
1090 bool visit(ExportsList *) override { return true; }
1091 bool visit(ExportClause *) override { return true; }
1092 bool visit(ExportDeclaration *) override { return true; }
1093 bool visit(ESModule *) override { return true; }
1094 bool visit(DebuggerStatement *) override { return true; }
1095 bool visit(Type *) override { return true; }
1096 bool visit(TypeAnnotation *) override { return true; }
1097
1098 // overridden to use BasicVisitor (and ensure warnings about new added AST)
1099 void endVisit(UiProgram *) override { }
1100 void endVisit(UiImport *) override { }
1101 void endVisit(UiHeaderItemList *) override { }
1102#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
1103 void endVisit(UiPragmaValueList *) override { }
1104#endif
1105 void endVisit(UiPragma *) override { }
1106 void endVisit(UiPublicMember *) override { }
1107 void endVisit(UiSourceElement *) override { }
1108 void endVisit(UiObjectDefinition *) override { }
1109 void endVisit(UiObjectInitializer *) override { }
1110 void endVisit(UiObjectBinding *) override { }
1111 void endVisit(UiScriptBinding *) override { }
1112 void endVisit(UiArrayBinding *) override { }
1113 void endVisit(UiParameterList *) override { }
1114 void endVisit(UiObjectMemberList *) override { }
1115 void endVisit(UiArrayMemberList *) override { }
1116 void endVisit(UiQualifiedId *) override { }
1117 void endVisit(UiEnumDeclaration *) override { }
1118 void endVisit(UiEnumMemberList *) override { }
1119 void endVisit(UiVersionSpecifier *) override { }
1120 void endVisit(UiInlineComponent *) override { }
1121 void endVisit(UiAnnotation *) override { }
1122 void endVisit(UiAnnotationList *) override { }
1123 void endVisit(UiRequired *) override { }
1124 void endVisit(TypeExpression *) override { }
1125 void endVisit(ThisExpression *) override { }
1126 void endVisit(IdentifierExpression *) override { }
1127 void endVisit(NullExpression *) override { }
1128 void endVisit(TrueLiteral *) override { }
1129 void endVisit(FalseLiteral *) override { }
1130 void endVisit(SuperLiteral *) override { }
1131 void endVisit(StringLiteral *) override { }
1132 void endVisit(TemplateLiteral *) override { }
1133 void endVisit(NumericLiteral *) override { }
1134 void endVisit(RegExpLiteral *) override { }
1135 void endVisit(ArrayPattern *) override { }
1136 void endVisit(ObjectPattern *) override { }
1137 void endVisit(PatternElementList *) override { }
1138 void endVisit(PatternPropertyList *) override { }
1139 void endVisit(PatternElement *) override { }
1140 void endVisit(PatternProperty *) override { }
1141 void endVisit(Elision *) override { }
1142 void endVisit(NestedExpression *) override { }
1143 void endVisit(IdentifierPropertyName *) override { }
1144 void endVisit(StringLiteralPropertyName *) override { }
1145 void endVisit(NumericLiteralPropertyName *) override { }
1146 void endVisit(ComputedPropertyName *) override { out(str: "]"); }
1147 void endVisit(ArrayMemberExpression *) override { }
1148 void endVisit(FieldMemberExpression *) override { }
1149 void endVisit(TaggedTemplate *) override { }
1150 void endVisit(NewMemberExpression *) override { }
1151 void endVisit(NewExpression *) override { }
1152 void endVisit(CallExpression *) override { }
1153 void endVisit(ArgumentList *) override { }
1154 void endVisit(PostIncrementExpression *) override { }
1155 void endVisit(PostDecrementExpression *) override { }
1156 void endVisit(DeleteExpression *) override { }
1157 void endVisit(VoidExpression *) override { }
1158 void endVisit(TypeOfExpression *) override { }
1159 void endVisit(PreIncrementExpression *) override { }
1160 void endVisit(PreDecrementExpression *) override { }
1161 void endVisit(UnaryPlusExpression *) override { }
1162 void endVisit(UnaryMinusExpression *) override { }
1163 void endVisit(TildeExpression *) override { }
1164 void endVisit(NotExpression *) override { }
1165 void endVisit(BinaryExpression *) override { }
1166 void endVisit(ConditionalExpression *) override { }
1167 void endVisit(Expression *) override { }
1168 void endVisit(Block *) override { }
1169 void endVisit(StatementList *) override { }
1170 void endVisit(VariableStatement *) override { }
1171 void endVisit(VariableDeclarationList *) override { }
1172 void endVisit(EmptyStatement *) override { }
1173 void endVisit(ExpressionStatement *) override { }
1174 void endVisit(IfStatement *) override { }
1175 void endVisit(DoWhileStatement *) override { }
1176 void endVisit(WhileStatement *) override { }
1177 void endVisit(ForStatement *) override { }
1178 void endVisit(ForEachStatement *) override { }
1179 void endVisit(ContinueStatement *) override { }
1180 void endVisit(BreakStatement *) override { }
1181 void endVisit(ReturnStatement *) override { }
1182 void endVisit(YieldExpression *) override { }
1183 void endVisit(WithStatement *) override { }
1184 void endVisit(SwitchStatement *) override { }
1185 void endVisit(CaseBlock *) override { }
1186 void endVisit(CaseClauses *) override { }
1187 void endVisit(CaseClause *) override { }
1188 void endVisit(DefaultClause *) override { }
1189 void endVisit(LabelledStatement *) override { }
1190 void endVisit(ThrowStatement *) override { }
1191 void endVisit(TryStatement *) override { }
1192 void endVisit(Catch *) override { }
1193 void endVisit(Finally *) override { }
1194 void endVisit(FunctionDeclaration *) override { }
1195 void endVisit(FunctionExpression *) override { }
1196 void endVisit(FormalParameterList *) override { }
1197 void endVisit(ClassExpression *) override { }
1198 void endVisit(ClassDeclaration *) override { }
1199 void endVisit(ClassElementList *) override { }
1200 void endVisit(Program *) override { }
1201 void endVisit(NameSpaceImport *) override { }
1202 void endVisit(ImportSpecifier *) override { }
1203 void endVisit(ImportsList *) override { }
1204 void endVisit(NamedImports *) override { }
1205 void endVisit(FromClause *) override { }
1206 void endVisit(ImportClause *) override { }
1207 void endVisit(ImportDeclaration *) override { }
1208 void endVisit(ExportSpecifier *) override { }
1209 void endVisit(ExportsList *) override { }
1210 void endVisit(ExportClause *) override { }
1211 void endVisit(ExportDeclaration *) override { }
1212 void endVisit(ESModule *) override { }
1213 void endVisit(DebuggerStatement *) override { }
1214 void endVisit(Type *) override { }
1215 void endVisit(TypeAnnotation *) override { }
1216
1217 void throwRecursionDepthError() override
1218 {
1219 out(str: "/* ERROR: Hit recursion limit visiting AST, rewrite failed */");
1220 }
1221};
1222
1223void reformatAst(OutWriter &lw, std::shared_ptr<AstComments> comments,
1224 const std::function<QStringView(SourceLocation)> loc2Str, AST::Node *n)
1225{
1226 if (n) {
1227 Rewriter rewriter(lw, comments, loc2Str, n);
1228 }
1229}
1230
1231} // namespace Dom
1232} // namespace QQmlJS
1233QT_END_NAMESPACE
1234

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