aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmlformat
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2019-12-13 16:10:46 +0100
committerMaximilian Goldstein <max.goldstein@qt.io>2019-12-19 16:45:51 +0100
commit73189151b59430671630ae931ac42c0e18cdab55 (patch)
treee57692afa5cbc0d517f8d10bcdbb792f5e1f1066 /tests/auto/qml/qmlformat
parent08977003850d7da27a7db8058ff860fc64eb439a (diff)
qtdeclarative/tools: Implement qmlformat
qmlformat is a tool that formats qml files according to the QML coding conventions (https://doc.qt.io/qt-5/qml-codingconventions.html). Change-Id: I359c4bd3b51f60614535f0e857d7e0b21b1d9033 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tests/auto/qml/qmlformat')
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml151
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.qml151
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.qml105
-rw-r--r--tests/auto/qml/qmlformat/qmlformat.pro11
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp111
5 files changed, 529 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml
new file mode 100644
index 0000000000..be9c43648e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.nosort.qml
@@ -0,0 +1,151 @@
+/* This file is licensed under the not a license license
+ 1. You may not comply
+ 2. Goodbye
+*/
+
+// Importing this is very important
+import QtQuick 5.15
+// Muddling the waters!
+import QtQuick.Models 3.14 as muddle
+// Importing that is important too
+import Z
+import That
+import This // THIS IS VERY IMPORTANT!
+import Y
+import X.Z
+import X.Y
+import A.LLOHA
+import A.B.B.A
+
+// This comment is related to Item
+Item {
+ // Orphan comment
+ // Another orphan
+ // More orphans
+
+ // This to id
+ // Also id. (line 2)
+ // This is the third id
+ // fourth id comment
+ id: foo
+
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+ property bool some_bool: false
+ property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
+ property bool something_computed: function(x) {
+ // This is an orphan inside something_computed
+ // Are these getting duplicated?
+ // Another orphan inside something_computed
+
+ const PI = 3, DAYS_PER_YEAR = 365.25;
+ var x = 3 + 2;
+ x["bla"] = 50;
+ // This one to var few!
+ var few = new WhatEver();
+ x += Math.sin(3);
+ x--;
+ --x;
+ x++;
+ ++x;
+ for (var x = 0; x < 100; x++) {
+ x++;
+ console.log("Foo");
+ }
+ for (var x in [3, 2, 1]) {
+ y++;
+ console.log("Bar");
+ }
+ while (true)
+ console.log("Wee");
+
+ with (foo) {
+ bar;
+ x += 5;
+ } // This is related to with!
+ x3:
+ do {
+ console.log("Hello");
+ } while (3 == 0);
+ try {
+ dangerous();
+ } catch (e) {
+ console.log(e);
+ } finally {
+ dangerous();
+ }
+ switch (x) {
+ case 0:
+ x = 1;
+ break;
+ case 1:
+ x = 5;
+ break;
+ case 4:
+ x = 100;
+ break;
+ }
+ if (x == 50)
+ console.log("true");
+ else if (x == 50)
+ console.log("other thing");
+ else
+ console.log("false");
+
+ if (x == 50) {
+ console.log("true");
+ } else if (x == 50) {
+ console.log("other thing");
+ x--;
+ } else {
+ console.log("false");
+ }
+ return "foobar";
+ }()
+ default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool
+ // some_read_only_bool
+ readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0
+
+ signal say(string name, bool caps)
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ x: 3 // Very cool
+ Component.onCompleted: console.log("Foo!")
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {
+ },
+ // This is a cool rectangle
+ Rectangle {
+ }
+ ]
+ Text {
+ required property string batman
+
+ signal boo(int count, int times, real duration)
+
+ text: "Bla"
+ }
+
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo
+ x: 3
+ y: x + 3
+ }
+
+}
+
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
new file mode 100644
index 0000000000..7adcfb2f3e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
@@ -0,0 +1,151 @@
+/* This file is licensed under the not a license license
+ 1. You may not comply
+ 2. Goodbye
+*/
+
+import A.B.B.A
+import A.LLOHA
+// Importing this is very important
+import QtQuick 5.15
+// Muddling the waters!
+import QtQuick.Models 3.14 as muddle
+import That
+import This // THIS IS VERY IMPORTANT!
+import X.Y
+import X.Z
+import Y
+// Importing that is important too
+import Z
+
+// This comment is related to Item
+Item {
+ // Orphan comment
+ // Another orphan
+ // More orphans
+
+ // This to id
+ // Also id. (line 2)
+ // This is the third id
+ // fourth id comment
+ id: foo
+
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+ property bool some_bool: false
+ property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
+ property bool something_computed: function(x) {
+ // This is an orphan inside something_computed
+ // Are these getting duplicated?
+ // Another orphan inside something_computed
+
+ const PI = 3, DAYS_PER_YEAR = 365.25;
+ var x = 3 + 2;
+ x["bla"] = 50;
+ // This one to var few!
+ var few = new WhatEver();
+ x += Math.sin(3);
+ x--;
+ --x;
+ x++;
+ ++x;
+ for (var x = 0; x < 100; x++) {
+ x++;
+ console.log("Foo");
+ }
+ for (var x in [3, 2, 1]) {
+ y++;
+ console.log("Bar");
+ }
+ while (true)
+ console.log("Wee");
+
+ with (foo) {
+ bar;
+ x += 5;
+ } // This is related to with!
+ x3:
+ do {
+ console.log("Hello");
+ } while (3 == 0);
+ try {
+ dangerous();
+ } catch (e) {
+ console.log(e);
+ } finally {
+ dangerous();
+ }
+ switch (x) {
+ case 0:
+ x = 1;
+ break;
+ case 1:
+ x = 5;
+ break;
+ case 4:
+ x = 100;
+ break;
+ }
+ if (x == 50)
+ console.log("true");
+ else if (x == 50)
+ console.log("other thing");
+ else
+ console.log("false");
+
+ if (x == 50) {
+ console.log("true");
+ } else if (x == 50) {
+ console.log("other thing");
+ x--;
+ } else {
+ console.log("false");
+ }
+ return "foobar";
+ }()
+ default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool
+ // some_read_only_bool
+ readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0
+
+ signal say(string name, bool caps)
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ x: 3 // Very cool
+ Component.onCompleted: console.log("Foo!")
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {
+ },
+ // This is a cool rectangle
+ Rectangle {
+ }
+ ]
+ Text {
+ required property string batman
+
+ signal boo(int count, int times, real duration)
+
+ text: "Bla"
+ }
+
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo
+ x: 3
+ y: x + 3
+ }
+
+}
+
diff --git a/tests/auto/qml/qmlformat/data/Example1.qml b/tests/auto/qml/qmlformat/data/Example1.qml
new file mode 100644
index 0000000000..0fb9053e3a
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/Example1.qml
@@ -0,0 +1,105 @@
+
+
+/* This file is licensed under the not a license license
+ 1. You may not comply
+ 2. Goodbye
+*/
+
+// Importing this is very important
+import QtQuick 5.15
+// Muddling the waters!
+import QtQuick.Models 3.14 as muddle
+// Importing that is important too
+import Z
+import That
+import This // THIS IS VERY IMPORTANT!
+import Y
+import X.Z
+import X.Y
+import A.LLOHA
+import A.B.B.A
+
+// This comment is related to Item
+Item {
+ x: 3 // Very cool
+
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+ // This one to aFunc()
+ function aFunc() {
+ var x = 3;
+ return x;
+ }
+
+ property bool some_bool : false
+ // This comment is related to the property animation
+ PropertyAnimation on x {
+ id: foo; x: 3; y: x + 3
+ }
+
+ // Orphan comment
+
+ // Another orphan
+
+ // More orphans
+
+
+ property variant some_array_literal: [30,20,Math["PI"],[4,3,2],"foo",0.3]
+ property bool something_computed: function(x) {
+ const PI = 3, DAYS_PER_YEAR=365.25; var x = 3 + 2; x["bla"] = 50;
+
+ // This is an orphan inside something_computed
+
+ // Are these getting duplicated?
+
+
+ // This one to var few!
+ var few = new WhatEver();
+ x += Math.sin(3); x--; --x; x++; ++x;
+ for (var x = 0; x < 100; x++) { x++; console.log("Foo"); }
+ for (var x in [3,2,1]) { y++; console.log("Bar"); }
+ while (true) { console.log("Wee"); }
+ with (foo) { bar; x+=5; } // This is related to with!
+ x3:
+ do { console.log("Hello"); } while (3 == 0)
+ try { dangerous(); } catch(e) { console.log(e); } finally { console.log("What else?"); }
+ switch (x) { case 0: x = 1; break; case 1: x = 5; break; case 4: x = 100; break; }
+ if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); } else { console.log("false"); }
+ if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); x--; } else { console.log("false"); }
+
+ // Another orphan inside something_computed
+
+ return "foobar"; }();
+
+ default property bool some_default_bool : 500 % 5 !== 0 // some_default_bool
+
+ myFavouriteThings: [
+ // This is an orphan
+
+ // This is a cool text
+ Text {},
+ // This is a cool rectangle
+ Rectangle {}]
+
+ // some_read_only_bool
+ readonly property bool some_read_only_bool : Math.sin(3) && (aFunc()[30] + 5) | 2 != 0
+
+ signal say(string name, bool caps);
+
+ Text { text: "Bla"; signal boo(int count, int times, real duration); required property string batman; }
+
+ Component.onCompleted: console.log("Foo!");
+
+ // This to id
+ // Also id. (line 2)
+ // This is the third id
+ // fourth id comment
+ id: foo
+
+}
diff --git a/tests/auto/qml/qmlformat/qmlformat.pro b/tests/auto/qml/qmlformat/qmlformat.pro
new file mode 100644
index 0000000000..9f8a44bc09
--- /dev/null
+++ b/tests/auto/qml/qmlformat/qmlformat.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+TARGET = tst_qmlformat
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qmlformat.cpp
+
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+QT += testlib
diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
new file mode 100644
index 0000000000..7ad9c99d83
--- /dev/null
+++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QProcess>
+#include <QString>
+
+#include <util.h>
+
+class TestQmlformat: public QQmlDataTest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase() override;
+
+ void testFormat();
+ void testFormatNoSort();
+
+private:
+ QString readTestFile(const QString &path);
+ QString runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed);
+
+ QString m_qmlformatPath;
+};
+
+void TestQmlformat::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ m_qmlformatPath = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/qmlformat");
+#ifdef Q_OS_WIN
+ m_qmlformatPath += QLatin1String(".exe");
+#endif
+ if (!QFileInfo(m_qmlformatPath).exists()) {
+ QString message = QStringLiteral("qmlformat executable not found (looked for %0)").arg(m_qmlformatPath);
+ QFAIL(qPrintable(message));
+ }
+}
+
+QString TestQmlformat::readTestFile(const QString &path)
+{
+ QFile file(testFile(path));
+
+ if (!file.open(QIODevice::ReadOnly))
+ return "";
+
+ return QString::fromUtf8(file.readAll());
+}
+
+void TestQmlformat::testFormat()
+{
+ QCOMPARE(runQmlformat("Example1.qml", true, true), readTestFile("Example1.formatted.qml"));
+}
+
+void TestQmlformat::testFormatNoSort()
+{
+ QCOMPARE(runQmlformat("Example1.qml", false, true), readTestFile("Example1.formatted.nosort.qml"));
+}
+
+QString TestQmlformat::runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed)
+{
+ QStringList args;
+ args << testFile(fileToFormat);
+
+ if (!sortImports)
+ args << "-n";
+
+ QString output;
+ auto verify = [&]() {
+ QProcess process;
+ process.start(m_qmlformatPath, args);
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ if (shouldSucceed)
+ QCOMPARE(process.exitCode(), 0);
+ else
+ QVERIFY(process.exitCode() != 0);
+ output = process.readAllStandardOutput();
+ };
+ verify();
+
+ return output;
+}
+
+QTEST_MAIN(TestQmlformat)
+#include "tst_qmlformat.moc"