aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2020-01-15 11:25:18 +0100
committerMaximilian Goldstein <max.goldstein@qt.io>2020-01-17 10:02:29 +0100
commit9e674be4fb8c369873a009f58e3152a12d2c4cce (patch)
tree034090e7ef4723bafb9983f10ba285fb84735273 /tools
parent47b187231ab1c45f8609bcbbf6f85f8a05bc9be7 (diff)
qmlformat: Fix some language features being unsupported
qmlformat now supports: - arrow functions - generator functions - this expressions - object patterns - regex literals - type expressions - plain expressions Aborts if an error occurs during dumping now. Also now automatically tests qmlformat against all example / test qml files. Change-Id: Idc24004c6f2c1cd65289bcad75985a1ef047c8d2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmlformat/dumpastvisitor.cpp98
-rw-r--r--tools/qmlformat/dumpastvisitor.h3
-rw-r--r--tools/qmlformat/main.cpp17
3 files changed, 103 insertions, 15 deletions
diff --git a/tools/qmlformat/dumpastvisitor.cpp b/tools/qmlformat/dumpastvisitor.cpp
index 716be0a9a7..20ebef8927 100644
--- a/tools/qmlformat/dumpastvisitor.cpp
+++ b/tools/qmlformat/dumpastvisitor.cpp
@@ -28,6 +28,8 @@
#include "dumpastvisitor.h"
+#include <QtQml/private/qqmljslexer_p.h>
+
DumpAstVisitor::DumpAstVisitor(Node *rootNode, CommentAstVisitor *comment): m_comment(comment)
{
// Add all completely orphaned comments
@@ -257,6 +259,22 @@ QString DumpAstVisitor::parseFormalParameterList(FormalParameterList *list)
return result;
}
+QString DumpAstVisitor::parsePatternProperty(PatternProperty *property)
+{
+ return escapeString(property->name->asString())+": "+parsePatternElement(property, false);
+}
+
+QString DumpAstVisitor::parsePatternPropertyList(PatternPropertyList *list)
+{
+ QString result = "";
+
+ for (auto *item = list; item != nullptr; item = item->next) {
+ result += formatLine(parsePatternProperty(item->property) + (item->next != nullptr ? "," : ""));
+ }
+
+ return result;
+}
+
QString DumpAstVisitor::parseExpression(ExpressionNode *expression)
{
if (expression == nullptr)
@@ -288,13 +306,23 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression)
auto *functExpr = cast<FunctionExpression *>(expression);
m_indentLevel++;
- QString result = "function";
+ QString result;
+
+ if (!functExpr->isArrowFunction) {
+ result += "function";
- if (!functExpr->name.isEmpty())
- result += " " + functExpr->name;
+ if (functExpr->isGenerator)
+ result += "*";
- result += "("+parseFormalParameterList(functExpr->formals)+") {\n"
- + parseStatementList(functExpr->body);
+ if (!functExpr->name.isEmpty())
+ result += " " + functExpr->name;
+
+ result += "("+parseFormalParameterList(functExpr->formals)+") {\n"
+ + parseStatementList(functExpr->body);
+ } else {
+ result += "("+parseFormalParameterList(functExpr->formals)+") => {\n";
+ result += parseStatementList(functExpr->body);
+ }
m_indentLevel--;
@@ -304,6 +332,8 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression)
}
case Node::Kind_NullExpression:
return "null";
+ case Node::Kind_ThisExpression:
+ return "this";
case Node::Kind_PostIncrementExpression:
return parseExpression(cast<PostIncrementExpression *>(expression)->base)+"++";
case Node::Kind_PreIncrementExpression:
@@ -371,6 +401,44 @@ QString DumpAstVisitor::parseExpression(ExpressionNode *expression)
return result;
}
+ case Node::Kind_ObjectPattern: {
+ auto *objectPattern = cast<ObjectPattern*>(expression);
+ QString result = "{\n";
+
+ m_indentLevel++;
+ result += parsePatternPropertyList(objectPattern->properties);
+ m_indentLevel--;
+
+ result += formatLine("}", false);
+
+ return result;
+ }
+ case Node::Kind_Expression: {
+ auto* expr = cast<Expression*>(expression);
+ return parseExpression(expr->left)+", "+parseExpression(expr->right);
+ }
+ case Node::Kind_Type: {
+ auto* type = reinterpret_cast<Type*>(expression);
+
+ return parseUiQualifiedId(type->typeId);
+ }
+ case Node::Kind_RegExpLiteral: {
+ auto* regexpLiteral = cast<RegExpLiteral*>(expression);
+ QString result = "/"+regexpLiteral->pattern+"/";
+
+ if (regexpLiteral->flags & QQmlJS::Lexer::RegExp_Unicode)
+ result += "u";
+ if (regexpLiteral->flags & QQmlJS::Lexer::RegExp_Global)
+ result += "g";
+ if (regexpLiteral->flags & QQmlJS::Lexer::RegExp_Multiline)
+ result += "m";
+ if (regexpLiteral->flags & QQmlJS::Lexer::RegExp_Sticky)
+ result += "y";
+ if (regexpLiteral->flags & QQmlJS::Lexer::RegExp_IgnoreCase)
+ result += "i";
+
+ return result;
+ }
default:
m_error = true;
return "unknown_expression_"+QString::number(expression->kind);
@@ -383,7 +451,7 @@ QString DumpAstVisitor::parseVariableDeclarationList(VariableDeclarationList *li
for (auto *item = list; item != nullptr; item = item->next) {
result += parsePatternElement(item->declaration, (item == list))
- + (item->next != nullptr ? ", " : "");
+ + (item->next != nullptr ? ", " : "");
}
return result;
@@ -469,7 +537,7 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext,
case Node::Kind_VariableStatement:
return parseVariableDeclarationList(cast<VariableStatement *>(statement)->declarations);
case Node::Kind_ReturnStatement:
- return "return "+parseExpression(cast<ReturnStatement *>(statement)->expression);
+ return "return "+parseExpression(cast<ReturnStatement *>(statement)->expression);
case Node::Kind_ContinueStatement:
return "continue";
case Node::Kind_BreakStatement:
@@ -705,7 +773,7 @@ bool DumpAstVisitor::visit(UiPublicMember *node) {
addLine("signal "+node->name.toString()+"("+parseUiParameterList(node->parameters) + ")"
+ commentBackInline);
- break;
+ break;
case UiPublicMember::Property: {
if (m_firstProperty) {
if (m_firstOfAll)
@@ -912,7 +980,15 @@ bool DumpAstVisitor::visit(FunctionDeclaration *node) {
addNewLine();
addLine(getComment(node, Comment::Location::Front));
- addLine("function "+node->name+"("+parseFormalParameterList(node->formals)+") {");
+
+ QString head = "function";
+
+ if (node->isGenerator)
+ head += "*";
+
+ head += " "+node->name+"("+parseFormalParameterList(node->formals)+") {";
+
+ addLine(head);
m_indentLevel++;
m_result += parseStatementList(node->body);
m_indentLevel--;
@@ -970,8 +1046,8 @@ bool DumpAstVisitor::visit(UiImport *node) {
result += parseUiQualifiedId(node->importUri);
if (node->version) {
- result += " " + QString::number(node->version->majorVersion) + "."
- + QString::number(node->version->minorVersion);
+ result += " " + QString::number(node->version->majorVersion) + "."
+ + QString::number(node->version->minorVersion);
}
if (node->asToken.isValid()) {
diff --git a/tools/qmlformat/dumpastvisitor.h b/tools/qmlformat/dumpastvisitor.h
index e73a7b628f..2001f4366e 100644
--- a/tools/qmlformat/dumpastvisitor.h
+++ b/tools/qmlformat/dumpastvisitor.h
@@ -89,6 +89,9 @@ private:
QString parsePatternElement(PatternElement *element, bool scope = true);
QString parsePatternElementList(PatternElementList *element);
+ QString parsePatternProperty(PatternProperty *property);
+ QString parsePatternPropertyList(PatternPropertyList *list);
+
QString parseArgumentList(ArgumentList *list);
QString parseUiParameterList(UiParameterList *list);
diff --git a/tools/qmlformat/main.cpp b/tools/qmlformat/main.cpp
index bca788d316..036fbe9748 100644
--- a/tools/qmlformat/main.cpp
+++ b/tools/qmlformat/main.cpp
@@ -43,7 +43,7 @@
#include "dumpastvisitor.h"
#include "restructureastvisitor.h"
-bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImports)
+bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImports, bool force)
{
QFile file(filename);
@@ -101,8 +101,14 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp
DumpAstVisitor dump(parser.rootNode(), &comment);
- if (dump.error())
- qWarning().noquote() << "An error has occurred. The output may not be reliable.";
+ if (dump.error()) {
+ if (force) {
+ qWarning().noquote() << "An error has occurred. The output may not be reliable.";
+ } else {
+ qWarning().noquote() << "Am error has occurred. Aborting.";
+ return false;
+ }
+ }
if (inplace) {
if (verbose)
@@ -145,6 +151,9 @@ int main(int argc, char *argv[])
parser.addOption(QCommandLineOption({"i", "inplace"},
QStringLiteral("Edit file in-place instead of outputting to stdout.")));
+ parser.addOption(QCommandLineOption({"f", "force"},
+ QStringLiteral("Continue even if an error has occurred.")));
+
parser.addPositionalArgument("filenames", "files to be processed by qmlformat");
parser.process(app);
@@ -155,7 +164,7 @@ int main(int argc, char *argv[])
parser.showHelp(-1);
for (const QString& file: parser.positionalArguments()) {
- if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"), !parser.isSet("no-sort")))
+ if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"), !parser.isSet("no-sort"), parser.isSet("force")))
success = false;
}
#endif