aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qmldom
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@qt.io>2021-03-23 15:37:32 +0100
committerFawzi Mohamed <fawzi.mohamed@qt.io>2021-06-05 00:07:48 +0200
commitde3d65009adf3c7ce0be6da77ee74b0a2610c9c5 (patch)
treeb9c03fc2b5e2c7845c4b4070c403eae66e5df3ef /tests/auto/qmldom
parent6cf15ad4e359223bb19c997f0dd279f9aea842d7 (diff)
qmldom: writeOut, write reformatted Qml
Adding writeOut: support for reformatted Qml - linewriter: write line by line with caching, callbacks, SourceLoaction updating - outwriter: write to line writer, and keep track of updated file locations and reformatted ScriptExpressions - reformatter: reformat javascript Change-Id: I4bdc393fb2d9b5a3db944a850719c24ef8726d15 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qmldom')
-rw-r--r--tests/auto/qmldom/CMakeLists.txt1
-rw-r--r--tests/auto/qmldom/combined/CMakeLists.txt1
-rw-r--r--tests/auto/qmldom/combined/tst_dom_all.cpp5
-rw-r--r--tests/auto/qmldom/domdata/reformatter/MyComponent.qml5
-rw-r--r--tests/auto/qmldom/domdata/reformatter/commentedFile.qml31
-rw-r--r--tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml31
-rw-r--r--tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml31
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1.qml42
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml49
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file1Unindented.qml42
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file2.qml58
-rw-r--r--tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml66
-rw-r--r--tests/auto/qmldom/domdata/reformatter/inline.qml8
-rw-r--r--tests/auto/qmldom/domdata/reformatter/inlineReformatted.qml8
-rw-r--r--tests/auto/qmldom/domdata/reformatter/required.qml13
-rw-r--r--tests/auto/qmldom/domdata/reformatter/requiredReformatted.qml13
-rw-r--r--tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml13
-rw-r--r--tests/auto/qmldom/domdata/reformatter/spread.qml14
-rw-r--r--tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml17
-rw-r--r--tests/auto/qmldom/domdata/reformatter/template.qml22
-rw-r--r--tests/auto/qmldom/domdata/reformatter/templateReformatted.qml17
-rw-r--r--tests/auto/qmldom/reformatter/CMakeLists.txt27
-rw-r--r--tests/auto/qmldom/reformatter/tst_reformatter.cpp40
-rw-r--r--tests/auto/qmldom/reformatter/tst_reformatter.h253
24 files changed, 807 insertions, 0 deletions
diff --git a/tests/auto/qmldom/CMakeLists.txt b/tests/auto/qmldom/CMakeLists.txt
index ebdf993038..36386cf821 100644
--- a/tests/auto/qmldom/CMakeLists.txt
+++ b/tests/auto/qmldom/CMakeLists.txt
@@ -5,4 +5,5 @@ add_subdirectory(domitem)
add_subdirectory(path)
add_subdirectory(stringdumper)
add_subdirectory(merging)
+add_subdirectory(reformatter)
add_subdirectory(combined)
diff --git a/tests/auto/qmldom/combined/CMakeLists.txt b/tests/auto/qmldom/combined/CMakeLists.txt
index ed2d492cdc..1eb7d7c790 100644
--- a/tests/auto/qmldom/combined/CMakeLists.txt
+++ b/tests/auto/qmldom/combined/CMakeLists.txt
@@ -16,6 +16,7 @@ qt_internal_add_test(tst_dom_all
../path/tst_qmldompath.h
../domitem/tst_qmldomitem.h
../merging/tst_dommerging.h
+ ../reformatter/tst_reformatter.h
INCLUDE_DIRECTORIES
..
DEFINES
diff --git a/tests/auto/qmldom/combined/tst_dom_all.cpp b/tests/auto/qmldom/combined/tst_dom_all.cpp
index 91ec70db83..c89792e482 100644
--- a/tests/auto/qmldom/combined/tst_dom_all.cpp
+++ b/tests/auto/qmldom/combined/tst_dom_all.cpp
@@ -40,6 +40,7 @@
#include "domitem/tst_qmldomitem.h"
#include "merging/tst_dommerging.h"
#include "path/tst_qmldompath.h"
+#include "reformatter/tst_reformatter.h"
int main(int argc, char *argv[])
{
@@ -64,5 +65,9 @@ int main(int argc, char *argv[])
QQmlJS::Dom::TestDomMerging test;
status |= QTest::qExec(&test, argc, argv);
}
+ {
+ QQmlJS::Dom::TestReformatter test;
+ status |= QTest::qExec(&test, argc, argv);
+ }
return status;
}
diff --git a/tests/auto/qmldom/domdata/reformatter/MyComponent.qml b/tests/auto/qmldom/domdata/reformatter/MyComponent.qml
new file mode 100644
index 0000000000..e661503f12
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/MyComponent.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Rectangle {
+ text: "bla"
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFile.qml b/tests/auto/qmldom/domdata/reformatter/commentedFile.qml
new file mode 100644
index 0000000000..4db877dcd1
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/commentedFile.qml
@@ -0,0 +1,31 @@
+// pre comment
+import QtQuick 2.15
+
+// pre item comment
+/* multi
+line */ // comment after multi line
+Item {
+// binding comment
+a: {// header
+
+// before x()
+// before x()
+x() // after x
+// before y = 8 + z + zz
+
+// before y = 8 + z + zz
+y = 8 +
+// before z
+z + // after z
+// before zz
+zz - // after z + zz
+/*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c) // after (a * b * c)
+
+ a + b // comment
+
+// footer
+}
+// post binding comment
+}
+// footer file comment
+/* second comment */ /* third comment */
diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml
new file mode 100644
index 0000000000..4125cbed2e
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted.qml
@@ -0,0 +1,31 @@
+// pre comment
+import QtQuick 2.15
+
+// pre item comment
+/* multi
+line */ // comment after multi line
+Item {
+ // binding comment
+ a: {
+ // header
+
+ // before x()
+ // before x()
+ x(); // after x
+ // before y = 8 + z + zz
+
+ // before y = 8 + z + zz
+ y = 8 +
+ // before z
+ z + // after z
+ // before zz
+ zz - // after z + zz
+ /*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c)
+ a + b; // comment
+
+ // footer
+ }
+ // post binding comment
+}
+// footer file comment
+/* second comment */ /* third comment */
diff --git a/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml
new file mode 100644
index 0000000000..df090abd6c
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/commentedFileReformatted2.qml
@@ -0,0 +1,31 @@
+// pre comment
+import QtQuick 2.15
+
+// pre item comment
+/* multi
+line */ // comment after multi line
+Item {
+ // binding comment
+ a: {
+ // header
+
+ // before x()
+ // before x()
+ x(); // after x
+ // before y = 8 + z + zz
+
+ // before y = 8 + z + zz
+ y = 8 +
+ // before z
+ z + // after z
+ // before zz
+ zz - // after z + zz
+ /*before (a b)*/(/* before a */ a * /* after a */ b * /*after b*/ c); // after (a * b * c)
+ a + b; // comment
+
+ // footer
+ }
+ // post binding comment
+}
+// footer file comment
+/* second comment */ /* third comment */
diff --git a/tests/auto/qmldom/domdata/reformatter/file1.qml b/tests/auto/qmldom/domdata/reformatter/file1.qml
new file mode 100644
index 0000000000..9df78103f1
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/file1.qml
@@ -0,0 +1,42 @@
+pragma pippo
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Scroll")
+
+ Rectangle {
+ anchors.fill: parent
+
+ ListView {
+ width: parent.width
+ model: {
+ MySingleton.mySignal()
+ 20
+ }
+ delegate: ItemDelegate {
+ id: root
+ text: "Item " + (index + 1)
+ width: parent.width
+ Rectangle {
+ text: "bla"
+ }
+ MyComponent {
+ text: root.text
+ function f(v = 4){
+ let c = 0
+ return {
+ a: function(){ if (b == 0) c += 78*5*v; }()
+ }
+ }
+ property int a: {
+ return 45
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml b/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml
new file mode 100644
index 0000000000..244a10f3f6
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/file1Reformatted.qml
@@ -0,0 +1,49 @@
+pragma pippo
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ height: 480
+ title: qsTr("Scroll")
+ visible: true
+ width: 640
+
+ Rectangle {
+ anchors.fill: parent
+
+ ListView {
+ model: {
+ MySingleton.mySignal();
+ 20;
+ }
+ width: parent.width
+
+ delegate: ItemDelegate {
+ id: root
+ text: "Item " + (index + 1)
+ width: parent.width
+
+ Rectangle {
+ text: "bla"
+ }
+ MyComponent {
+ property int a: {
+ return 45;
+ }
+
+ text: root.text
+
+ function f(v = 4) {
+ let c = 0;
+ return {
+ "a": function () {
+ if (b == 0)
+ c += 78 * 5 * v;
+ }()
+ };
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml b/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml
new file mode 100644
index 0000000000..146bafee00
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/file1Unindented.qml
@@ -0,0 +1,42 @@
+pragma pippo
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+visible: true
+width: 640
+height: 480
+title: qsTr("Scroll")
+
+Rectangle {
+anchors.fill: parent
+
+ListView {
+width: parent.width
+model: {
+MySingleton.mySignal()
+20
+}
+delegate: ItemDelegate {
+id: root
+text: "Item " + (index + 1)
+width: parent.width
+Rectangle {
+text: "bla"
+}
+MyComponent {
+text: root.text
+function f(v = 4){
+let c = 0
+return {
+a: function(){ if (b == 0) c += 78*5*v; }()
+}
+}
+property int a: {
+return 45
+}
+}
+}
+}
+}
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/file2.qml b/tests/auto/qmldom/domdata/reformatter/file2.qml
new file mode 100644
index 0000000000..5aeebc14e6
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/file2.qml
@@ -0,0 +1,58 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Scroll")
+
+ onTrigger: console.log("trigger signal emitted")
+
+ onSend: {
+ console.log("send signal emitted with notice: " + notice)
+ }
+
+ Rectangle {
+ anchors.fill: parent
+
+ ListView {
+ width: parent.width
+ model: {
+ MySingleton.mySignal()
+ 20
+ }
+ delegate: ItemDelegate {
+ id: root
+ text: "Item " + (index + 1)
+ width: parent.width
+ Rectangle {
+ text: "bla"
+ }
+ MyComponent {
+ text: root.text
+ function f(v){
+ let c = 0
+ return {
+ a: function(){ if (b == 0) c += 78*5*v; }()
+ }
+ }
+ property int a: {
+ let x = isNaN;
+ (45)
+ x ? 5 + 1 : 8
+ }
+ property list<Item> b: [ Item{
+ width: 5
+ },
+ Item{
+ width: 6
+ }]
+ }
+ }
+ }
+ }
+ Component.onCompleted: {
+ console.log("loaded")
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml b/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml
new file mode 100644
index 0000000000..30ad8f0618
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/file2Reformatted.qml
@@ -0,0 +1,66 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ height: 480
+ title: qsTr("Scroll")
+ visible: true
+ width: 640
+
+ Component.onCompleted: {
+ console.log("loaded");
+ }
+ onSend: {
+ console.log("send signal emitted with notice: " + notice);
+ }
+ onTrigger: console.log("trigger signal emitted")
+
+ Rectangle {
+ anchors.fill: parent
+
+ ListView {
+ model: {
+ MySingleton.mySignal();
+ 20;
+ }
+ width: parent.width
+
+ delegate: ItemDelegate {
+ id: root
+ text: "Item " + (index + 1)
+ width: parent.width
+
+ Rectangle {
+ text: "bla"
+ }
+ MyComponent {
+ property int a: {
+ let x = isNaN;
+ (45);
+ x ? 5 + 1 : 8;
+ }
+ property list<Item> b: [
+ Item {
+ width: 5
+ },
+ Item {
+ width: 6
+ }
+ ]
+
+ text: root.text
+
+ function f(v) {
+ let c = 0;
+ return {
+ "a": function () {
+ if (b == 0)
+ c += 78 * 5 * v;
+ }()
+ };
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/inline.qml b/tests/auto/qmldom/domdata/reformatter/inline.qml
new file mode 100644
index 0000000000..3429e9a2af
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/inline.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+component CustomText: Text {
+color: "red"
+text: "Test Text"
+}
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/inlineReformatted.qml b/tests/auto/qmldom/domdata/reformatter/inlineReformatted.qml
new file mode 100644
index 0000000000..749da25332
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/inlineReformatted.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ component CustomText: Text {
+ color: "red"
+ text: "Test Text"
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/required.qml b/tests/auto/qmldom/domdata/reformatter/required.qml
new file mode 100644
index 0000000000..29103114bd
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/required.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.15
+
+Item {
+ id: theFoo
+
+ required property Item theItem
+ required data
+
+ function foo() {
+ theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:",
+ {"foo": theFoo})
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/requiredReformatted.qml b/tests/auto/qmldom/domdata/reformatter/requiredReformatted.qml
new file mode 100644
index 0000000000..8d199d9ad7
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/requiredReformatted.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.15
+
+Item {
+ id: theFoo
+ required data
+ required property Item theItem
+
+ function foo() {
+ theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:", {
+ "foo": theFoo
+ });
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml
new file mode 100644
index 0000000000..44685765da
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.15
+
+Item {
+ id: theFoo
+ required data
+ required property Item theItem
+
+ function foo() {
+ theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:", {
+ "foo": theFoo
+ });
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/spread.qml b/tests/auto/qmldom/domdata/reformatter/spread.qml
new file mode 100644
index 0000000000..04fba62f9d
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/spread.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.15
+
+Item {
+ function myFunction() {}
+ function foo() {
+ iterableObj = [1,2]
+ obj = {a:42}
+ myFunction(...iterableObj); // pass all elements of iterableObj as arguments to function myFunction
+ let arr = [...iterableObj, '4', 'five', 6]; // combine two arrays by inserting all elements from iterableObj
+ //let objClone = { ...obj }; // pass all key:value pairs from an object (ES2018)
+ myFunction(-1, ...args, 2, ...[3]);
+ console.log(Math.max(...[1, 2, 3, 4]))
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml b/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml
new file mode 100644
index 0000000000..795a28257a
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/spreadReformatted.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.15
+
+Item {
+ function foo() {
+ iterableObj = [1, 2];
+ obj = {
+ "a": 42
+ };
+ myFunction(...iterableObj); // pass all elements of iterableObj as arguments to function myFunction
+ let arr = [...iterableObj, '4', 'five', 6]; // combine two arrays by inserting all elements from iterableObj
+ //let objClone = { ...obj }; // pass all key:value pairs from an object (ES2018)
+ myFunction(-1, ...args, 2, ...[3]);
+ console.log(Math.max(...[1, 2, 3, 4]));
+ }
+ function myFunction() {
+ }
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/template.qml b/tests/auto/qmldom/domdata/reformatter/template.qml
new file mode 100644
index 0000000000..886922838b
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/template.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.15
+
+Text {
+ property int i: 3
+ text: "´"+
+ "m
+ l
+
+ "+
+ 'b'+'
+ multi
+ l
+ l'+
+ `template` +
+ `t${i+6}`+
+ `t${i+`nested${i}`}`+
+ `t${function(){return 5}()}`+
+ `t\${i}
+ ${i +
+ 2}`
+ width: 300
+}
diff --git a/tests/auto/qmldom/domdata/reformatter/templateReformatted.qml b/tests/auto/qmldom/domdata/reformatter/templateReformatted.qml
new file mode 100644
index 0000000000..bfc8d28db1
--- /dev/null
+++ b/tests/auto/qmldom/domdata/reformatter/templateReformatted.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.15
+
+Text {
+ property int i: 3
+
+ text: "´" + "m
+ l
+
+ " + 'b' + '
+ multi
+ l
+ l' + `template` + `t${i + 6}` + `t${i + `nested${i}`}` + `t${function () {
+ return 5;
+ }()}` + `t\${i}
+ ${i + 2}`
+ width: 300
+}
diff --git a/tests/auto/qmldom/reformatter/CMakeLists.txt b/tests/auto/qmldom/reformatter/CMakeLists.txt
new file mode 100644
index 0000000000..4e6f1d1a06
--- /dev/null
+++ b/tests/auto/qmldom/reformatter/CMakeLists.txt
@@ -0,0 +1,27 @@
+#####################################################################
+## tst_reformatter:
+#####################################################################
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
+ domdata/reformatter/*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_reformatter
+ SOURCES
+ tst_reformatter.cpp tst_reformatter.h
+ DEFINES
+ QT_DEPRECATED_WARNINGS
+ QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../domdata\\\"
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::QmlDevToolsPrivate
+ Qt::QmlDomPrivate
+ Qt::Test
+ TESTDATA ${test_data}
+)
+
+qt_internal_extend_target(tst_reformatter CONDITION ANDROID OR IOS
+ DEFINES
+ QT_REFORMATTERTEST_DATADIR=\\\":/domdata\\\"
+)
diff --git a/tests/auto/qmldom/reformatter/tst_reformatter.cpp b/tests/auto/qmldom/reformatter/tst_reformatter.cpp
new file mode 100644
index 0000000000..848f6d525f
--- /dev/null
+++ b/tests/auto/qmldom/reformatter/tst_reformatter.cpp
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#include "tst_reformatter.h"
+
+QTEST_MAIN(QQmlJS::Dom::TestReformatter)
diff --git a/tests/auto/qmldom/reformatter/tst_reformatter.h b/tests/auto/qmldom/reformatter/tst_reformatter.h
new file mode 100644
index 0000000000..26593fcfe2
--- /dev/null
+++ b/tests/auto/qmldom/reformatter/tst_reformatter.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**/
+#ifndef TST_QMLDOMCODEFORMATTER_H
+#define TST_QMLDOMCODEFORMATTER_H
+#include <QtQmlDom/private/qqmldomlinewriter_p.h>
+#include <QtQmlDom/private/qqmldomoutwriter_p.h>
+#include <QtQmlDom/private/qqmldomitem_p.h>
+#include <QtQmlDom/private/qqmldomtop_p.h>
+
+#include <QtTest/QtTest>
+#include <QCborValue>
+#include <QDebug>
+#include <QLibraryInfo>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+namespace QQmlJS {
+namespace Dom {
+
+class TestReformatter : public QObject
+{
+ Q_OBJECT
+public:
+private slots:
+
+ void manualReformatter_data()
+ {
+ LineWriterOptions noReorderOptions;
+ QTest::addColumn<QString>("inFile");
+ QTest::addColumn<QString>("outFile");
+ QTest::addColumn<LineWriterOptions>("options");
+ LineWriterOptions defaultOptions;
+
+ noReorderOptions.attributesSequence = LineWriterOptions::AttributesSequence::Preserve;
+
+ QTest::newRow("file1") << QStringLiteral(u"file1.qml")
+ << QStringLiteral(u"file1Reformatted.qml") << defaultOptions;
+
+ QTest::newRow("file2") << QStringLiteral(u"file2.qml")
+ << QStringLiteral(u"file2Reformatted.qml") << defaultOptions;
+
+ QTest::newRow("commentedFile")
+ << QStringLiteral(u"commentedFile.qml")
+ << QStringLiteral(u"commentedFileReformatted2.qml") << defaultOptions;
+
+ QTest::newRow("required") << QStringLiteral(u"required.qml")
+ << QStringLiteral(u"requiredReformatted2.qml") << defaultOptions;
+
+ QTest::newRow("inline") << QStringLiteral(u"inline.qml")
+ << QStringLiteral(u"inlineReformatted.qml") << defaultOptions;
+
+ QTest::newRow("spread") << QStringLiteral(u"spread.qml")
+ << QStringLiteral(u"spreadReformatted.qml") << defaultOptions;
+
+ QTest::newRow("template") << QStringLiteral(u"template.qml")
+ << QStringLiteral(u"templateReformatted.qml") << defaultOptions;
+
+ QTest::newRow("file1NoReorder")
+ << QStringLiteral(u"file1.qml") << QStringLiteral(u"file1Reformatted2.qml")
+ << noReorderOptions;
+ }
+
+ void manualReformatter()
+ {
+ QFETCH(QString, inFile);
+ QFETCH(QString, outFile);
+ QFETCH(LineWriterOptions, options);
+
+ QString baseDir = QLatin1String(QT_QMLTEST_DATADIR) + QLatin1String("/reformatter");
+ QStringList qmltypeDirs =
+ QStringList({ baseDir, QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath) });
+ DomItem env = DomEnvironment::create(
+ qmltypeDirs,
+ QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
+ | QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
+ QString testFilePath = baseDir + QLatin1Char('/') + inFile;
+ DomItem tFile;
+ env.loadBuiltins();
+ env.loadFile(
+ testFilePath, QString(),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
+ LoadOption::DefaultLoad);
+ env.loadPendingDependencies();
+
+ MutableDomItem myFile = tFile.field(Fields::currentItem);
+
+ QString resultStr;
+ QTextStream res(&resultStr);
+ LineWriter lw([&res](QStringView s) { res << s; }, QLatin1String("*testStream*"), options);
+ OutWriter ow(lw);
+ ow.indentNextlines = true;
+ DomItem qmlFile = tFile.field(Fields::currentItem);
+ qmlFile.writeOut(ow);
+ lw.eof();
+ res.flush();
+ QString fullRes = resultStr;
+ res.seek(0);
+ QFile fOut(baseDir + QLatin1Char('/') + outFile);
+ if (!fOut.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "could not open file" << outFile;
+ return;
+ }
+ QTextStream out(&fOut);
+ QString line = out.readLine();
+ QString resLine = res.readLine();
+ int iLine = 0;
+ auto writeReformatted = [fullRes]() {
+ qDebug().noquote().nospace() << "Reformatted output:\n"
+ << "-----------------\n"
+ << fullRes << "-----------------\n";
+ };
+ while (!line.isNull() && !resLine.isNull()) {
+ ++iLine;
+ if (resLine != line)
+ writeReformatted();
+ QCOMPARE(resLine, line);
+ line = out.readLine();
+ resLine = res.readLine();
+ }
+ if (resLine.isNull() != line.isNull()) {
+ writeReformatted();
+ qDebug() << "reformatted at end" << resLine.isNull() << resLine
+ << "reference at end:" << line.isNull() << line;
+ }
+ QCOMPARE(resLine.isNull(), line.isNull());
+ }
+
+ void indentInfo()
+ {
+ IndentInfo i1(u"\n\n ", 4);
+ QCOMPARE(i1.trailingString, u" ");
+ QCOMPARE(i1.nNewlines, 2);
+ QCOMPARE(i1.column, 2);
+ IndentInfo i2(u"\r\n\r\n ", 4);
+ QCOMPARE(i2.trailingString, u" ");
+ QCOMPARE(i2.nNewlines, 2);
+ QCOMPARE(i2.column, 2);
+ IndentInfo i3(u"\n ", 4);
+ QCOMPARE(i3.trailingString, u" ");
+ QCOMPARE(i3.nNewlines, 1);
+ QCOMPARE(i3.column, 1);
+ IndentInfo i4(u"\r\n ", 4);
+ QCOMPARE(i4.trailingString, u" ");
+ QCOMPARE(i4.nNewlines, 1);
+ QCOMPARE(i4.column, 1);
+ IndentInfo i5(u"\n", 4);
+ QCOMPARE(i5.trailingString, u"");
+ QCOMPARE(i5.nNewlines, 1);
+ QCOMPARE(i5.column, 0);
+ IndentInfo i6(u"\r\n", 4);
+ QCOMPARE(i6.trailingString, u"");
+ QCOMPARE(i6.nNewlines, 1);
+ QCOMPARE(i6.column, 0);
+ IndentInfo i7(u" ", 4);
+ QCOMPARE(i7.trailingString, u" ");
+ QCOMPARE(i7.nNewlines, 0);
+ QCOMPARE(i7.column, 2);
+ IndentInfo i8(u"", 4);
+ QCOMPARE(i8.trailingString, u"");
+ QCOMPARE(i8.nNewlines, 0);
+ QCOMPARE(i8.column, 0);
+ }
+
+ void lineWriter()
+ {
+ {
+ QString res;
+ LineWriterOptions opts;
+ opts.lineEndings = LineWriterOptions::LineEndings::Unix;
+ LineWriter lw([&res](QStringView v) { res.append(v); }, QLatin1String("*testStream*"),
+ opts);
+ lw.write(u"a\nb");
+ lw.write(u"c\r\nd");
+ lw.write(u"e\rf");
+ lw.write(u"g\r\n");
+ lw.write(u"h\r");
+ lw.write(u"\n");
+ QCOMPARE(res, u"a\nbc\nde\nfg\nh\n\n");
+ }
+ {
+ QString res;
+ LineWriterOptions opts;
+ opts.lineEndings = LineWriterOptions::LineEndings::Windows;
+ LineWriter lw([&res](QStringView v) { res.append(v); }, QLatin1String("*testStream*"),
+ opts);
+ lw.write(u"a\nb");
+ lw.write(u"c\r\nd");
+ lw.write(u"e\rf");
+ lw.write(u"g\r\n");
+ lw.write(u"h\r");
+ lw.write(u"\n");
+ QCOMPARE(res, u"a\r\nbc\r\nde\r\nfg\r\nh\r\n\r\n");
+ }
+ {
+ QString res;
+ LineWriterOptions opts;
+ opts.lineEndings = LineWriterOptions::LineEndings::OldMacOs;
+ LineWriter lw([&res](QStringView v) { res.append(v); }, QLatin1String("*testStream*"),
+ opts);
+ lw.write(u"a\nb");
+ lw.write(u"c\r\nd");
+ lw.write(u"e\rf");
+ lw.write(u"g\r\n");
+ lw.write(u"h\r");
+ lw.write(u"\n");
+ QCOMPARE(res, u"a\rbc\rde\rfg\rh\r\r");
+ }
+ }
+
+private:
+};
+
+} // namespace Dom
+} // namespace QQmlJS
+QT_END_NAMESPACE
+
+#endif // TST_QMLDOMSCANNER_H