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>
21bool ScriptFormatter::preVisit(Node *n)
23 const CommentedElement *c = comments->commentForNode(n, CommentAnchor{});
27 if (!c->preComments().empty()) {
29 for (
const auto &preComment : c->preComments())
30 lw.maybeWriteComment(preComment);
33 postOps[n].append([c,
this]() {
34 if (!c->postComments().empty()) {
36 for (
const auto &postComment : c->postComments())
37 lw.maybeWriteComment(postComment);
43void ScriptFormatter::postVisit(Node *n)
45 for (
auto &op : postOps[n]) {
51void ScriptFormatter::lnAcceptIndented(Node *node)
53 int indent = lw.increaseIndent(1);
56 lw.decreaseIndent(1, indent);
59bool ScriptFormatter::acceptBlockOrIndented(Node *ast,
bool finishWithSpaceOrNewline)
61 if (
auto *es = cast<EmptyStatement *>(ast)) {
62 writeOutSemicolon(es);
65 if (cast<Block *>(ast)) {
66 ensureSpaceIfNoComment();
68 if (finishWithSpaceOrNewline)
69 ensureSpaceIfNoComment();
72 if (finishWithSpaceOrNewline)
73 postOps[ast].append([
this]() { ensureNewline(); });
74 lnAcceptIndented(ast);
79bool ScriptFormatter::visit(ThisExpression *ast)
85bool ScriptFormatter::visit(NullExpression *ast)
90bool ScriptFormatter::visit(TrueLiteral *ast)
95bool ScriptFormatter::visit(FalseLiteral *ast)
101bool ScriptFormatter::visit(IdentifierExpression *ast)
103 out(ast->identifierToken);
106bool ScriptFormatter::visit(StringLiteral *ast)
109 if (ast->literalToken.length == 0)
111 QStringView str = m_script->loc2Str(ast->literalToken);
112 if (lw.indentNextlines && str.contains(QLatin1Char(
'\n'))) {
114 lw.indentNextlines =
false;
116 lw.indentNextlines =
true;
122bool ScriptFormatter::visit(NumericLiteral *ast)
124 outWithComments(ast->literalToken, ast);
127bool ScriptFormatter::visit(RegExpLiteral *ast)
129 out(ast->literalToken);
133bool ScriptFormatter::visit(ArrayPattern *ast)
135 outWithComments(ast->lbracketToken, ast);
136 int baseIndent = lw.increaseIndent(1);
138 accept(ast->elements);
139 outWithComments(ast->commaToken, ast);
140 auto lastElement = lastListElement(ast->elements);
141 if (lastElement->element && cast<ObjectPattern *>(lastElement->element->initializer)) {
145 outWithComments(ast->commaToken, ast);
147 lw.decreaseIndent(1, baseIndent);
148 outWithComments(ast->rbracketToken, ast);
152bool ScriptFormatter::visit(ObjectPattern *ast)
154 outWithComments(ast->lbraceToken, ast);
156 if (ast->properties) {
157 lnAcceptIndented(ast->properties);
161 outWithComments(ast->rbraceToken, ast);
165bool ScriptFormatter::visit(PatternElementList *ast)
167 for (PatternElementList *it = ast; it; it = it->next) {
168 const bool isObjectInitializer =
169 it->element && cast<ObjectPattern *>(it->element->initializer);
170 if (isObjectInitializer)
176 ensureSpaceIfNoComment();
181 outWithComments(it->next->commaToken, it);
182 ensureSpaceIfNoComment();
183 if (isObjectInitializer)
190bool ScriptFormatter::visit(PatternPropertyList *ast)
192 for (PatternPropertyList *it = ast; it; it = it->next) {
193 accept(it->property);
203bool ScriptFormatter::visit(AST::PatternProperty *property)
205 if (property->type == PatternElement::Getter || property->type == PatternElement::Setter
206 || property->type == PatternElement::Method) {
211 if (property->type == PatternProperty::Getter) {
213 ensureSpaceIfNoComment();
214 }
else if (property->type == PatternProperty::Setter) {
216 ensureSpaceIfNoComment();
218 FunctionExpression *f = AST::cast<FunctionExpression *>(property->initializer);
219 if (f->isGenerator) {
222 accept(property->name);
226 ensureSpaceIfNoComment();
228 const bool scoped = f->lbraceToken.isValid();
232 if (f->body->next || scoped) {
233 lnAcceptIndented(f->body);
236 auto baseIndent = lw.increaseIndent(1);
238 lw.decreaseIndent(1, baseIndent);
248 accept(property->name);
249 bool useInitializer =
false;
250 const bool bindingIdentifierExist = !property->bindingIdentifier.isEmpty();
251 if (property->colonToken.isValid()) {
254 ensureSpaceIfNoComment();
255 useInitializer =
true;
256 if (bindingIdentifierExist)
257 out(property->bindingIdentifier);
258 if (property->bindingTarget)
259 accept(property->bindingTarget);
262 if (property->initializer) {
264 if (bindingIdentifierExist) {
265 ensureSpaceIfNoComment();
267 ensureSpaceIfNoComment();
268 useInitializer =
true;
271 accept(property->initializer);
276bool ScriptFormatter::visit(NestedExpression *ast)
278 out(ast->lparenToken);
279 int baseIndent = lw.increaseIndent(1);
280 accept(ast->expression);
281 lw.decreaseIndent(1, baseIndent);
282 out(ast->rparenToken);
286bool ScriptFormatter::visit(IdentifierPropertyName *ast)
288 out(ast->id.toString());
291bool ScriptFormatter::visit(StringLiteralPropertyName *ast)
293 out(ast->propertyNameToken);
296bool ScriptFormatter::visit(NumericLiteralPropertyName *ast)
298 out(QString::number(ast->id));
302bool ScriptFormatter::visit(TemplateLiteral *ast)
305 if (ast->literalToken.length != 0) {
306 QStringView str = m_script->loc2Str(ast->literalToken);
307 if (lw.indentNextlines && str.contains(QLatin1Char(
'\n'))) {
309 lw.indentNextlines =
false;
311 lw.indentNextlines =
true;
316 accept(ast->expression);
320bool ScriptFormatter::visit(ArrayMemberExpression *ast)
323 out(ast->optionalToken);
324 out(ast->lbracketToken);
325 int indent = lw.increaseIndent(1);
326 accept(ast->expression);
327 lw.decreaseIndent(1, indent);
328 out(ast->rbracketToken);
332bool ScriptFormatter::visit(FieldMemberExpression *ast)
336 out(ast->identifierToken);
340bool ScriptFormatter::visit(NewMemberExpression *ast)
343 ensureSpaceIfNoComment();
345 out(ast->lparenToken);
346 accept(ast->arguments);
347 out(ast->rparenToken);
351bool ScriptFormatter::visit(NewExpression *ast)
354 ensureSpaceIfNoComment();
355 accept(ast->expression);
359bool ScriptFormatter::visit(CallExpression *ast)
362 outWithComments(ast->optionalToken, ast);
363 outWithComments(ast->lparenToken, ast);
364 accept(ast->arguments);
365 outWithComments(ast->rparenToken, ast);
369bool ScriptFormatter::visit(PostIncrementExpression *ast)
372 out(ast->incrementToken);
376bool ScriptFormatter::visit(PostDecrementExpression *ast)
379 out(ast->decrementToken);
383bool ScriptFormatter::visit(PreIncrementExpression *ast)
385 out(ast->incrementToken);
386 accept(ast->expression);
390bool ScriptFormatter::visit(PreDecrementExpression *ast)
392 out(ast->decrementToken);
393 accept(ast->expression);
397bool ScriptFormatter::visit(DeleteExpression *ast)
400 ensureSpaceIfNoComment();
401 accept(ast->expression);
405bool ScriptFormatter::visit(VoidExpression *ast)
408 ensureSpaceIfNoComment();
409 accept(ast->expression);
413bool ScriptFormatter::visit(TypeOfExpression *ast)
416 ensureSpaceIfNoComment();
417 accept(ast->expression);
421bool ScriptFormatter::visit(UnaryPlusExpression *ast)
424 accept(ast->expression);
428bool ScriptFormatter::visit(UnaryMinusExpression *ast)
430 out(ast->minusToken);
431 accept(ast->expression);
435bool ScriptFormatter::visit(TildeExpression *ast)
437 out(ast->tildeToken);
438 accept(ast->expression);
442bool ScriptFormatter::visit(NotExpression *ast)
445 accept(ast->expression);
449bool ScriptFormatter::visit(BinaryExpression *ast)
452 ensureSpaceIfNoComment();
453 out(ast->operatorToken);
454 ensureSpaceIfNoComment();
459bool ScriptFormatter::visit(ConditionalExpression *ast)
461 accept(ast->expression);
462 ensureSpaceIfNoComment();
464 ensureSpaceIfNoComment();
466 ensureSpaceIfNoComment();
468 ensureSpaceIfNoComment();
473bool ScriptFormatter::visit(Block *ast)
476 const CommentedElement *c =
477 comments->commentForNode(ast, CommentAnchor::from(ast->lbraceToken));
480 out(ast->lbraceToken);
481 const int indent = lw.increaseIndent();
485 if (ast->statements) {
488 accept(ast->statements);
495 c = comments->commentForNode(ast, CommentAnchor::from(ast->rbraceToken));
498 lw.decreaseIndent(1, indent);
499 out(ast->rbraceToken);
505bool ScriptFormatter::visit(VariableStatement *ast)
507 out(ast->declarationKindToken);
508 ensureSpaceIfNoComment();
509 accept(ast->declarations);
511 writeOutSemicolon(ast);
515bool ScriptFormatter::visit(PatternElement *ast)
518 case PatternElement::Literal:
519 case PatternElement::Method:
520 case PatternElement::Binding:
522 case PatternElement::Getter:
524 ensureSpaceIfNoComment();
526 case PatternElement::Setter:
528 ensureSpaceIfNoComment();
530 case PatternElement::SpreadElement:
535 accept(ast->bindingTarget);
536 if (!ast->destructuringPattern())
537 out(ast->identifierToken);
538 if (ast->initializer) {
539 if (ast->isVariableDeclaration() || ast->type == AST::PatternElement::Binding) {
540 ensureSpaceIfNoComment();
541 outWithComments(ast->equalToken, ast);
542 ensureSpaceIfNoComment();
544 accept(ast->initializer);
546 accept(ast->typeAnnotation);
550bool ScriptFormatter::visit(TypeAnnotation *ast)
552 out(ast->colonToken);
553 ensureSpaceIfNoComment();
558bool ScriptFormatter::visit(Type *ast)
561 if (ast->typeArgument) {
562 outWithComments(ast->lAngleBracketToken, ast);
563 accept(ast->typeArgument);
564 outWithComments(ast->rAngleBracketToken, ast);
569bool ScriptFormatter::visit(UiQualifiedId *ast)
571 for (UiQualifiedId *it = ast; it; it = it->next) {
572 outWithComments(it->dotToken, it);
573 outWithComments(it->identifierToken, it);
578bool ScriptFormatter::visit(EmptyStatement *)
580 lw.lineWriter.ensureSemicolon();
584bool ScriptFormatter::visit(IfStatement *ast)
587 ensureSpaceIfNoComment();
588 out(ast->lparenToken);
589 preVisit(ast->expression);
590 ast->expression->accept0(
this);
591 out(ast->rparenToken);
592 postVisit(ast->expression);
593 acceptBlockOrIndented(ast->ok, ast->ko);
596 if (cast<Block *>(ast->ko) || cast<IfStatement *>(ast->ko)) {
597 ensureSpaceIfNoComment();
600 lnAcceptIndented(ast->ko);
606bool ScriptFormatter::visit(DoWhileStatement *ast)
609 acceptBlockOrIndented(ast->statement,
true);
610 out(ast->whileToken);
611 ensureSpaceIfNoComment();
612 outWithComments(ast->lparenToken, ast);
613 accept(ast->expression);
614 outWithComments(ast->rparenToken, ast);
618bool ScriptFormatter::visit(WhileStatement *ast)
620 out(ast->whileToken);
621 ensureSpaceIfNoComment();
622 outWithComments(ast->lparenToken, ast);
623 accept(ast->expression);
624 outWithComments(ast->rparenToken, ast);
625 acceptBlockOrIndented(ast->statement);
629bool ScriptFormatter::visit(ForStatement *ast)
632 ensureSpaceIfNoComment();
633 outWithComments(ast->lparenToken, ast);
634 if (ast->initialiser) {
635 accept(ast->initialiser);
636 }
else if (ast->declarations) {
637 if (
auto pe = ast->declarations->declaration) {
638 out(pe->declarationKindToken);
639 ensureSpaceIfNoComment();
642 for (VariableDeclarationList *it = ast->declarations; it; it = it->next) {
643 if (!std::exchange(first,
false)) {
645 ensureSpaceIfNoComment();
647 accept(it->declaration);
653 ensureSpaceIfNoComment();
654 accept(ast->condition);
656 ensureSpaceIfNoComment();
657 accept(ast->expression);
658 outWithComments(ast->rparenToken, ast);
659 acceptBlockOrIndented(ast->statement);
663bool ScriptFormatter::visit(ForEachStatement *ast)
666 ensureSpaceIfNoComment();
667 out(ast->lparenToken);
668 if (
auto pe = AST::cast<PatternElement *>(ast->lhs)) {
669 out(pe->declarationKindToken);
670 ensureSpaceIfNoComment();
673 ensureSpaceIfNoComment();
675 ensureSpaceIfNoComment();
676 accept(ast->expression);
677 out(ast->rparenToken);
678 acceptBlockOrIndented(ast->statement);
682bool ScriptFormatter::visit(ContinueStatement *ast)
684 out(ast->continueToken);
685 if (!ast->label.isNull()) {
686 ensureSpaceIfNoComment();
687 out(ast->identifierToken);
690 writeOutSemicolon(ast);
694bool ScriptFormatter::visit(BreakStatement *ast)
696 out(ast->breakToken);
697 if (!ast->label.isNull()) {
698 ensureSpaceIfNoComment();
699 out(ast->identifierToken);
702 writeOutSemicolon(ast);
706bool ScriptFormatter::visit(ReturnStatement *ast)
708 out(ast->returnToken);
709 if (ast->expression) {
710 if (ast->returnToken.length != 0)
711 ensureSpaceIfNoComment();
712 accept(ast->expression);
714 if (ast->returnToken.length > 0 && addSemicolons())
715 writeOutSemicolon(ast);
719bool ScriptFormatter::visit(YieldExpression *ast)
721 out(ast->yieldToken);
722 if (ast->isYieldStar)
724 if (ast->expression) {
725 if (ast->yieldToken.isValid())
726 ensureSpaceIfNoComment();
727 accept(ast->expression);
732bool ScriptFormatter::visit(ThrowStatement *ast)
734 out(ast->throwToken);
735 if (ast->expression) {
736 ensureSpaceIfNoComment();
737 accept(ast->expression);
740 writeOutSemicolon(ast);
744bool ScriptFormatter::visit(WithStatement *ast)
747 ensureSpaceIfNoComment();
748 out(ast->lparenToken);
749 accept(ast->expression);
750 out(ast->rparenToken);
751 acceptBlockOrIndented(ast->statement);
755bool ScriptFormatter::visit(SwitchStatement *ast)
757 out(ast->switchToken);
758 ensureSpaceIfNoComment();
759 out(ast->lparenToken);
760 accept(ast->expression);
761 out(ast->rparenToken);
762 ensureSpaceIfNoComment();
767bool ScriptFormatter::visit(CaseBlock *ast)
769 out(ast->lbraceToken);
772 accept(ast->clauses);
773 if (ast->clauses && ast->defaultClause)
775 accept(ast->defaultClause);
776 if (ast->moreClauses)
778 accept(ast->moreClauses);
781 out(ast->rbraceToken);
785bool ScriptFormatter::visit(CaseClause *ast)
788 ensureSpaceIfNoComment();
789 accept(ast->expression);
790 outWithComments(ast->colonToken, ast);
792 lnAcceptIndented(ast->statements);
796bool ScriptFormatter::visit(DefaultClause *ast)
798 out(ast->defaultToken);
799 out(ast->colonToken);
800 lnAcceptIndented(ast->statements);
804bool ScriptFormatter::visit(LabelledStatement *ast)
806 out(ast->identifierToken);
808 ensureSpaceIfNoComment();
809 accept(ast->statement);
813bool ScriptFormatter::visit(TryStatement *ast)
815 outWithComments(ast->tryToken, ast);
816 ensureSpaceIfNoComment();
817 accept(ast->statement);
818 if (ast->catchExpression) {
819 ensureSpaceIfNoComment();
820 accept(ast->catchExpression);
822 if (ast->finallyExpression) {
823 ensureSpaceIfNoComment();
824 accept(ast->finallyExpression);
829bool ScriptFormatter::visit(Catch *ast)
831 outWithComments(ast->catchToken, ast);
832 ensureSpaceIfNoComment();
833 outWithComments(ast->lparenToken, ast);
834 outWithComments(ast->identifierToken, ast);
835 outWithComments(ast->rparenToken, ast);
836 ensureSpaceIfNoComment();
837 accept(ast->statement);
841bool ScriptFormatter::visit(Finally *ast)
843 outWithComments(ast->finallyToken, ast);
844 ensureSpaceIfNoComment();
845 accept(ast->statement);
849bool ScriptFormatter::visit(FunctionDeclaration *ast)
851 return ScriptFormatter::visit(
static_cast<FunctionExpression *>(ast));
854bool ScriptFormatter::visit(FunctionExpression *ast)
856 if (!ast->isArrowFunction) {
857 outWithComments(ast->functionToken, ast);
858 if (ast->isGenerator)
859 outWithComments(ast->starToken, ast);
860 ensureSpaceIfNoComment();
861 outWithComments(ast->identifierToken, ast);
864 const bool removeParentheses = ast->isArrowFunction && ast->formals && !ast->formals->next
865 && (ast->formals->element && !ast->formals->element->bindingTarget);
869 outWithComments(ast->lparenToken, ast, removeParentheses ? OnlyComments : TokenAndComment);
870 int baseIndent = lw.increaseIndent(1);
871 accept(ast->formals);
872 lw.decreaseIndent(1, baseIndent);
873 outWithComments(ast->rparenToken, ast, removeParentheses ? OnlyComments : TokenAndComment);
874 accept(ast->typeAnnotation);
875 ensureSpaceIfNoComment();
876 if (ast->isArrowFunction) {
878 ensureSpaceIfNoComment();
880 outWithComments(ast->lbraceToken, ast);
881 if (ast->lbraceToken.length != 0)
884 if (ast->body->next || ast->lbraceToken.length != 0) {
885 lnAcceptIndented(ast->body);
889 baseIndent = lw.increaseIndent(1);
891 lw.decreaseIndent(1, baseIndent);
894 if (ast->lbraceToken.length != 0)
896 outWithComments(ast->rbraceToken, ast);
900bool ScriptFormatter::visit(Elision *ast)
902 for (Elision *it = ast; it; it = it->next) {
903 if (!it->commaToken.isValid())
905 outWithComments(it->commaToken, it);
907 ensureSpaceIfNoComment();
912bool ScriptFormatter::visit(ArgumentList *ast)
914 for (ArgumentList *it = ast; it; it = it->next) {
915 if (it->commaToken.isValid()) {
916 outWithComments(it->commaToken, it);
917 ensureSpaceIfNoComment();
919 if (it->spreadToken.isValid())
920 outWithComments(it->spreadToken, it);
921 accept(it->expression);
926bool ScriptFormatter::visit(StatementList *ast)
929 for (StatementList *it = ast; it; it = it->next) {
931 if (EmptyStatement *emptyStatement = cast<EmptyStatement *>(it->statement)) {
932 if (m_script->loc2Str(emptyStatement->semicolonToken) != QLatin1String(
";"))
936 accept(it->statement);
944 auto *commentForCurrentStatement =
945 comments->commentForNode(it->statement, CommentAnchor{});
946 auto *commentForNextStatement =
947 comments->commentForNode(it->next->statement, CommentAnchor{});
950 (commentForCurrentStatement && !commentForCurrentStatement->postComments().empty())
951 || (commentForNextStatement && !commentForNextStatement->preComments().empty())
954 quint32 lineDelta = it->next->firstSourceLocation().startLine
955 - it->statement->lastSourceLocation().startLine;
956 lineDelta = std::clamp(lineDelta, quint32{ 1 }, quint32{ 2 });
958 ensureNewline(lineDelta);
965bool ScriptFormatter::visit(VariableDeclarationList *ast)
967 for (VariableDeclarationList *it = ast; it; it = it->next) {
968 accept(it->declaration);
971 ensureSpaceIfNoComment();
977bool ScriptFormatter::visit(CaseClauses *ast)
979 for (CaseClauses *it = ast; it; it = it->next) {
987bool ScriptFormatter::visit(FormalParameterList *ast)
989 for (FormalParameterList *it = ast; it; it = it->next) {
991 if (it->commaToken.isValid()) {
992 outWithComments(it->commaToken, it);
993 ensureSpaceIfNoComment();
1000bool ScriptFormatter::visit(SuperLiteral *)
1005bool ScriptFormatter::visit(ComputedPropertyName *)
1010bool ScriptFormatter::visit(CommaExpression *el)
1014 ensureSpaceIfNoComment();
1018bool ScriptFormatter::visit(ExpressionStatement *el)
1020 if (addSemicolons())
1021 postOps[el->expression].append([
this, el]() { writeOutSemicolon(el); });
1026bool ScriptFormatter::visit(ClassDeclaration *ast)
1028 out(ast->classToken);
1029 ensureSpaceIfNoComment();
1030 outWithComments(ast->identifierToken, ast);
1031 if (ast->heritage) {
1032 ensureSpaceIfNoComment();
1034 ensureSpaceIfNoComment();
1035 accept(ast->heritage);
1037 ensureSpaceIfNoComment();
1038 outWithComments(ast->lbraceToken, ast);
1039 int baseIndent = lw.increaseIndent();
1040 for (ClassElementList *it = ast->elements; it; it = it->next) {
1044 ensureSpaceIfNoComment();
1046 accept(it->property);
1049 lw.decreaseIndent(1, baseIndent);
1050 outWithComments(ast->rbraceToken, ast);
1054bool ScriptFormatter::visit(AST::ImportDeclaration *ast)
1056 out(ast->importToken);
1057 ensureSpaceIfNoComment();
1058 if (!ast->moduleSpecifier.isNull()) {
1059 out(ast->moduleSpecifierToken);
1064bool ScriptFormatter::visit(AST::ImportSpecifier *ast)
1066 if (!ast->identifier.isNull()) {
1067 out(ast->identifierToken);
1068 ensureSpaceIfNoComment();
1070 ensureSpaceIfNoComment();
1072 out(ast->importedBindingToken);
1076bool ScriptFormatter::visit(AST::NameSpaceImport *ast)
1078 out(ast->starToken);
1079 ensureSpaceIfNoComment();
1081 ensureSpaceIfNoComment();
1082 out(ast->importedBindingToken);
1086bool ScriptFormatter::visit(AST::ImportsList *ast)
1088 for (ImportsList *it = ast; it; it = it->next) {
1089 accept(it->importSpecifier);
1092 ensureSpaceIfNoComment();
1097bool ScriptFormatter::visit(AST::NamedImports *ast)
1099 out(ast->leftBraceToken);
1100 if (ast->importsList) {
1101 ensureSpaceIfNoComment();
1106bool ScriptFormatter::visit(AST::ImportClause *ast)
1108 if (!ast->importedDefaultBinding.isNull()) {
1109 out(ast->importedDefaultBindingToken);
1110 if (ast->nameSpaceImport || ast->namedImports) {
1112 ensureSpaceIfNoComment();
1118bool ScriptFormatter::visit(AST::ExportDeclaration *ast)
1120 out(ast->exportToken);
1121 ensureSpaceIfNoComment();
1122 if (ast->exportDefault) {
1124 ensureSpaceIfNoComment();
1126 if (ast->exportsAll()) {
1132bool ScriptFormatter::visit(AST::ExportClause *ast)
1134 out(ast->leftBraceToken);
1135 if (ast->exportsList) {
1136 ensureSpaceIfNoComment();
1141bool ScriptFormatter::visit(AST::ExportSpecifier *ast)
1143 out(ast->identifier);
1144 if (ast->exportedIdentifierToken.isValid()) {
1145 ensureSpaceIfNoComment();
1147 ensureSpaceIfNoComment();
1148 out(ast->exportedIdentifier);
1153bool ScriptFormatter::visit(AST::ExportsList *ast)
1155 for (ExportsList *it = ast; it; it = it->next) {
1156 accept(it->exportSpecifier);
1159 ensureSpaceIfNoComment();
1165bool ScriptFormatter::visit(AST::FromClause *ast)
1167 ensureSpaceIfNoComment();
1168 out(ast->fromToken);
1169 ensureSpaceIfNoComment();
1170 out(ast->moduleSpecifierToken);
1174void ScriptFormatter::endVisit(ComputedPropertyName *)
1179void ScriptFormatter::endVisit(AST::ExportDeclaration *ast)
1184 if (ast->fromClause) {
1185 writeOutSemicolon(ast);
1190 if (ast->exportClause && !ast->fromClause) {
1191 writeOutSemicolon(ast);
1196 if (ast->exportDefault && ast->variableStatementOrDeclaration) {
1198 if (!(ast->variableStatementOrDeclaration->kind == Node::Kind_FunctionDeclaration
1199 || ast->variableStatementOrDeclaration->kind == Node::Kind_ClassDeclaration)) {
1200 writeOutSemicolon(ast);
1205 if (ast->variableStatementOrDeclaration->kind == Node::Kind_FunctionDeclaration
1206 &&
static_cast<AST::FunctionDeclaration *>(ast->variableStatementOrDeclaration)
1207 ->isArrowFunction) {
1208 writeOutSemicolon(ast);
1213void ScriptFormatter::endVisit(AST::ExportClause *ast)
1215 if (ast->exportsList) {
1216 ensureSpaceIfNoComment();
1218 out(ast->rightBraceToken);
1221void ScriptFormatter::endVisit(AST::NamedImports *ast)
1223 if (ast->importsList) {
1224 ensureSpaceIfNoComment();
1226 out(ast->rightBraceToken);
1229void ScriptFormatter::endVisit(AST::ImportDeclaration *id)
1231 writeOutSemicolon(id);
1234void ScriptFormatter::throwRecursionDepthError()
1236 out(
"/* ERROR: Hit recursion limit ScriptFormatter::visiting AST, rewrite failed */");
1243bool ScriptFormatter::canRemoveSemicolon(AST::Node *node)
1245 const auto canRelyOnASI = [
this](Node *node) {
1246 auto nodeLoc = node->lastSourceLocation().offset + 1;
1247 auto code = m_script->engine()->code();
1248 auto it = code.begin() + nodeLoc;
1249 auto end = code.end();
1255 if (c.isSpace() || c == u';') {
1260 if (c == u'/' && it + 1 != end) {
1262 if (*next == u'/') {
1264 it = std::find(next, end, u'\n');
1268 }
else if (*next == u'*') {
1272 if (*it == u'*' && it + 1 != end && *(it + 1) == u'/') {
1284 if (c == u'(' || c == u'[' || c == u'+' || c == u'-') {
1296 switch (node->kind) {
1297 case AST::Node::Kind_ExpressionStatement:
1298 return canRelyOnASI(cast<ExpressionStatement *>(node));
1299 case AST::Node::Kind_VariableStatement:
1300 return canRelyOnASI(cast<VariableStatement *>(node));
1301 case AST::Node::Kind_EmptyStatement:
1303 case AST::Node::Kind_ContinueStatement:
1304 case AST::Node::Kind_BreakStatement:
1305 case AST::Node::Kind_ReturnStatement:
1306 case AST::Node::Kind_ThrowStatement:
1307 case AST::Node::Kind_ExportDeclaration:
1308 case AST::Node::Kind_ImportDeclaration:
1309 case AST::Node::Kind_FromClause:
1310 case AST::Node::Kind_ExportClause:
1316OutWriter &ScriptFormatter::writeOutSemicolon(AST::Node *node)
1320 switch (lw.lineWriter.options().semicolonRule) {
1321 case LineWriterOptions::SemicolonRule::Essential:
1322 if (!canRemoveSemicolon(node))
1326 case LineWriterOptions::SemicolonRule::Always:
1330 Q_UNREACHABLE_RETURN(lw);
1334void reformatAst(OutWriter &lw,
const QQmlJS::Dom::ScriptExpression *
const script)
1337 ScriptFormatter formatter(lw, script);