aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldomreformatter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldomreformatter.cpp')
-rw-r--r--src/qmldom/qqmldomreformatter.cpp1980
1 files changed, 957 insertions, 1023 deletions
diff --git a/src/qmldom/qqmldomreformatter.cpp b/src/qmldom/qqmldomreformatter.cpp
index 9114f39c3e..95533b61ac 100644
--- a/src/qmldom/qqmldomreformatter.cpp
+++ b/src/qmldom/qqmldomreformatter.cpp
@@ -11,6 +11,7 @@
#include <QString>
+#include <algorithm>
#include <limits>
QT_BEGIN_NAMESPACE
@@ -19,1170 +20,1103 @@ namespace Dom {
using namespace AST;
-class Rewriter : protected BaseVisitor
+bool ScriptFormatter::preVisit(Node *n)
{
- OutWriter &lw;
- std::shared_ptr<AstComments> comments;
- std::function<QStringView(SourceLocation)> loc2Str;
- QHash<Node *, QList<std::function<void()>>> postOps;
- int expressionDepth = 0;
-
- bool addSemicolons() const { return expressionDepth > 0; }
-
-public:
- Rewriter(OutWriter &lw, std::shared_ptr<AstComments> comments,
- std::function<QStringView(SourceLocation)> loc2Str, Node *node)
- : lw(lw), comments(comments), loc2Str(loc2Str)
- {
- accept(node);
+ if (CommentedElement *c = comments->commentForNode(n)) {
+ c->writePre(lw);
+ postOps[n].append([c, this]() { c->writePost(lw); });
}
-
-protected:
- bool preVisit(Node *n) override
- {
- if (CommentedElement *c = comments->commentForNode(n)) {
- c->writePre(lw);
- postOps[n].append([c, this]() { c->writePost(lw); });
- }
- return true;
- }
- void postVisit(Node *n) override
- {
- for (auto &op : postOps[n]) {
- op();
- }
- postOps.remove(n);
+ return true;
+}
+void ScriptFormatter::postVisit(Node *n)
+{
+ for (auto &op : postOps[n]) {
+ op();
}
+ postOps.remove(n);
+}
- void accept(Node *node) { Node::accept(node, this); }
+void ScriptFormatter::lnAcceptIndented(Node *node)
+{
+ int indent = lw.increaseIndent(1);
+ lw.ensureNewline();
+ accept(node);
+ lw.decreaseIndent(1, indent);
+}
- void lnAcceptIndented(Node *node)
- {
- int indent = lw.increaseIndent(1);
- lw.ensureNewline();
- accept(node);
- lw.decreaseIndent(1, indent);
+bool ScriptFormatter::acceptBlockOrIndented(Node *ast, bool finishWithSpaceOrNewline)
+{
+ if (cast<Block *>(ast)) {
+ out(" ");
+ accept(ast);
+ if (finishWithSpaceOrNewline)
+ out(" ");
+ return true;
+ } else {
+ if (finishWithSpaceOrNewline)
+ postOps[ast].append([this]() { this->newLine(); });
+ lnAcceptIndented(ast);
+ return false;
}
+}
- void out(const char *str) { lw.write(QString::fromLatin1(str)); }
-
- void out(QStringView str) { lw.write(str); }
+bool ScriptFormatter::visit(ThisExpression *ast)
+{
+ out(ast->thisToken);
+ return true;
+}
- void out(const SourceLocation &loc)
- {
- if (loc.length != 0)
- out(loc2Str(loc));
- }
+bool ScriptFormatter::visit(NullExpression *ast)
+{
+ out(ast->nullToken);
+ return true;
+}
+bool ScriptFormatter::visit(TrueLiteral *ast)
+{
+ out(ast->trueToken);
+ return true;
+}
+bool ScriptFormatter::visit(FalseLiteral *ast)
+{
+ out(ast->falseToken);
+ return true;
+}
- void newLine() { lw.ensureNewline(); }
+bool ScriptFormatter::visit(IdentifierExpression *ast)
+{
+ out(ast->identifierToken);
+ return true;
+}
+bool ScriptFormatter::visit(StringLiteral *ast)
+{
+ // correctly handle multiline literals
+ if (ast->literalToken.length == 0)
+ return true;
+ QStringView str = loc2Str(ast->literalToken);
+ if (lw.indentNextlines && str.contains(QLatin1Char('\n'))) {
+ out(str.mid(0, 1));
+ lw.indentNextlines = false;
+ out(str.mid(1));
+ lw.indentNextlines = true;
+ } else {
+ out(str);
+ }
+ return true;
+}
+bool ScriptFormatter::visit(NumericLiteral *ast)
+{
+ out(ast->literalToken);
+ return true;
+}
+bool ScriptFormatter::visit(RegExpLiteral *ast)
+{
+ out(ast->literalToken);
+ return true;
+}
- bool acceptBlockOrIndented(Node *ast, bool finishWithSpaceOrNewline = false)
- {
- if (cast<Block *>(ast)) {
- out(" ");
- accept(ast);
- if (finishWithSpaceOrNewline)
- out(" ");
- return true;
- } else {
- if (finishWithSpaceOrNewline)
- postOps[ast].append([this]() { this->newLine(); });
- lnAcceptIndented(ast);
- return false;
+bool ScriptFormatter::visit(ArrayPattern *ast)
+{
+ out(ast->lbracketToken);
+ int baseIndent = lw.increaseIndent(1);
+ if (ast->elements) {
+ accept(ast->elements);
+ out(ast->commaToken);
+ auto lastElement = lastListElement(ast->elements);
+ if (lastElement->element && cast<ObjectPattern *>(lastElement->element->initializer)) {
+ newLine();
}
+ } else {
+ out(ast->commaToken);
}
+ lw.decreaseIndent(1, baseIndent);
+ out(ast->rbracketToken);
+ return false;
+}
- // we are not supposed to handle the ui
- bool visit(UiPragma *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiEnumDeclaration *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiEnumMemberList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiImport *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiObjectDefinition *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiObjectInitializer *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiParameterList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiPublicMember *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiObjectBinding *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiScriptBinding *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiArrayBinding *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiHeaderItemList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiObjectMemberList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiArrayMemberList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiQualifiedId *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiProgram *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiSourceElement *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiVersionSpecifier *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiInlineComponent *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiAnnotation *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiAnnotationList *) override
- {
- Q_ASSERT(false);
- return false;
- }
- bool visit(UiRequired *) override
- {
- Q_ASSERT(false);
- return false;
+bool ScriptFormatter::visit(ObjectPattern *ast)
+{
+ out(ast->lbraceToken);
+ ++expressionDepth;
+ if (ast->properties) {
+ lnAcceptIndented(ast->properties);
+ newLine();
}
+ --expressionDepth;
+ out(ast->rbraceToken);
+ return false;
+}
- bool visit(ThisExpression *ast) override
- {
- out(ast->thisToken);
- return true;
- }
- bool visit(NullExpression *ast) override
- {
- out(ast->nullToken);
- return true;
- }
- bool visit(TrueLiteral *ast) override
- {
- out(ast->trueToken);
- return true;
- }
- bool visit(FalseLiteral *ast) override
- {
- out(ast->falseToken);
- return true;
- }
- bool visit(IdentifierExpression *ast) override
- {
- out(ast->identifierToken);
- return true;
- }
- bool visit(StringLiteral *ast) override
- {
- // correctly handle multiline literals
- if (ast->literalToken.length == 0)
- return true;
- QStringView str = loc2Str(ast->literalToken);
- if (lw.indentNextlines && str.contains(QLatin1Char('\n'))) {
- out(str.mid(0, 1));
- lw.indentNextlines = false;
- out(str.mid(1));
- lw.indentNextlines = true;
- } else {
- out(str);
- }
- return true;
- }
- bool visit(NumericLiteral *ast) override
- {
- out(ast->literalToken);
- return true;
- }
- bool visit(RegExpLiteral *ast) override
- {
- out(ast->literalToken);
- return true;
- }
+bool ScriptFormatter::visit(PatternElementList *ast)
+{
+ for (PatternElementList *it = ast; it; it = it->next) {
+ const bool isObjectInitializer =
+ it->element && cast<ObjectPattern *>(it->element->initializer);
+ if (isObjectInitializer)
+ newLine();
- bool visit(ArrayPattern *ast) override
- {
- out(ast->lbracketToken);
- int baseIndent = lw.increaseIndent(1);
- if (ast->elements)
- accept(ast->elements);
- out(ast->commaToken);
- lw.decreaseIndent(1, baseIndent);
- out(ast->rbracketToken);
- return false;
+ if (it->elision)
+ accept(it->elision);
+ if (it->elision && it->element)
+ out(", ");
+ if (it->element)
+ accept(it->element);
+ if (it->next) {
+ out(", ");
+ if (isObjectInitializer)
+ newLine();
+ }
}
+ return false;
+}
- bool visit(ObjectPattern *ast) override
- {
- out(ast->lbraceToken);
- ++expressionDepth;
- if (ast->properties) {
- lnAcceptIndented(ast->properties);
+bool ScriptFormatter::visit(PatternPropertyList *ast)
+{
+ for (PatternPropertyList *it = ast; it; it = it->next) {
+ accept(it->property);
+ if (it->next) {
+ out(",");
newLine();
}
- --expressionDepth;
- out(ast->rbraceToken);
- return false;
}
+ return false;
+}
- bool visit(PatternElementList *ast) override
- {
- for (PatternElementList *it = ast; it; it = it->next) {
- if (it->elision)
- accept(it->elision);
- if (it->elision && it->element)
- out(", ");
- if (it->element)
- accept(it->element);
- if (it->next)
- out(", ");
+// https://262.ecma-international.org/7.0/#prod-PropertyDefinition
+bool ScriptFormatter::visit(AST::PatternProperty *property)
+{
+ if (property->type == PatternElement::Getter || property->type == PatternElement::Setter
+ || property->type == PatternElement::Method) {
+ // note that MethodDefinitions and FunctionDeclarations have different syntax
+ // https://262.ecma-international.org/7.0/#prod-MethodDefinition
+ // https://262.ecma-international.org/7.0/#prod-FunctionDeclaration
+ // hence visit(FunctionDeclaration*) is not quite appropriate here
+ if (property->type == PatternProperty::Getter)
+ out("get ");
+ else if (property->type == PatternProperty::Setter)
+ out("set ");
+ FunctionExpression *f = AST::cast<FunctionExpression *>(property->initializer);
+ if (f->isGenerator) {
+ out("*");
}
- return false;
- }
-
- bool visit(PatternPropertyList *ast) override
- {
- for (PatternPropertyList *it = ast; it; it = it->next) {
- PatternProperty *assignment = AST::cast<PatternProperty *>(it->property);
- if (assignment) {
- preVisit(assignment);
- bool isStringLike = AST::cast<StringLiteralPropertyName *>(assignment->name)
- || cast<IdentifierPropertyName *>(assignment->name);
- if (isStringLike)
- out("\"");
- accept(assignment->name);
- if (isStringLike)
- out("\"");
- out(": "); // assignment->colonToken
- if (it->next)
- postOps[assignment->initializer].append([this] {
- out(","); // always invalid?
- });
- accept(assignment->initializer);
- if (it->next)
- newLine();
- postVisit(assignment);
- continue;
- }
- PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next);
- if (getterSetter->property) {
- switch (getterSetter->property->type) {
- case PatternElement::Getter:
- out("get");
- break;
- case PatternElement::Setter:
- out("set");
- break;
- default:
- break;
- }
-
- accept(getterSetter->property->name);
- out("(");
- // accept(getterSetter->formals); // TODO
- out(")");
- out(" {");
- // accept(getterSetter->functionBody); // TODO
- out(" }");
+ accept(property->name);
+ out(f->lparenToken);
+ accept(f->formals);
+ out(f->rparenToken);
+ out(f->lbraceToken);
+ const bool scoped = f->lbraceToken.isValid();
+ if (scoped)
+ ++expressionDepth;
+ if (f->body) {
+ if (f->body->next || scoped) {
+ lnAcceptIndented(f->body);
+ lw.newline();
+ } else {
+ auto baseIndent = lw.increaseIndent(1);
+ accept(f->body);
+ lw.decreaseIndent(1, baseIndent);
}
}
+ if (scoped)
+ --expressionDepth;
+ out(f->rbraceToken);
return false;
}
- bool visit(NestedExpression *ast) override
- {
- out(ast->lparenToken);
- int baseIndent = lw.increaseIndent(1);
- accept(ast->expression);
- lw.decreaseIndent(1, baseIndent);
- out(ast->rparenToken);
- return false;
+ // IdentifierReference[?Yield]
+ accept(property->name);
+ bool useInitializer = false;
+ const bool bindingIdentifierExist = !property->bindingIdentifier.isEmpty();
+ if (property->colonToken.isValid()) {
+ // PropertyName[?Yield] : AssignmentExpression[In, ?Yield]
+ out(": ");
+ useInitializer = true;
+ if (bindingIdentifierExist)
+ out(property->bindingIdentifier);
+ if (property->bindingTarget)
+ accept(property->bindingTarget);
}
- bool visit(IdentifierPropertyName *ast) override
- {
- out(ast->id.toString());
- return true;
- }
- bool visit(StringLiteralPropertyName *ast) override
- {
- out(ast->id.toString());
- return true;
- }
- bool visit(NumericLiteralPropertyName *ast) override
- {
- out(QString::number(ast->id));
- return true;
+ if (property->initializer) {
+ // CoverInitializedName[?Yield]
+ if (bindingIdentifierExist) {
+ out(" = ");
+ useInitializer = true;
+ }
+ if (useInitializer)
+ accept(property->initializer);
}
+ return false;
+}
- bool visit(TemplateLiteral *ast) override
- {
- // correctly handle multiline literals
- if (ast->literalToken.length != 0) {
- QStringView str = loc2Str(ast->literalToken);
- if (lw.indentNextlines && str.contains(QLatin1Char('\n'))) {
- out(str.mid(0, 1));
- lw.indentNextlines = false;
- out(str.mid(1));
- lw.indentNextlines = true;
- } else {
- out(str);
- }
+bool ScriptFormatter::visit(NestedExpression *ast)
+{
+ out(ast->lparenToken);
+ int baseIndent = lw.increaseIndent(1);
+ accept(ast->expression);
+ lw.decreaseIndent(1, baseIndent);
+ out(ast->rparenToken);
+ return false;
+}
+
+bool ScriptFormatter::visit(IdentifierPropertyName *ast)
+{
+ out(ast->id.toString());
+ return true;
+}
+bool ScriptFormatter::visit(StringLiteralPropertyName *ast)
+{
+ out(ast->propertyNameToken);
+ return true;
+}
+bool ScriptFormatter::visit(NumericLiteralPropertyName *ast)
+{
+ out(QString::number(ast->id));
+ return true;
+}
+
+bool ScriptFormatter::visit(TemplateLiteral *ast)
+{
+ // correctly handle multiline literals
+ if (ast->literalToken.length != 0) {
+ QStringView str = loc2Str(ast->literalToken);
+ if (lw.indentNextlines && str.contains(QLatin1Char('\n'))) {
+ out(str.mid(0, 1));
+ lw.indentNextlines = false;
+ out(str.mid(1));
+ lw.indentNextlines = true;
+ } else {
+ out(str);
}
- accept(ast->expression);
- return true;
}
+ accept(ast->expression);
+ return true;
+}
- bool visit(ArrayMemberExpression *ast) override
- {
- accept(ast->base);
- out(ast->lbracketToken);
- int indent = lw.increaseIndent(1);
- accept(ast->expression);
- lw.decreaseIndent(1, indent);
- out(ast->rbracketToken);
- return false;
- }
+bool ScriptFormatter::visit(ArrayMemberExpression *ast)
+{
+ accept(ast->base);
+ out(ast->lbracketToken);
+ int indent = lw.increaseIndent(1);
+ accept(ast->expression);
+ lw.decreaseIndent(1, indent);
+ out(ast->rbracketToken);
+ return false;
+}
- bool visit(FieldMemberExpression *ast) override
- {
- accept(ast->base);
- out(ast->dotToken);
- out(ast->identifierToken);
- return false;
- }
+bool ScriptFormatter::visit(FieldMemberExpression *ast)
+{
+ accept(ast->base);
+ out(ast->dotToken);
+ out(ast->identifierToken);
+ return false;
+}
- bool visit(NewMemberExpression *ast) override
- {
- out("new "); // ast->newToken
- accept(ast->base);
- out(ast->lparenToken);
- accept(ast->arguments);
- out(ast->rparenToken);
- return false;
- }
+bool ScriptFormatter::visit(NewMemberExpression *ast)
+{
+ out("new "); // ast->newToken
+ accept(ast->base);
+ out(ast->lparenToken);
+ accept(ast->arguments);
+ out(ast->rparenToken);
+ return false;
+}
- bool visit(NewExpression *ast) override
- {
- out("new "); // ast->newToken
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(NewExpression *ast)
+{
+ out("new "); // ast->newToken
+ accept(ast->expression);
+ return false;
+}
- bool visit(CallExpression *ast) override
- {
- accept(ast->base);
- out(ast->lparenToken);
- int baseIndent = lw.increaseIndent(1);
- accept(ast->arguments);
- lw.decreaseIndent(1, baseIndent);
- out(ast->rparenToken);
- return false;
- }
+bool ScriptFormatter::visit(CallExpression *ast)
+{
+ accept(ast->base);
+ out(ast->lparenToken);
+ accept(ast->arguments);
+ out(ast->rparenToken);
+ return false;
+}
- bool visit(PostIncrementExpression *ast) override
- {
- accept(ast->base);
- out(ast->incrementToken);
- return false;
- }
+bool ScriptFormatter::visit(PostIncrementExpression *ast)
+{
+ accept(ast->base);
+ out(ast->incrementToken);
+ return false;
+}
- bool visit(PostDecrementExpression *ast) override
- {
- accept(ast->base);
- out(ast->decrementToken);
- return false;
- }
+bool ScriptFormatter::visit(PostDecrementExpression *ast)
+{
+ accept(ast->base);
+ out(ast->decrementToken);
+ return false;
+}
- bool visit(PreIncrementExpression *ast) override
- {
- out(ast->incrementToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(PreIncrementExpression *ast)
+{
+ out(ast->incrementToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(PreDecrementExpression *ast) override
- {
- out(ast->decrementToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(PreDecrementExpression *ast)
+{
+ out(ast->decrementToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(DeleteExpression *ast) override
- {
- out("delete "); // ast->deleteToken
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(DeleteExpression *ast)
+{
+ out("delete "); // ast->deleteToken
+ accept(ast->expression);
+ return false;
+}
- bool visit(VoidExpression *ast) override
- {
- out("void "); // ast->voidToken
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(VoidExpression *ast)
+{
+ out("void "); // ast->voidToken
+ accept(ast->expression);
+ return false;
+}
- bool visit(TypeOfExpression *ast) override
- {
- out("typeof "); // ast->typeofToken
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(TypeOfExpression *ast)
+{
+ out("typeof "); // ast->typeofToken
+ accept(ast->expression);
+ return false;
+}
- bool visit(UnaryPlusExpression *ast) override
- {
- out(ast->plusToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(UnaryPlusExpression *ast)
+{
+ out(ast->plusToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(UnaryMinusExpression *ast) override
- {
- out(ast->minusToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(UnaryMinusExpression *ast)
+{
+ out(ast->minusToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(TildeExpression *ast) override
- {
- out(ast->tildeToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(TildeExpression *ast)
+{
+ out(ast->tildeToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(NotExpression *ast) override
- {
- out(ast->notToken);
- accept(ast->expression);
- return false;
- }
+bool ScriptFormatter::visit(NotExpression *ast)
+{
+ out(ast->notToken);
+ accept(ast->expression);
+ return false;
+}
- bool visit(BinaryExpression *ast) override
- {
- accept(ast->left);
- out(" ");
- out(ast->operatorToken);
- out(" ");
- accept(ast->right);
- return false;
- }
+bool ScriptFormatter::visit(BinaryExpression *ast)
+{
+ accept(ast->left);
+ out(" ");
+ out(ast->operatorToken);
+ out(" ");
+ accept(ast->right);
+ return false;
+}
- bool visit(ConditionalExpression *ast) override
- {
- accept(ast->expression);
- out(" ? "); // ast->questionToken
- accept(ast->ok);
- out(" : "); // ast->colonToken
- accept(ast->ko);
- return false;
- }
+bool ScriptFormatter::visit(ConditionalExpression *ast)
+{
+ accept(ast->expression);
+ out(" ? "); // ast->questionToken
+ accept(ast->ok);
+ out(" : "); // ast->colonToken
+ accept(ast->ko);
+ return false;
+}
- bool visit(Block *ast) override
- {
- out(ast->lbraceToken);
+bool ScriptFormatter::visit(Block *ast)
+{
+ out(ast->lbraceToken);
+ if (ast->statements) {
++expressionDepth;
lnAcceptIndented(ast->statements);
newLine();
--expressionDepth;
- out(ast->rbraceToken);
- return false;
}
+ out(ast->rbraceToken);
+ return false;
+}
- bool visit(VariableStatement *ast) override
- {
- out(ast->declarationKindToken);
- out(" ");
- accept(ast->declarations);
- if (addSemicolons())
- out(";");
- return false;
+bool ScriptFormatter::visit(VariableStatement *ast)
+{
+ out(ast->declarationKindToken);
+ out(" ");
+ accept(ast->declarations);
+ if (addSemicolons())
+ out(";");
+ return false;
+}
+
+bool ScriptFormatter::visit(PatternElement *ast)
+{
+ switch (ast->type) {
+ case PatternElement::Literal:
+ case PatternElement::Method:
+ case PatternElement::Binding:
+ break;
+ case PatternElement::Getter:
+ out("get ");
+ break;
+ case PatternElement::Setter:
+ out("set ");
+ break;
+ case PatternElement::SpreadElement:
+ out("...");
+ break;
+ }
+
+ accept(ast->bindingTarget);
+ if (!ast->destructuringPattern())
+ out(ast->identifierToken);
+ if (ast->initializer) {
+ if (ast->isVariableDeclaration() || ast->type == AST::PatternElement::Binding)
+ out(" = ");
+ accept(ast->initializer);
}
+ return false;
+}
+bool ScriptFormatter::visit(EmptyStatement *ast)
+{
+ out(ast->semicolonToken);
+ return false;
+}
- void outputScope(VariableScope scope) {
- switch (scope) {
- case VariableScope::Const:
- out("const ");
- break;
- case VariableScope::Let:
- out("let ");
- break;
- case VariableScope::Var:
- out("var ");
- break;
- default:
- break;
+bool ScriptFormatter::visit(IfStatement *ast)
+{
+ out(ast->ifToken);
+ out(" ");
+ out(ast->lparenToken);
+ preVisit(ast->expression);
+ ast->expression->accept0(this);
+ out(ast->rparenToken);
+ postVisit(ast->expression);
+ acceptBlockOrIndented(ast->ok, ast->ko);
+ if (ast->ko) {
+ out(ast->elseToken);
+ if (cast<Block *>(ast->ko) || cast<IfStatement *>(ast->ko)) {
+ out(" ");
+ accept(ast->ko);
+ } else {
+ lnAcceptIndented(ast->ko);
}
}
+ return false;
+}
- bool visit(PatternElement *ast) override
- {
- if (ast->isForDeclaration) {
- outputScope(ast->scope);
- }
- accept(ast->bindingTarget);
- switch (ast->type) {
- case PatternElement::Literal:
- case PatternElement::Method:
- case PatternElement::Binding:
- break;
- case PatternElement::Getter:
- out("get ");
- break;
- case PatternElement::Setter:
- out("set ");
- break;
- case PatternElement::SpreadElement:
- out("...");
- break;
+bool ScriptFormatter::visit(DoWhileStatement *ast)
+{
+ out(ast->doToken);
+ acceptBlockOrIndented(ast->statement, true);
+ out(ast->whileToken);
+ out(" ");
+ out(ast->lparenToken);
+ accept(ast->expression);
+ out(ast->rparenToken);
+ return false;
+}
+
+bool ScriptFormatter::visit(WhileStatement *ast)
+{
+ out(ast->whileToken);
+ out(" ");
+ out(ast->lparenToken);
+ accept(ast->expression);
+ out(ast->rparenToken);
+ acceptBlockOrIndented(ast->statement);
+ return false;
+}
+
+bool ScriptFormatter::visit(ForStatement *ast)
+{
+ out(ast->forToken);
+ out(" ");
+ out(ast->lparenToken);
+ if (ast->initialiser) {
+ accept(ast->initialiser);
+ } else if (ast->declarations) {
+ if (auto pe = ast->declarations->declaration) {
+ out(pe->declarationKindToken);
+ out(" ");
}
- out(ast->identifierToken);
- if (ast->initializer) {
- if (ast->isVariableDeclaration())
- out(" = ");
- accept(ast->initializer);
+ for (VariableDeclarationList *it = ast->declarations; it; it = it->next) {
+ accept(it->declaration);
}
- return false;
}
+ out("; "); // ast->firstSemicolonToken
+ accept(ast->condition);
+ out("; "); // ast->secondSemicolonToken
+ accept(ast->expression);
+ out(ast->rparenToken);
+ acceptBlockOrIndented(ast->statement);
+ return false;
+}
- bool visit(EmptyStatement *ast) override
- {
- out(ast->semicolonToken);
- return false;
+bool ScriptFormatter::visit(ForEachStatement *ast)
+{
+ out(ast->forToken);
+ out(" ");
+ out(ast->lparenToken);
+ if (auto pe = AST::cast<PatternElement *>(ast->lhs)) {
+ out(pe->declarationKindToken);
+ out(" ");
}
+ accept(ast->lhs);
+ out(" ");
+ out(ast->inOfToken);
+ out(" ");
+ accept(ast->expression);
+ out(ast->rparenToken);
+ acceptBlockOrIndented(ast->statement);
+ return false;
+}
- bool visit(IfStatement *ast) override
- {
- out(ast->ifToken);
+bool ScriptFormatter::visit(ContinueStatement *ast)
+{
+ out(ast->continueToken);
+ if (!ast->label.isNull()) {
out(" ");
- out(ast->lparenToken);
- preVisit(ast->expression);
- ast->expression->accept0(this);
- out(ast->rparenToken);
- postVisit(ast->expression);
- acceptBlockOrIndented(ast->ok, ast->ko);
- if (ast->ko) {
- out(ast->elseToken);
- if (cast<Block *>(ast->ko) || cast<IfStatement *>(ast->ko)) {
- out(" ");
- accept(ast->ko);
- } else {
- lnAcceptIndented(ast->ko);
- }
- }
- return false;
+ out(ast->identifierToken);
}
+ if (addSemicolons())
+ out(";");
+ return false;
+}
- bool visit(DoWhileStatement *ast) override
- {
- out(ast->doToken);
- acceptBlockOrIndented(ast->statement, true);
- out(ast->whileToken);
+bool ScriptFormatter::visit(BreakStatement *ast)
+{
+ out(ast->breakToken);
+ if (!ast->label.isNull()) {
out(" ");
- out(ast->lparenToken);
- accept(ast->expression);
- out(ast->rparenToken);
- return false;
+ out(ast->identifierToken);
}
+ if (addSemicolons())
+ out(";");
+ return false;
+}
- bool visit(WhileStatement *ast) override
- {
- out(ast->whileToken);
- out(" ");
- out(ast->lparenToken);
+bool ScriptFormatter::visit(ReturnStatement *ast)
+{
+ out(ast->returnToken);
+ if (ast->expression) {
+ if (ast->returnToken.length != 0)
+ out(" ");
accept(ast->expression);
- out(ast->rparenToken);
- acceptBlockOrIndented(ast->statement);
- return false;
}
+ if (ast->returnToken.length > 0 && addSemicolons())
+ out(";");
+ return false;
+}
- bool visit(ForStatement *ast) override
- {
- out(ast->forToken);
+bool ScriptFormatter::visit(ThrowStatement *ast)
+{
+ out(ast->throwToken);
+ if (ast->expression) {
out(" ");
- out(ast->lparenToken);
- if (ast->initialiser) {
- accept(ast->initialiser);
- } else if (ast->declarations) {
- outputScope(ast->declarations->declaration->scope);
- accept(ast->declarations);
- }
- out("; "); // ast->firstSemicolonToken
- accept(ast->condition);
- out("; "); // ast->secondSemicolonToken
accept(ast->expression);
- out(ast->rparenToken);
- acceptBlockOrIndented(ast->statement);
- return false;
}
+ if (addSemicolons())
+ out(";");
+ return false;
+}
- bool visit(ForEachStatement *ast) override
- {
- out(ast->forToken);
- out(" ");
- out(ast->lparenToken);
- accept(ast->lhs);
+bool ScriptFormatter::visit(WithStatement *ast)
+{
+ out(ast->withToken);
+ out(" ");
+ out(ast->lparenToken);
+ accept(ast->expression);
+ out(ast->rparenToken);
+ acceptBlockOrIndented(ast->statement);
+ return false;
+}
+
+bool ScriptFormatter::visit(SwitchStatement *ast)
+{
+ out(ast->switchToken);
+ out(" ");
+ out(ast->lparenToken);
+ accept(ast->expression);
+ out(ast->rparenToken);
+ out(" ");
+ accept(ast->block);
+ return false;
+}
+
+bool ScriptFormatter::visit(CaseBlock *ast)
+{
+ out(ast->lbraceToken);
+ ++expressionDepth;
+ newLine();
+ accept(ast->clauses);
+ if (ast->clauses && ast->defaultClause)
+ newLine();
+ accept(ast->defaultClause);
+ if (ast->moreClauses)
+ newLine();
+ accept(ast->moreClauses);
+ newLine();
+ --expressionDepth;
+ out(ast->rbraceToken);
+ return false;
+}
+
+bool ScriptFormatter::visit(CaseClause *ast)
+{
+ out("case "); // ast->caseToken
+ accept(ast->expression);
+ out(ast->colonToken);
+ if (ast->statements)
+ lnAcceptIndented(ast->statements);
+ return false;
+}
+
+bool ScriptFormatter::visit(DefaultClause *ast)
+{
+ out(ast->defaultToken);
+ out(ast->colonToken);
+ lnAcceptIndented(ast->statements);
+ return false;
+}
+
+bool ScriptFormatter::visit(LabelledStatement *ast)
+{
+ out(ast->identifierToken);
+ out(": "); // ast->colonToken
+ accept(ast->statement);
+ return false;
+}
+
+bool ScriptFormatter::visit(TryStatement *ast)
+{
+ out("try "); // ast->tryToken
+ accept(ast->statement);
+ if (ast->catchExpression) {
out(" ");
- out(ast->inOfToken);
+ accept(ast->catchExpression);
+ }
+ if (ast->finallyExpression) {
out(" ");
- accept(ast->expression);
- out(ast->rparenToken);
- acceptBlockOrIndented(ast->statement);
- return false;
+ accept(ast->finallyExpression);
}
+ return false;
+}
- bool visit(ContinueStatement *ast) override
- {
- out(ast->continueToken);
- if (!ast->label.isNull()) {
- out(" ");
+bool ScriptFormatter::visit(Catch *ast)
+{
+ out(ast->catchToken);
+ out(" ");
+ out(ast->lparenToken);
+ out(ast->identifierToken);
+ out(") "); // ast->rparenToken
+ accept(ast->statement);
+ return false;
+}
+
+bool ScriptFormatter::visit(Finally *ast)
+{
+ out("finally "); // ast->finallyToken
+ accept(ast->statement);
+ return false;
+}
+
+bool ScriptFormatter::visit(FunctionDeclaration *ast)
+{
+ return ScriptFormatter::visit(static_cast<FunctionExpression *>(ast));
+}
+
+bool ScriptFormatter::visit(FunctionExpression *ast)
+{
+ if (!ast->isArrowFunction) {
+ if (ast->isGenerator) {
+ out("function* ");
+ } else {
+ out("function ");
+ }
+ if (!ast->name.isNull())
out(ast->identifierToken);
+ }
+ out(ast->lparenToken);
+ const bool needParentheses = ast->formals
+ && (ast->formals->next
+ || (ast->formals->element && ast->formals->element->bindingTarget));
+ if (ast->isArrowFunction && needParentheses)
+ out("(");
+ int baseIndent = lw.increaseIndent(1);
+ accept(ast->formals);
+ lw.decreaseIndent(1, baseIndent);
+ if (ast->isArrowFunction && needParentheses)
+ out(")");
+ out(ast->rparenToken);
+ if (ast->isArrowFunction && !ast->formals)
+ out("()");
+ out(" ");
+ if (ast->isArrowFunction)
+ out("=> ");
+ out(ast->lbraceToken);
+ if (ast->lbraceToken.length != 0)
+ ++expressionDepth;
+ if (ast->body) {
+ if (ast->body->next || ast->lbraceToken.length != 0) {
+ lnAcceptIndented(ast->body);
+ newLine();
+ } else {
+ // print a single statement in one line. E.g. x => x * 2
+ baseIndent = lw.increaseIndent(1);
+ accept(ast->body);
+ lw.decreaseIndent(1, baseIndent);
}
- if (addSemicolons())
- out(";");
- return false;
}
+ if (ast->lbraceToken.length != 0)
+ --expressionDepth;
+ out(ast->rbraceToken);
+ return false;
+}
- bool visit(BreakStatement *ast) override
- {
- out(ast->breakToken);
- if (!ast->label.isNull()) {
- out(" ");
- out(ast->identifierToken);
- }
- if (addSemicolons())
- out(";");
- return false;
+bool ScriptFormatter::visit(Elision *ast)
+{
+ for (Elision *it = ast; it; it = it->next) {
+ if (it->next)
+ out(", "); // ast->commaToken
}
+ return false;
+}
- bool visit(ReturnStatement *ast) override
- {
- out(ast->returnToken);
- if (ast->expression) {
- if (ast->returnToken.length != 0)
- out(" ");
- accept(ast->expression);
+bool ScriptFormatter::visit(ArgumentList *ast)
+{
+ for (ArgumentList *it = ast; it; it = it->next) {
+ if (it->isSpreadElement)
+ out("...");
+ accept(it->expression);
+ if (it->next) {
+ out(", "); // it->commaToken
}
- if (ast->returnToken.length > 0 && addSemicolons())
- out(";");
- return false;
}
+ return false;
+}
- bool visit(ThrowStatement *ast) override
- {
- out(ast->throwToken);
- if (ast->expression) {
- out(" ");
- accept(ast->expression);
+bool ScriptFormatter::visit(StatementList *ast)
+{
+ ++expressionDepth;
+ for (StatementList *it = ast; it; it = it->next) {
+ // ### work around parser bug: skip empty statements with wrong tokens
+ if (EmptyStatement *emptyStatement = cast<EmptyStatement *>(it->statement)) {
+ if (loc2Str(emptyStatement->semicolonToken) != QLatin1String(";"))
+ continue;
}
- if (addSemicolons())
- out(";");
- return false;
- }
- bool visit(WithStatement *ast) override
- {
- out(ast->withToken);
- out(" ");
- out(ast->lparenToken);
- accept(ast->expression);
- out(ast->rparenToken);
- acceptBlockOrIndented(ast->statement);
- return false;
+ accept(it->statement);
+ if (it->next) {
+ // There might be a post-comment attached to the current
+ // statement or a pre-comment attached to the next
+ // statmente or both.
+ // If any of those are present they will take care of
+ // handling the spacing between the statements so we
+ // don't need to push any newline.
+ auto *commentForCurrentStatement = comments->commentForNode(it->statement);
+ auto *commentForNextStatement = comments->commentForNode(it->next->statement);
+
+ if (
+ (commentForCurrentStatement && !commentForCurrentStatement->postComments().empty())
+ || (commentForNextStatement && !commentForNextStatement->preComments().empty())
+ ) continue;
+
+ quint32 lineDelta = it->next->firstSourceLocation().startLine
+ - it->statement->lastSourceLocation().startLine;
+ lineDelta = std::clamp(lineDelta, quint32{ 1 }, quint32{ 2 });
+
+ newLine(lineDelta);
+ }
}
+ --expressionDepth;
+ return false;
+}
- bool visit(SwitchStatement *ast) override
- {
- out(ast->switchToken);
- out(" ");
- out(ast->lparenToken);
- accept(ast->expression);
- out(ast->rparenToken);
- out(" ");
- accept(ast->block);
- return false;
+bool ScriptFormatter::visit(VariableDeclarationList *ast)
+{
+ for (VariableDeclarationList *it = ast; it; it = it->next) {
+ accept(it->declaration);
+ if (it->next)
+ out(", "); // it->commaToken
}
+ return false;
+}
- bool visit(CaseBlock *ast) override
- {
- out(ast->lbraceToken);
- ++expressionDepth;
- newLine();
- accept(ast->clauses);
- if (ast->clauses && ast->defaultClause)
- newLine();
- accept(ast->defaultClause);
- if (ast->moreClauses)
+bool ScriptFormatter::visit(CaseClauses *ast)
+{
+ for (CaseClauses *it = ast; it; it = it->next) {
+ accept(it->clause);
+ if (it->next)
newLine();
- accept(ast->moreClauses);
- newLine();
- --expressionDepth;
- out(ast->rbraceToken);
- return false;
}
+ return false;
+}
- bool visit(CaseClause *ast) override
- {
- out("case "); // ast->caseToken
- accept(ast->expression);
- out(ast->colonToken);
- if (ast->statements)
- lnAcceptIndented(ast->statements);
- return false;
- }
+bool ScriptFormatter::visit(FormalParameterList *ast)
+{
+ for (FormalParameterList *it = ast; it; it = it->next) {
+ // compare FormalParameterList::finish
+ if (auto id = it->element->bindingIdentifier.toString(); !id.isEmpty())
+ out(id);
+ if (it->element->bindingTarget)
+ accept(it->element->bindingTarget);
+ if (it->next)
+ out(", ");
+ }
+ return false;
+}
- bool visit(DefaultClause *ast) override
- {
- out(ast->defaultToken);
- out(ast->colonToken);
- lnAcceptIndented(ast->statements);
- return false;
- }
+// to check
+bool ScriptFormatter::visit(SuperLiteral *)
+{
+ out("super");
+ return true;
+}
+bool ScriptFormatter::visit(ComputedPropertyName *)
+{
+ out("[");
+ return true;
+}
+bool ScriptFormatter::visit(Expression *el)
+{
+ accept(el->left);
+ out(", ");
+ accept(el->right);
+ return false;
+}
+bool ScriptFormatter::visit(ExpressionStatement *el)
+{
+ if (addSemicolons())
+ postOps[el->expression].append([this]() { out(";"); });
+ return true;
+}
- bool visit(LabelledStatement *ast) override
- {
- out(ast->identifierToken);
- out(": "); // ast->colonToken
- accept(ast->statement);
- return false;
- }
+// Return false because we want to omit default function calls in accept0 implementation.
+bool ScriptFormatter::visit(ClassDeclaration *ast)
+{
+ preVisit(ast);
+ out(ast->classToken);
+ out(" ");
+ out(ast->name);
+ if (ast->heritage) {
+ out(" extends ");
+ accept(ast->heritage);
+ }
+ out(" {");
+ int baseIndent = lw.increaseIndent();
+ for (ClassElementList *it = ast->elements; it; it = it->next) {
+ lw.newline();
+ if (it->isStatic)
+ out("static ");
+ accept(it->property);
+ lw.newline();
+ }
+ lw.decreaseIndent(1, baseIndent);
+ out("}");
+ postVisit(ast);
+ return false;
+}
- bool visit(TryStatement *ast) override
- {
- out("try "); // ast->tryToken
- accept(ast->statement);
- if (ast->catchExpression) {
- out(" ");
- accept(ast->catchExpression);
- }
- if (ast->finallyExpression) {
- out(" ");
- accept(ast->finallyExpression);
- }
- return false;
+bool ScriptFormatter::visit(AST::ImportDeclaration *ast)
+{
+ out(ast->importToken);
+ lw.space();
+ if (!ast->moduleSpecifier.isNull()) {
+ out(ast->moduleSpecifierToken);
}
+ return true;
+}
- bool visit(Catch *ast) override
- {
- out(ast->catchToken);
- out(" ");
- out(ast->lparenToken);
+bool ScriptFormatter::visit(AST::ImportSpecifier *ast)
+{
+ if (!ast->identifier.isNull()) {
out(ast->identifierToken);
- out(") "); // ast->rparenToken
- accept(ast->statement);
- return false;
+ lw.space();
+ out("as");
+ lw.space();
}
+ out(ast->importedBindingToken);
+ return true;
+}
- bool visit(Finally *ast) override
- {
- out("finally "); // ast->finallyToken
- accept(ast->statement);
- return false;
- }
+bool ScriptFormatter::visit(AST::NameSpaceImport *ast)
+{
+ out(ast->starToken);
+ lw.space();
+ out("as");
+ lw.space();
+ out(ast->importedBindingToken);
+ return true;
+}
- bool visit(FunctionDeclaration *ast) override
- {
- return visit(static_cast<FunctionExpression *>(ast));
+bool ScriptFormatter::visit(AST::ImportsList *ast)
+{
+ for (ImportsList *it = ast; it; it = it->next) {
+ accept(it->importSpecifier);
+ if (it->next) {
+ out(",");
+ lw.space();
+ }
+ }
+ return false;
+}
+bool ScriptFormatter::visit(AST::NamedImports *ast)
+{
+ out(ast->leftBraceToken);
+ if (ast->importsList) {
+ lw.space();
}
+ return true;
+}
- bool visit(FunctionExpression *ast) override
- {
- if (!ast->isArrowFunction) {
- out("function "); // ast->functionToken
- if (!ast->name.isNull())
- out(ast->identifierToken);
- }
- out(ast->lparenToken);
- if (ast->isArrowFunction && ast->formals && ast->formals->next)
- out("(");
- int baseIndent = lw.increaseIndent(1);
- accept(ast->formals);
- lw.decreaseIndent(1, baseIndent);
- if (ast->isArrowFunction && ast->formals && ast->formals->next)
- out(")");
- out(ast->rparenToken);
- if (ast->isArrowFunction && !ast->formals)
- out("()");
- out(" ");
- if (ast->isArrowFunction)
- out("=> ");
- out(ast->lbraceToken);
- if (ast->lbraceToken.length != 0)
- ++expressionDepth;
- if (ast->body) {
- if (ast->body->next || ast->lbraceToken.length != 0) {
- lnAcceptIndented(ast->body);
- newLine();
- } else {
- // print a single statement in one line. E.g. x => x * 2
- baseIndent = lw.increaseIndent(1);
- accept(ast->body);
- lw.decreaseIndent(1, baseIndent);
- }
+bool ScriptFormatter::visit(AST::ImportClause *ast)
+{
+ if (!ast->importedDefaultBinding.isNull()) {
+ out(ast->importedDefaultBindingToken);
+ if (ast->nameSpaceImport || ast->namedImports) {
+ out(",");
+ lw.space();
}
- if (ast->lbraceToken.length != 0)
- --expressionDepth;
- out(ast->rbraceToken);
- return false;
}
+ return true;
+}
- bool visit(Elision *ast) override
- {
- for (Elision *it = ast; it; it = it->next) {
- if (it->next)
- out(", "); // ast->commaToken
- }
- return false;
+bool ScriptFormatter::visit(AST::ExportDeclaration *ast)
+{
+ out(ast->exportToken);
+ lw.space();
+ if (ast->exportDefault) {
+ out("default");
+ lw.space();
+ }
+ if (ast->exportsAll()) {
+ out("*");
}
+ return true;
+}
- bool visit(ArgumentList *ast) override
- {
- for (ArgumentList *it = ast; it; it = it->next) {
- if (it->isSpreadElement)
- out("...");
- accept(it->expression);
- if (it->next) {
- out(", "); // it->commaToken
- }
- }
- return false;
+bool ScriptFormatter::visit(AST::ExportClause *ast)
+{
+ out(ast->leftBraceToken);
+ if (ast->exportsList) {
+ lw.space();
}
+ return true;
+}
- bool visit(StatementList *ast) override
- {
- ++expressionDepth;
- for (StatementList *it = ast; it; it = it->next) {
- // ### work around parser bug: skip empty statements with wrong tokens
- if (EmptyStatement *emptyStatement = cast<EmptyStatement *>(it->statement)) {
- if (loc2Str(emptyStatement->semicolonToken) != QLatin1String(";"))
- continue;
- }
+bool ScriptFormatter::visit(AST::ExportSpecifier *ast)
+{
+ out(ast->identifier);
+ if (ast->exportedIdentifierToken.isValid()) {
+ lw.space();
+ out("as");
+ lw.space();
+ out(ast->exportedIdentifier);
+ }
+ return true;
+}
- accept(it->statement);
- if (it->next)
- newLine();
+bool ScriptFormatter::visit(AST::ExportsList *ast)
+{
+ for (ExportsList *it = ast; it; it = it->next) {
+ accept(it->exportSpecifier);
+ if (it->next) {
+ out(",");
+ lw.space();
}
- --expressionDepth;
- return false;
}
+ return false;
+}
- bool visit(VariableDeclarationList *ast) override
- {
- for (VariableDeclarationList *it = ast; it; it = it->next) {
- accept(it->declaration);
- if (it->next)
- out(", "); // it->commaToken
- }
- return false;
- }
+bool ScriptFormatter::visit(AST::FromClause *ast)
+{
+ lw.space();
+ out(ast->fromToken);
+ lw.space();
+ out(ast->moduleSpecifierToken);
+ return true;
+}
- bool visit(CaseClauses *ast) override
- {
- for (CaseClauses *it = ast; it; it = it->next) {
- accept(it->clause);
- if (it->next)
- newLine();
- }
- return false;
- }
+void ScriptFormatter::endVisit(ComputedPropertyName *)
+{
+ out("]");
+}
- bool visit(FormalParameterList *ast) override
- {
- for (FormalParameterList *it = ast; it; it = it->next) {
- out(it->element->bindingIdentifier.toString()); // TODO
- if (it->next)
- out(", ");
- }
- return false;
+void ScriptFormatter::endVisit(AST::ExportDeclaration *ast)
+{
+ // add a semicolon at the end of the following expressions
+ // export * FromClause ;
+ // export ExportClause FromClause ;
+ if (ast->fromClause) {
+ out(";");
}
- // to check
- bool visit(TypeExpression *) override { return true; }
- bool visit(SuperLiteral *) override
- {
- out("super");
- return true;
- }
- bool visit(PatternProperty *) override { return true; }
- bool visit(ComputedPropertyName *) override
- {
- out("[");
- return true;
- }
- bool visit(TaggedTemplate *) override { return true; }
- bool visit(Expression *el) override
- {
- accept(el->left);
- out(", ");
- accept(el->right);
- return false;
- }
- bool visit(ExpressionStatement *el) override
- {
- if (addSemicolons())
- postOps[el->expression].append([this]() { out(";"); });
- return true;
+ // add a semicolon at the end of the following expressions
+ // export ExportClause ;
+ if (ast->exportClause && !ast->fromClause) {
+ out(";");
}
- bool visit(YieldExpression *) override { return true; }
- bool visit(ClassExpression *) override { return true; }
-
- // Return false because we want to omit default function calls in accept0 implementation.
- bool visit(ClassDeclaration *ast) override
- {
- preVisit(ast);
- out(ast->classToken);
- out(" ");
- out(ast->name);
- if (ast->heritage) {
- out(" extends ");
- accept(ast->heritage);
+
+ // add a semicolon at the end of the following expressions
+ // export default [lookahead ∉ { function, class }] AssignmentExpression;
+ if (ast->exportDefault && ast->variableStatementOrDeclaration) {
+ // lookahead ∉ { function, class }
+ if (!(ast->variableStatementOrDeclaration->kind == Node::Kind_FunctionDeclaration
+ || ast->variableStatementOrDeclaration->kind == Node::Kind_ClassDeclaration)) {
+ out(";");
}
- out(" {");
- int baseIndent = lw.increaseIndent();
- for (ClassElementList *it = ast->elements; it; it = it->next) {
- PatternProperty *property = it->property;
- lw.newline();
- preVisit(property);
- if (it->isStatic)
- out("static ");
- if (property->type == PatternProperty::Getter)
- out("get ");
- else if (property->type == PatternProperty::Setter)
- out("set ");
- FunctionExpression *f = AST::cast<FunctionExpression *>(property->initializer);
- const bool scoped = f->lbraceToken.length != 0;
- out(f->functionToken);
- out(f->lparenToken);
- accept(f->formals);
- out(f->rparenToken);
- out(f->lbraceToken);
- if (scoped)
- ++expressionDepth;
- if (f->body) {
- if (f->body->next || scoped) {
- lnAcceptIndented(f->body);
- lw.newline();
- } else {
- baseIndent = lw.increaseIndent(1);
- accept(f->body);
- lw.decreaseIndent(1, baseIndent);
- }
- }
- if (scoped)
- --expressionDepth;
- out(f->rbraceToken);
- lw.newline();
- postVisit(property);
+ // ArrowFunction in QQmlJS::AST is handled with the help of FunctionDeclaration
+ // and not as part of AssignmentExpression (as per ECMA
+ // https://262.ecma-international.org/7.0/#prod-AssignmentExpression)
+ if (ast->variableStatementOrDeclaration->kind == Node::Kind_FunctionDeclaration
+ && static_cast<AST::FunctionDeclaration *>(ast->variableStatementOrDeclaration)
+ ->isArrowFunction) {
+ out(";");
}
- lw.decreaseIndent(1, baseIndent);
- out("}");
- postVisit(ast);
- return false;
}
+}
+
+void ScriptFormatter::endVisit(AST::ExportClause *ast)
+{
+ if (ast->exportsList) {
+ lw.space();
+ }
+ out(ast->rightBraceToken);
+}
- bool visit(ClassElementList *) override { return true; }
- bool visit(Program *) override { return true; }
- bool visit(NameSpaceImport *) override { return true; }
- bool visit(ImportSpecifier *) override { return true; }
- bool visit(ImportsList *) override { return true; }
- bool visit(NamedImports *) override { return true; }
- bool visit(FromClause *) override { return true; }
- bool visit(ImportClause *) override { return true; }
- bool visit(ImportDeclaration *) override { return true; }
- bool visit(ExportSpecifier *) override { return true; }
- bool visit(ExportsList *) override { return true; }
- bool visit(ExportClause *) override { return true; }
- bool visit(ExportDeclaration *) override { return true; }
- bool visit(ESModule *) override { return true; }
- bool visit(DebuggerStatement *) override { return true; }
- bool visit(Type *) override { return true; }
- bool visit(TypeArgument *) override { return true; }
- bool visit(TypeAnnotation *) override { return true; }
-
- // overridden to use BasicVisitor (and ensure warnings about new added AST)
- void endVisit(UiProgram *) override { }
- void endVisit(UiImport *) override { }
- void endVisit(UiHeaderItemList *) override { }
- void endVisit(UiPragma *) override { }
- void endVisit(UiPublicMember *) override { }
- void endVisit(UiSourceElement *) override { }
- void endVisit(UiObjectDefinition *) override { }
- void endVisit(UiObjectInitializer *) override { }
- void endVisit(UiObjectBinding *) override { }
- void endVisit(UiScriptBinding *) override { }
- void endVisit(UiArrayBinding *) override { }
- void endVisit(UiParameterList *) override { }
- void endVisit(UiObjectMemberList *) override { }
- void endVisit(UiArrayMemberList *) override { }
- void endVisit(UiQualifiedId *) override { }
- void endVisit(UiEnumDeclaration *) override { }
- void endVisit(UiEnumMemberList *) override { }
- void endVisit(UiVersionSpecifier *) override { }
- void endVisit(UiInlineComponent *) override { }
- void endVisit(UiAnnotation *) override { }
- void endVisit(UiAnnotationList *) override { }
- void endVisit(UiRequired *) override { }
- void endVisit(TypeExpression *) override { }
- void endVisit(ThisExpression *) override { }
- void endVisit(IdentifierExpression *) override { }
- void endVisit(NullExpression *) override { }
- void endVisit(TrueLiteral *) override { }
- void endVisit(FalseLiteral *) override { }
- void endVisit(SuperLiteral *) override { }
- void endVisit(StringLiteral *) override { }
- void endVisit(TemplateLiteral *) override { }
- void endVisit(NumericLiteral *) override { }
- void endVisit(RegExpLiteral *) override { }
- void endVisit(ArrayPattern *) override { }
- void endVisit(ObjectPattern *) override { }
- void endVisit(PatternElementList *) override { }
- void endVisit(PatternPropertyList *) override { }
- void endVisit(PatternElement *) override { }
- void endVisit(PatternProperty *) override { }
- void endVisit(Elision *) override { }
- void endVisit(NestedExpression *) override { }
- void endVisit(IdentifierPropertyName *) override { }
- void endVisit(StringLiteralPropertyName *) override { }
- void endVisit(NumericLiteralPropertyName *) override { }
- void endVisit(ComputedPropertyName *) override { out("]"); }
- void endVisit(ArrayMemberExpression *) override { }
- void endVisit(FieldMemberExpression *) override { }
- void endVisit(TaggedTemplate *) override { }
- void endVisit(NewMemberExpression *) override { }
- void endVisit(NewExpression *) override { }
- void endVisit(CallExpression *) override { }
- void endVisit(ArgumentList *) override { }
- void endVisit(PostIncrementExpression *) override { }
- void endVisit(PostDecrementExpression *) override { }
- void endVisit(DeleteExpression *) override { }
- void endVisit(VoidExpression *) override { }
- void endVisit(TypeOfExpression *) override { }
- void endVisit(PreIncrementExpression *) override { }
- void endVisit(PreDecrementExpression *) override { }
- void endVisit(UnaryPlusExpression *) override { }
- void endVisit(UnaryMinusExpression *) override { }
- void endVisit(TildeExpression *) override { }
- void endVisit(NotExpression *) override { }
- void endVisit(BinaryExpression *) override { }
- void endVisit(ConditionalExpression *) override { }
- void endVisit(Expression *) override { }
- void endVisit(Block *) override { }
- void endVisit(StatementList *) override { }
- void endVisit(VariableStatement *) override { }
- void endVisit(VariableDeclarationList *) override { }
- void endVisit(EmptyStatement *) override { }
- void endVisit(ExpressionStatement *) override { }
- void endVisit(IfStatement *) override { }
- void endVisit(DoWhileStatement *) override { }
- void endVisit(WhileStatement *) override { }
- void endVisit(ForStatement *) override { }
- void endVisit(ForEachStatement *) override { }
- void endVisit(ContinueStatement *) override { }
- void endVisit(BreakStatement *) override { }
- void endVisit(ReturnStatement *) override { }
- void endVisit(YieldExpression *) override { }
- void endVisit(WithStatement *) override { }
- void endVisit(SwitchStatement *) override { }
- void endVisit(CaseBlock *) override { }
- void endVisit(CaseClauses *) override { }
- void endVisit(CaseClause *) override { }
- void endVisit(DefaultClause *) override { }
- void endVisit(LabelledStatement *) override { }
- void endVisit(ThrowStatement *) override { }
- void endVisit(TryStatement *) override { }
- void endVisit(Catch *) override { }
- void endVisit(Finally *) override { }
- void endVisit(FunctionDeclaration *) override { }
- void endVisit(FunctionExpression *) override { }
- void endVisit(FormalParameterList *) override { }
- void endVisit(ClassExpression *) override { }
- void endVisit(ClassDeclaration *) override { }
- void endVisit(ClassElementList *) override { }
- void endVisit(Program *) override { }
- void endVisit(NameSpaceImport *) override { }
- void endVisit(ImportSpecifier *) override { }
- void endVisit(ImportsList *) override { }
- void endVisit(NamedImports *) override { }
- void endVisit(FromClause *) override { }
- void endVisit(ImportClause *) override { }
- void endVisit(ImportDeclaration *) override { }
- void endVisit(ExportSpecifier *) override { }
- void endVisit(ExportsList *) override { }
- void endVisit(ExportClause *) override { }
- void endVisit(ExportDeclaration *) override { }
- void endVisit(ESModule *) override { }
- void endVisit(DebuggerStatement *) override { }
- void endVisit(Type *) override { }
- void endVisit(TypeArgument *) override { }
- void endVisit(TypeAnnotation *) override { }
-
- void throwRecursionDepthError() override
- {
- out("/* ERROR: Hit recursion limit visiting AST, rewrite failed */");
+void ScriptFormatter::endVisit(AST::NamedImports *ast)
+{
+ if (ast->importsList) {
+ lw.space();
}
-};
+ out(ast->rightBraceToken);
+}
+
+void ScriptFormatter::endVisit(AST::ImportDeclaration *)
+{
+ out(";");
+}
+
+void ScriptFormatter::throwRecursionDepthError()
+{
+ out("/* ERROR: Hit recursion limit ScriptFormatter::visiting AST, rewrite failed */");
+}
-void reformatAst(OutWriter &lw, std::shared_ptr<AstComments> comments,
- const std::function<QStringView(SourceLocation)> loc2Str, AST::Node *n)
+void reformatAst(OutWriter &lw, const std::shared_ptr<AstComments> &comments,
+ const std::function<QStringView(SourceLocation)> &loc2Str, AST::Node *n)
{
if (n) {
- Rewriter rewriter(lw, comments, loc2Str, n);
+ ScriptFormatter formatter(lw, comments, loc2Str, n);
}
}