diff options
Diffstat (limited to 'tests/auto/qml/qmlformat')
101 files changed, 2193 insertions, 375 deletions
diff --git a/tests/auto/qml/qmlformat/CMakeLists.txt b/tests/auto/qml/qmlformat/CMakeLists.txt index 01f4fa2837..76923d66de 100644 --- a/tests/auto/qml/qmlformat/CMakeLists.txt +++ b/tests/auto/qml/qmlformat/CMakeLists.txt @@ -1,9 +1,18 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # Generated from qmlformat.pro. ##################################################################### ## tst_qmlformat Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmlformat LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -12,26 +21,29 @@ list(APPEND test_data ${test_data_glob}) qt_internal_add_test(tst_qmlformat SOURCES - ../../shared/util.cpp ../../shared/util.h tst_qmlformat.cpp DEFINES - SRCDIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}\\\" - INCLUDE_DIRECTORIES - ../../shared - PUBLIC_LIBRARIES - Qt::Gui + SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" + LIBRARIES + Qt::Core + Qt::QmlDomPrivate + Qt::TestPrivate + Qt::QuickTestUtilsPrivate TESTDATA ${test_data} + TIMEOUT 3000 ) +add_dependencies(tst_qmlformat Qt::qmlformat) + ## Scopes: ##################################################################### qt_internal_extend_target(tst_qmlformat CONDITION ANDROID OR IOS DEFINES - QT_QMLTEST_DATADIR=\\\":/data\\\" + QT_QMLTEST_DATADIR=":/data" ) qt_internal_extend_target(tst_qmlformat CONDITION NOT ANDROID AND NOT IOS DEFINES - QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\" + QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data" ) diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml index ab56b5ce00..019b7f0141 100644 --- a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml +++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml @@ -1,32 +1,6 @@ #!/she-bang -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Charts module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL$ -** 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 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only //![2] import QtQuick 2.0 @@ -36,72 +10,93 @@ import QtCharts 2.0 @Pippo { atg1: 3 } -@Annotation2 { -} +@Annotation2 {} Item { - //![1] - + @Annotate {} + anchors.fill: parent @AnnotateMore { property int x: 5 } - @AnnotateALot { - } - + @AnnotateALot {} property variant othersSlice: 0 - @Annotate { - } - anchors.fill: parent - @SuperComplete { - binding: late - } - Component.onCompleted: { - // You can also manipulate slices dynamically, like append a slice or set a slice exploded - othersSlice = pieSeries.append("Others", 52); - pieSeries.find("Volkswagen").exploded = true; - } //![1] ChartView { id: chart - title: "Top-5 car brand shares in Finland" anchors.fill: parent legend.alignment: Qt.AlignBottom antialiasing: true - @ExtraAnnotation { - signal pippo() + signal pippo } PieSeries { + @IdAnnotation { + des: "pippo" + } id: pieSeries - + @Maximum { + nTied: 0 + } PieSlice { label: "Volkswagen" value: 13.5 } - PieSlice { label: "Toyota" value: 10.9 } - PieSlice { label: "Ford" value: 8.6 } - PieSlice { label: "Skoda" value: 8.2 } - PieSlice { label: "Volvo" value: 6.8 } - } - + @SignalAnnotation { + implicit: true + } + signal pippo2 // nice signal + @MethodAnnotation { + important: true + } + function foo(x) { + return 42; + } + @BindingAnn { + bType: 1 + } + val: 34 + @BindingAnn { + bType: 2 + } + val2: Item {} + @BindingAnn { + bType: 3 + } + val3: [ + Item {} + ] + @BindingAnn { + bType: 4 + } + Animation on val { + duration: 34 + } } - + @SuperComplete { + binding: late + } + Component.onCompleted: { + // You can also manipulate slices dynamically, like append a slice or set a slice exploded + othersSlice = pieSeries.append("Others", 52.0); + pieSeries.find("Volkswagen").exploded = true; + } + //![1] } diff --git a/tests/auto/qml/qmlformat/data/Annotations.qml b/tests/auto/qml/qmlformat/data/Annotations.qml index 4638d4f7e9..4b463048b4 100644 --- a/tests/auto/qml/qmlformat/data/Annotations.qml +++ b/tests/auto/qml/qmlformat/data/Annotations.qml @@ -1,32 +1,6 @@ #!/she-bang -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Charts module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL$ -** 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 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only //![2] import QtQuick 2.0 @@ -56,13 +30,31 @@ Item { signal pippo } PieSeries { + @IdAnnotation{ des: "pippo"} id: pieSeries + @Maximum { nTied: 0 } PieSlice { label: "Volkswagen"; value: 13.5 } PieSlice { label: "Toyota"; value: 10.9 } PieSlice { label: "Ford"; value: 8.6 } PieSlice { label: "Skoda"; value: 8.2 } PieSlice { label: "Volvo"; value: 6.8 } } + @SignalAnnotation{ implicit: true } + signal pippo2 // nice signal + @MethodAnnotation{ important: true } + function foo(x){ + return 42; + } + @BindingAnn{ bType: 1 } + val: 34 + @BindingAnn{ bType: 2 } + val2: Item{ } + @BindingAnn{ bType: 3 } + val3: [ Item{} ] + @BindingAnn{ bType: 4 } + Animation on val { + duration: 34 + } } @SuperComplete{ diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml index 5e27aeec22..b1662e8898 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml @@ -19,34 +19,52 @@ 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 + 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 + D // This is D + } + + // This one to aFunc() + function aFunc() { + var x = 3; + return x; } 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 + // This comment is related to the property animation + PropertyAnimation on x { + id: foo2 + 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); @@ -62,23 +80,22 @@ Item { y++; console.log("Bar"); } - while (true) + while (true) { console.log("Wee"); - + } with (foo) { bar; x += 5; } // This is related to with! - x3: - do { + x3: do { console.log("Hello"); - } while (3 == 0); + } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { - dangerous(); + console.log("What else?"); } switch (x) { case 0: @@ -91,12 +108,13 @@ Item { x = 100; break; } - if (x == 50) + if (x == 50) { console.log("true"); - else if (x == 50) + } else if (x == 50) { console.log("other thing"); - else + } else { console.log("false"); + } if (x == 50) { console.log("true"); } else if (x == 50) { @@ -105,47 +123,33 @@ Item { } else { console.log("false"); } + + // Another orphan inside something_computed + 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; - } + default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool - x: 3 // Very cool - Component.onCompleted: console.log("Foo!") myFavouriteThings: [ // This is an orphan // This is a cool text - Text { - }, + Text {}, // This is a cool rectangle - Rectangle { - } + Rectangle {} ] - Text { - required property string batman + // some_read_only_bool + readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 - signal boo(int count, int times, real duration) + signal say(string name, bool caps) + Text { text: "Bla" + signal boo(int count, int times, real duration) + required property string batman } - // This comment is related to the property animation - PropertyAnimation on x { - id: foo - - x: 3 - y: x + 3 - } - + Component.onCompleted: console.log("Foo!") } diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml index fdc0b1f68c..c4aef78924 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml @@ -19,34 +19,52 @@ 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 + 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 + D // This is D + } + + // This one to aFunc() + function aFunc() { + var x = 3; + return x; } 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 + // This comment is related to the property animation + PropertyAnimation on x { + id: foo2 + 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); @@ -62,23 +80,22 @@ Item { y++; console.log("Bar"); } - while (true) + while (true) { console.log("Wee"); - + } with (foo) { bar; x += 5; } // This is related to with! - x3: - do { + x3: do { console.log("Hello"); - } while (3 == 0); + } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { - dangerous(); + console.log("What else?"); } switch (x) { case 0: @@ -91,12 +108,13 @@ Item { x = 100; break; } - if (x == 50) + if (x == 50) { console.log("true"); - else if (x == 50) + } else if (x == 50) { console.log("other thing"); - else + } else { console.log("false"); + } if (x == 50) { console.log("true"); } else if (x == 50) { @@ -105,47 +123,33 @@ Item { } else { console.log("false"); } + + // Another orphan inside something_computed + 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; - } + default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool - x: 3 // Very cool - Component.onCompleted: console.log("Foo!") myFavouriteThings: [ // This is an orphan // This is a cool text - Text { - }, + Text {}, // This is a cool rectangle - Rectangle { - } + Rectangle {} ] - Text { - required property string batman + // some_read_only_bool + readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 - signal boo(int count, int times, real duration) + signal say(string name, bool caps) + Text { text: "Bla" + signal boo(int count, int times, real duration) + required property string batman } - // This comment is related to the property animation - PropertyAnimation on x { - id: foo - - x: 3 - y: x + 3 - } - + Component.onCompleted: console.log("Foo!") } diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml index d1c17c4c6b..7cea50213a 100644 --- a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml +++ b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml @@ -19,34 +19,52 @@ 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 + 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 + D // This is D + } + + // This one to aFunc() + function aFunc() { + var x = 3; + return x; } 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 + // This comment is related to the property animation + PropertyAnimation on x { + id: foo2 + 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); @@ -62,23 +80,22 @@ Item { y++; console.log("Bar"); } - while (true) + while (true) { console.log("Wee"); - + } with (foo) { bar; x += 5; } // This is related to with! - x3: - do { + x3: do { console.log("Hello"); - } while (3 == 0); + } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { - dangerous(); + console.log("What else?"); } switch (x) { case 0: @@ -91,12 +108,13 @@ Item { x = 100; break; } - if (x == 50) + if (x == 50) { console.log("true"); - else if (x == 50) + } else if (x == 50) { console.log("other thing"); - else + } else { console.log("false"); + } if (x == 50) { console.log("true"); } else if (x == 50) { @@ -105,47 +123,33 @@ Item { } else { console.log("false"); } + + // Another orphan inside something_computed + 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; - } + default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool - x: 3 // Very cool - Component.onCompleted: console.log("Foo!") myFavouriteThings: [ // This is an orphan // This is a cool text - Text { - }, + Text {}, // This is a cool rectangle - Rectangle { - } + Rectangle {} ] - Text { - required property string batman + // some_read_only_bool + readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 - signal boo(int count, int times, real duration) + signal say(string name, bool caps) + Text { text: "Bla" + signal boo(int count, int times, real duration) + required property string batman } - // This comment is related to the property animation - PropertyAnimation on x { - id: foo - - x: 3 - y: x + 3 - } - + Component.onCompleted: console.log("Foo!") } diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml new file mode 100644 index 0000000000..7049686900 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml @@ -0,0 +1,155 @@ +/* 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 { + + // 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 + } + + // Orphan comment + + // Another orphan + + // More orphans + + property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] + property bool some_bool: false + 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 + 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"; + }() + + x: 3 // Very cool + + // This one to aFunc() + function aFunc() { + var x = 3; + return x; + } + signal say(string name, bool caps) + + Component.onCompleted: console.log("Foo!") + + Text { + required property string batman + + text: "Bla" + + signal boo(int count, int times, real duration) + } + + myFavouriteThings: [ + // This is an orphan + + // This is a cool text + Text {}, + // This is a cool rectangle + Rectangle {} + ] + // This comment is related to the property animation + PropertyAnimation on x { + id: foo2 + x: 3 + y: x + 3 + } +} diff --git a/tests/auto/qml/qmlformat/data/Example1.qml b/tests/auto/qml/qmlformat/data/Example1.qml index 0fb9053e3a..36ffc6b058 100644 --- a/tests/auto/qml/qmlformat/data/Example1.qml +++ b/tests/auto/qml/qmlformat/data/Example1.qml @@ -40,7 +40,7 @@ Item { property bool some_bool : false // This comment is related to the property animation PropertyAnimation on x { - id: foo; x: 3; y: x + 3 + id: foo2; x: 3; y: x + 3 } // Orphan comment diff --git a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml index 620fbf4120..95b4fcf4a3 100644 --- a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml +++ b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml @@ -1,3 +1,3 @@ // This comment should be directly above Item after formatting -Item { -} + +Item {} diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml index d89260df5d..0db1801d8a 100644 --- a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml +++ b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml @@ -1,4 +1,5 @@ #!/she-bang + Item { function test() { //// The following if blocks should NOT HAVE braces @@ -7,8 +8,9 @@ Item { console.log("foo"); // Single branch, no braces - if (true) + if (true) { console.log("foo"); + } // Multiple branches, No braces if (true) @@ -17,46 +19,49 @@ Item { console.log("bar"); else console.log("baz"); + // Multiple branches, all braces - if (true) + if (true) { console.log("foo"); - else if (false) + } else if (false) { console.log("bar"); - else + } else { console.log("baz"); + } + //// The following if blocks should HAVE braces // Single branch, braces if (true) { console.log("foo"); console.log("bar"); } + // Multiple branches, some braces if (true) { console.log("foo"); console.log("foo2"); - } else if (false) { + } else if (false) console.log("bar"); - } else { + else console.log("baz"); - } + // Multiple branches, some braces - if (true) { + if (true) console.log("foo"); - } else if (false) { + else if (false) { console.log("bar"); console.log("bar2"); - } else { + } else console.log("baz"); - } + // Multiple branches, some braces - if (true) { + if (true) console.log("foo"); - } else if (false) { + else if (false) console.log("bar"); - } else { + else { console.log("baz"); console.log("baz2"); } } - } diff --git a/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml b/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml index 53e278ab9c..5d8d7a5fb4 100644 --- a/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml +++ b/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml @@ -1,10 +1,12 @@ #!/she-bang // extra comment + Item { Component.onCompleted: { if (3 < 2) console.log("Foo"); - else + else { console.log("Bar"); + } } } diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml new file mode 100644 index 0000000000..8ae4dd7c88 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml @@ -0,0 +1,4 @@ +Item { + // should keep its comma + property var some_array_literal: [30, 20, 0.3,] +} diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.qml new file mode 100644 index 0000000000..1aec09515c --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrayEndComma.qml @@ -0,0 +1,8 @@ +Item { + // should keep its comma + property var some_array_literal: [ + 30, + 20, + 0.3, + ] +} diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml new file mode 100644 index 0000000000..ac4cf97881 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml @@ -0,0 +1,10 @@ +import QtQuick + +Item { + Component.onCompleted: { + let f = ([]) => {}; + let g = ([a]) => {}; + let h = ([a, b]) => {}; + let i = ([a, ...b]) => {}; + } +} diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml new file mode 100644 index 0000000000..2a47b2f152 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml @@ -0,0 +1,8 @@ +import QtQuick + +Item { Component.onCompleted: { let f = ([]) => {}; + let g = ([a]) => {}; + let h = ([a, b]) => {}; + let i = ([a, ...b]) => {}; + } +} diff --git a/tests/auto/qml/qmlformat/data/arrowFunctions.formatted.qml b/tests/auto/qml/qmlformat/data/arrowFunctions.formatted.qml index e4bc1f6747..142a6fe36a 100644 --- a/tests/auto/qml/qmlformat/data/arrowFunctions.formatted.qml +++ b/tests/auto/qml/qmlformat/data/arrowFunctions.formatted.qml @@ -1,5 +1,5 @@ Item { - arrow1: (x) => x - arrow2: (x) => x + x + arrow1: x => x + arrow2: x => x + x arrow3: () => x > 3 ? x * x : x } diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml new file mode 100644 index 0000000000..071e3bc69f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml @@ -0,0 +1,12 @@ +/* comment with spaces */ + +/* + another comment + */ +// + +// another comment /*test */ + +import QtQml + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml new file mode 100644 index 0000000000..c99415aeed --- /dev/null +++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml @@ -0,0 +1,15 @@ +/* comment with spaces */ + +/* + another comment + */ +// + + +// another comment /*test */ + + + +import QtQml + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/checkIdsNewline.formatted.qml b/tests/auto/qml/qmlformat/data/checkIdsNewline.formatted.qml new file mode 100644 index 0000000000..e95aa70567 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/checkIdsNewline.formatted.qml @@ -0,0 +1,23 @@ +Item { + id: test1 + + height: 360 + width: 360 + + Button { + } + Rectangle { + id: test2 + + color: "salmon" + height: 360 + width: 360 + + Item { + id: test3 + + height: 360 + width: 360 + } + } +} diff --git a/tests/auto/qml/qmlformat/data/checkIdsNewline.qml b/tests/auto/qml/qmlformat/data/checkIdsNewline.qml new file mode 100644 index 0000000000..94bdb3a8f3 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/checkIdsNewline.qml @@ -0,0 +1,22 @@ +Item { + id: test1 + + Button { + } + + height: 360 + width: 360 + + Rectangle { + color: "salmon" + height: 360 + width: 360 + id: test2 + + Item { + id: test3 + height: 360 + width: 360 + } + } +} diff --git a/tests/auto/qml/qmlformat/data/class.formatted.js b/tests/auto/qml/qmlformat/data/class.formatted.js new file mode 100644 index 0000000000..eeb1faf64e --- /dev/null +++ b/tests/auto/qml/qmlformat/data/class.formatted.js @@ -0,0 +1,5 @@ +class Person { + constructor(name) { + this._name = name; + } +} diff --git a/tests/auto/qml/qmlformat/data/class.js b/tests/auto/qml/qmlformat/data/class.js new file mode 100644 index 0000000000..116061d515 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/class.js @@ -0,0 +1 @@ +class Person{constructor(name){this._name = name;}} diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml new file mode 100644 index 0000000000..583c315c4b --- /dev/null +++ b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml @@ -0,0 +1,11 @@ +import QtQml + +QtObject { + // This to enum + enum Foo { + A = 3, // This is A + B, // This is B + C = 4, // This is C + D // This is D + } +} diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.qml b/tests/auto/qml/qmlformat/data/commentInEnum.qml new file mode 100644 index 0000000000..3a1b15d278 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/commentInEnum.qml @@ -0,0 +1,12 @@ +import QtQml + +QtObject { + // This to enum + enum Foo { + A = 3, // This is A + B, // This is B + C = 4, // This is C + D // This is D + } + +} diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml new file mode 100644 index 0000000000..749dc65b7c --- /dev/null +++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml @@ -0,0 +1,4 @@ +import QtQml + +// hello world +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml new file mode 100644 index 0000000000..9aca637e4f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml @@ -0,0 +1,5 @@ +import QtQml + +QtObject { + // hello world +} diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml new file mode 100644 index 0000000000..0bfcc58179 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml @@ -0,0 +1,24 @@ +import QtQml + +QtObject { + + function evil({ + hello = "world", + x = 42 + }, [n = 42, m = 43, o = 44], { + destructuring, + is = { + a, + lot, + of + }, + fun = 42 + } = { + destructuring: 123, + is: { + x: 123 + }, + fun: 456 + }) { + } +} diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml new file mode 100644 index 0000000000..f41661ed67 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml @@ -0,0 +1,9 @@ +import QtQml + +QtObject { + + function evil({ hello = "world", x = 42 }, + [n = 42, m = 43, o = 44], + { destructuring, is = {a, lot, of}, fun = 42 } = {destructuring : 123, is : {x : 123}, fun : 456}) { + } +} diff --git a/tests/auto/qml/qmlformat/data/directives.formatted.js b/tests/auto/qml/qmlformat/data/directives.formatted.js new file mode 100644 index 0000000000..3d0a4db544 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/directives.formatted.js @@ -0,0 +1,8 @@ +.pragma library +.import "fun.js" as Fun +.import Qt.test 1.0 as JsQtTest +.import Qt.Quick as Test + +Fun.begin(); +Test.do_stuff(); +JsQtTest.do_stuff(); diff --git a/tests/auto/qml/qmlformat/data/directives.js b/tests/auto/qml/qmlformat/data/directives.js new file mode 100644 index 0000000000..b8e1b785ac --- /dev/null +++ b/tests/auto/qml/qmlformat/data/directives.js @@ -0,0 +1,9 @@ + +.pragma library + +.import "fun.js" as Fun +.import Qt.test 1.0 as JsQtTest + + +.import Qt.Quick as Test +Fun.begin();Test.do_stuff();JsQtTest.do_stuff(); diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js new file mode 100644 index 0000000000..c130f72453 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js @@ -0,0 +1,6 @@ +.pragma library // use as library +/* + Fun is necessary + */ +.import "fun.js" as Fun +.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.js b/tests/auto/qml/qmlformat/data/directivesWithComments.js new file mode 100644 index 0000000000..7206bb27ed --- /dev/null +++ b/tests/auto/qml/qmlformat/data/directivesWithComments.js @@ -0,0 +1,8 @@ + +.pragma library // use as library + +/* + Fun is necessary + */ +.import "fun.js" as Fun +.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml new file mode 100644 index 0000000000..8eaac71178 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml @@ -0,0 +1,15 @@ +Item { + property var test: [ + { + // Testing + "foo": "bar" + } + ] + + onTestChanged: { + fooBar(test, { + // Testing + "foo": "bar" + }); + } +} diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml new file mode 100644 index 0000000000..2d2b4b6705 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml @@ -0,0 +1,15 @@ +Item { + property var test: [ + { + // Testing + "foo": "bar" + } + ] + + onTestChanged: { + fooBar(test, { + // Testing + "foo": "bar" + }); + } +} diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml new file mode 100644 index 0000000000..de6a23f9c7 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml @@ -0,0 +1,39 @@ +import QtQuick + +Item { + + function f() { + var count = 0; + + class Person { + constructor(name){ + this._name = name; + } + } + + class Employee extends Person { + constructor(name, age){ + super(name); + this._name = name; + this._age = age; + ++count; + } + + doWork(){} + + /* do we get the comment? */ get name(){ + return this._name.toUpperCase(); + } + + set name(newName){ + if (newName) { + this._name = newName; + } + } + + static get count(){ + return count; + } + } + } +} diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml new file mode 100644 index 0000000000..268859d3cc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml @@ -0,0 +1,45 @@ +import QtQuick + +Item { + +function f() { + +var count = 0; + +class Person { + constructor(name) { + this._name = name + } +} + +class Employee extends Person{ + + + constructor(name, age) { + super(name); + this._name = name; + this._age = age; + ++count; + } + + doWork() { + + } + + get /* do we get the comment? */ name() { + return this._name.toUpperCase(); + } + + set name(newName){ + if(newName){ + this._name = newName; + } + } + + static get count() { return count;} +} + + +} + +}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml new file mode 100644 index 0000000000..f41942e054 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml @@ -0,0 +1,13 @@ +import QtQml + +QtObject { + + function patron(a, ...b) { + } + + function patron1(a, ...[b, ...args]) { + } + + function patron2(...{}) { + } +} diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml new file mode 100644 index 0000000000..28364f29c9 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml @@ -0,0 +1,11 @@ +import QtQml + +QtObject { + + function patron(a, ...b) { + } + + function patron1(a, ...[b, ...args]) {} + + function patron2(...{}) {} +}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml new file mode 100644 index 0000000000..3f6807834f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml @@ -0,0 +1,16 @@ +import QtQuick + +Item { + x: { + const s = "\""; + let a = { + "\"": "\\" + }; + + let patron = { + "\\\"\n\n": "\?\?\\\"", + "": "", + "\'\"\n": 1 + }; + } +} diff --git a/tests/auto/qml/qmlformat/data/escapeChars.qml b/tests/auto/qml/qmlformat/data/escapeChars.qml new file mode 100644 index 0000000000..c82ff3119e --- /dev/null +++ b/tests/auto/qml/qmlformat/data/escapeChars.qml @@ -0,0 +1,16 @@ +import QtQuick + +Item { + x: { + const s = "\"" + let a = { + "\"": "\\" + }; + + let patron = { + "\\\"\n\n" : "\?\?\\\"","": "", "\'\"\n":1 + }; + + + } +} diff --git a/tests/auto/qml/qmlformat/data/esm.formatted.mjs b/tests/auto/qml/qmlformat/data/esm.formatted.mjs new file mode 100644 index 0000000000..f0b3fd7753 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/esm.formatted.mjs @@ -0,0 +1,44 @@ +//Imports +import defaultExport from "module-name"; +import * as name from "module-name"; +import { export1 } from "module-name"; +import { export1 as alias1 } from "module-name"; +import { default as alias } from "module-name"; +import { export1, export2 } from "module-name"; +import { export1, export2 as alias2 } from "module-name"; +import defaultExport, { export1, a } from "module-name"; +import defaultExport, * as name from "module-name"; +import "module-name"; + +// Exporting declarations +export let name1, name2; // also var +export const name1 = 1, name2 = 2; // also var, let +export function functionName() {} +export class ClassName { + constructor(h){ + this.h = h; + } +} +export function* generatorFunctionName() {} +export const { + name1, + name2: bar +} = o; +export const [name1, name2] = array; + +// Export list +export { name1, nameN }; +export { variable1 as name1, variable2 as name2, nameN }; +export { name1 as default }; + +// Default exports +export default function* generatorFunctionName() { + return 1; +} + +// Aggregating modules +export * from "module-name"; +export { name1, nameN } from "module-name"; +export { import1 as name1, import2 as name2, nameN } from "module-name"; +export { default } from "module-name"; +export { default as name1 } from "module-name"; diff --git a/tests/auto/qml/qmlformat/data/esm.mjs b/tests/auto/qml/qmlformat/data/esm.mjs new file mode 100644 index 0000000000..83e22fdedd --- /dev/null +++ b/tests/auto/qml/qmlformat/data/esm.mjs @@ -0,0 +1,33 @@ +//Imports +import defaultExport from "module-name"; +import * as name from "module-name" +import {export1} from "module-name"; +import { export1 as alias1 } from "module-name"; +import { default as alias } from "module-name" +import { export1, export2 } from "module-name"; +import {export1,export2 as alias2} from "module-name"; +import defaultExport,{export1,a} from "module-name" +import defaultExport, * as name from "module-name"; +import "module-name"; + + +// Exporting declarations +export let name1,name2; // also var +export const name1=1,name2=2 // also var, let +export function functionName() {} +export class ClassName{constructor(h){this.h=h;}} +export function* generatorFunctionName() {} +export const {name1, name2: bar}=o;export const [name1,name2]=array + +// Export list +export {name1,nameN};export {variable1 as name1,variable2 as name2,nameN } +export {name1 as default}; + +// Default exports +export default function* generatorFunctionName() {return 1;} + +// Aggregating modules +export * from "module-name"; +export { name1,nameN} from "module-name" +export { import1 as name1, import2 as name2,nameN } from "module-name";export { default, } from "module-name"; +export { default as name1 } from "module-name"; diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml new file mode 100644 index 0000000000..a995f0479f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml @@ -0,0 +1,10 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQml + +QtObject { + property int a + function aa() { + } +} diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml new file mode 100644 index 0000000000..8aef366bd9 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml @@ -0,0 +1,9 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQml + +QtObject { +property int a +function aa(){} +}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml new file mode 100644 index 0000000000..a995f0479f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml @@ -0,0 +1,10 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQml + +QtObject { + property int a + function aa() { + } +} diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml new file mode 100644 index 0000000000..f2cb636c00 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml @@ -0,0 +1,9 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQml + +QtObject { + property int a + function aa() {} +} diff --git a/tests/auto/qml/qmlformat/data/forOf.formatted.qml b/tests/auto/qml/qmlformat/data/forOf.formatted.qml index fa29f16b81..0cc4f9fecd 100644 --- a/tests/auto/qml/qmlformat/data/forOf.formatted.qml +++ b/tests/auto/qml/qmlformat/data/forOf.formatted.qml @@ -3,7 +3,10 @@ import QtQml 2.0 QtObject { Component.onCompleted: { var list = [[1, 2], [3, 4], [5, 6]]; - for (const [x, y] of list) console.log("X: " + x + "; Y: " + y) - for (let [x, y] of list) console.log("X: " + x + "; Y: " + y) + + for (const [x, y] of list) + console.log("X: " + x + "; Y: " + y); + for (let [x, y] of list) + console.log("X: " + x + "; Y: " + y); } } diff --git a/tests/auto/qml/qmlformat/data/forWithLet.formatted.qml b/tests/auto/qml/qmlformat/data/forWithLet.formatted.qml new file mode 100644 index 0000000000..5fecc1d180 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/forWithLet.formatted.qml @@ -0,0 +1,8 @@ +import QtQml + +QtObject { + function foo() { + for (let i = 0; i < 5; ++i) + console.log(i); + } +} diff --git a/tests/auto/qml/qmlformat/data/forWithLet.qml b/tests/auto/qml/qmlformat/data/forWithLet.qml new file mode 100644 index 0000000000..afed76ebce --- /dev/null +++ b/tests/auto/qml/qmlformat/data/forWithLet.qml @@ -0,0 +1,8 @@ +import QtQml + +QtObject { +function foo() { +for (let i = 0; i < 5; ++i) +console.log(i); +} +} diff --git a/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml new file mode 100644 index 0000000000..91f520b5fc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml @@ -0,0 +1,20 @@ +Item { + id: test + + signal testSignal + function test1() { + } + function test2() { + } + Button {} + + function test4() { + } + + function test5() { + } + height: 360 + width: 360 + function test3() { + } +} diff --git a/tests/auto/qml/qmlformat/data/functionsSpacing.qml b/tests/auto/qml/qmlformat/data/functionsSpacing.qml new file mode 100644 index 0000000000..d8a5071445 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/functionsSpacing.qml @@ -0,0 +1,22 @@ +Item { + id: test + + signal testSignal + function test1() { + } + function test2() { + } + Button { + } + + function test4() { + } + + + function test5() { + } + height: 360 + width: 360 + function test3() { + } +} diff --git a/tests/auto/qml/qmlformat/data/importStatements.formatted.qml b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml new file mode 100644 index 0000000000..6613becaca --- /dev/null +++ b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml @@ -0,0 +1,8 @@ +import QtQml + +import QtQuick +import QtQuick.Controls + +import org.test.module + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/importStatements.qml b/tests/auto/qml/qmlformat/data/importStatements.qml new file mode 100644 index 0000000000..efe1872e93 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/importStatements.qml @@ -0,0 +1,12 @@ +import QtQml + + +import QtQuick +import QtQuick.Controls + +import org.test.module + + + +QtObject { +} diff --git a/tests/auto/qml/qmlformat/data/inlineComponents.formatted.qml b/tests/auto/qml/qmlformat/data/inlineComponents.formatted.qml index fd5ab99197..9d35f763fa 100644 --- a/tests/auto/qml/qmlformat/data/inlineComponents.formatted.qml +++ b/tests/auto/qml/qmlformat/data/inlineComponents.formatted.qml @@ -3,5 +3,4 @@ Item { color: "red" text: "Test Text" } - } diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml new file mode 100644 index 0000000000..09ab9454e1 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml @@ -0,0 +1,6 @@ +Item { + block1: { + console.log("Hello, world!"); + } + emptyBlock: {} +} diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.qml new file mode 100644 index 0000000000..1665c81f42 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/javascriptBlock.qml @@ -0,0 +1,5 @@ +Item { + block1: {console.log("Hello, world!");} + emptyBlock: { + } +} diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js new file mode 100644 index 0000000000..62a5e36f5e --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js @@ -0,0 +1,6 @@ +var b = function () { + var a = 1; + for (var ii = 1; ii < 10; ++ii) { + a = a * ii; + } +}; diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js new file mode 100644 index 0000000000..0155cff7f9 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js @@ -0,0 +1 @@ +var b=function(){var a=1;for(var ii=1;ii<10;++ii){a=a*ii;}} diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js new file mode 100644 index 0000000000..3bc7f683c4 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js @@ -0,0 +1,7 @@ +var f = function () { + if (true) { + console.log("true"); + } else { + console.log("false"); + } +}; diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js new file mode 100644 index 0000000000..aaf731e5f0 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js @@ -0,0 +1 @@ +var f = function(){if(true){ console.log("true");} else {console.log("false");}} diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js new file mode 100644 index 0000000000..99db6fb372 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js @@ -0,0 +1,9 @@ +var l = function () { + var nl = function () { + if (true) { + console.log("true"); + } else { + console.log("false"); + } + }; +}; diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js new file mode 100644 index 0000000000..23ae087b04 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js @@ -0,0 +1 @@ +var l = function(){var nl = function(){if(true){console.log("true");}else{console.log("false");}};}; diff --git a/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml b/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml index 354693d229..879bf297b2 100644 --- a/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml +++ b/tests/auto/qml/qmlformat/data/largeBindings.formatted.qml @@ -2,16 +2,15 @@ import QtQml import QtQuick 2 QtObject { - small1: 3 - small2: foo - smallButNeedsBraces: { - if (foo) { - bar(); - } - } // THIS NEEDS TO BE LAST largeBinding: { var x = 300; console.log(x); } + + small1: 3 + small2: foo + smallButNeedsBraces: if (foo) { + bar(); + } } diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js new file mode 100644 index 0000000000..cd7d75314c --- /dev/null +++ b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js @@ -0,0 +1,4 @@ +if (((typeof ezJsu !== 'undefined') && ezJsu === true) || ((typeof _ez_sa !== 'undefined') && _ez_sa === true)) { + a.defaultStoreUrl = '//g.ezoic.net/ezoic/imp.gif'; + a.defaultStoreA = '//g.ezoic.net/ezoic/i.gif';// Single Line Comments here +} diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.js b/tests/auto/qml/qmlformat/data/messyIfStatement.js new file mode 100644 index 0000000000..cdd4c7bd9d --- /dev/null +++ b/tests/auto/qml/qmlformat/data/messyIfStatement.js @@ -0,0 +1,2 @@ +if (((typeof ezJsu!=='undefined')&&ezJsu===true)||((typeof _ez_sa !=='undefined')&&_ez_sa === true)) {a.defaultStoreUrl='//g.ezoic.net/ezoic/imp.gif';a.defaultStoreA ='//g.ezoic.net/ezoic/i.gif';// Single Line Comments here +} diff --git a/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs new file mode 100644 index 0000000000..37f8ccb698 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs @@ -0,0 +1,20 @@ +//Imports +import defaultExport from "module-name"; +import "module-name"; +export class ClassName { + constructor(h){ + this.h = h; + } +} +export const { + n1, + n3, + n4, + name2: bar +} = o; +export const [name1, name2] = array; +function stuff() { + var l = () => { + 1 + 1; + }; +} diff --git a/tests/auto/qml/qmlformat/data/mini_esm.mjs b/tests/auto/qml/qmlformat/data/mini_esm.mjs new file mode 100644 index 0000000000..9d6c2406dc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/mini_esm.mjs @@ -0,0 +1,3 @@ +//Imports +import defaultExport from "module-name";import "module-name";export class ClassName{constructor(h){this.h=h;}} +export const {n1,n3,n4,name2:bar}=o;export const [name1,name2]=array;function stuff(){var l=()=>{1+1};}; diff --git a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml index 830ff32095..46e3e963ea 100644 --- a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml +++ b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml @@ -1,12 +1,9 @@ Item { - Item { - } + Item {} - // This is a multiline comment. - // it should stay attached to Commented instead of getting orphaned. - // + /* This is a multiline comment. + it should stay attached to Commented instead of getting orphaned. + */ // This should also stick to Commented - Commented { - } - + Commented {} } diff --git a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml index 5a3489e98f..fc1915f647 100644 --- a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml +++ b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml @@ -1,16 +1,13 @@ Item { function a() { - function nested() { - } + function nested() {} foo(); } function b() { - function nested() { - } + function nested() {} bar(); } - } diff --git a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml index 11acf5b568..ebb125f36d 100644 --- a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml +++ b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml @@ -6,11 +6,11 @@ Item { foo(); else bar(); - } else if (x == 3) { + } else if (x == 3) stuff(); - } else { + else foo_bar(); - } + // Same for "for" if (a) { for (x in y) { @@ -18,6 +18,7 @@ Item { y(); } } + // ...and while if (b) { while (y in x) { @@ -25,6 +26,7 @@ Item { x(); } } + if (x && y) if (x < y) return 0; diff --git a/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.formatted.qml new file mode 100644 index 0000000000..5b41da753b --- /dev/null +++ b/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.formatted.qml @@ -0,0 +1,26 @@ +Item { + id: test + + signal testSignal + + function test1() { + } + + function test2() { + } + + function test3() { + } + + function test4() { + } + + function test5() { + } + + height: 360 + width: 360 + + Button { + } +} diff --git a/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.qml b/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.qml new file mode 100644 index 0000000000..5451e0e66a --- /dev/null +++ b/tests/auto/qml/qmlformat/data/normalizedFunctionsSpacing.qml @@ -0,0 +1,23 @@ +Item { + id: test + + signal testSignal + function test1() { + } + function test2() { + } + Button { + } + + function test4() { + } + + + function test5() { + } + height: 360 + width: 360 + function test3() { + } + +} diff --git a/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.formatted.qml new file mode 100644 index 0000000000..97f09a177f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.formatted.qml @@ -0,0 +1,30 @@ +Item { + height: 360 + width: 360 + + Button { + } + + Rectangle { + color: "salmon" + height: 360 + width: 360 + + Item { + Loader { + height: 360 + width: 360 + } + + Loader { + height: 360 + width: 360 + } + } + } + + Image { + height: 360 + width: 360 + } +} diff --git a/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.qml b/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.qml new file mode 100644 index 0000000000..6adc89778c --- /dev/null +++ b/tests/auto/qml/qmlformat/data/normalizedObjectsSpacing.qml @@ -0,0 +1,31 @@ +Item { + + Button { + } + + height: 360 + width: 360 + + Rectangle { + color: "salmon" + height: 360 + width: 360 + + Item { + + Loader { + height: 360 + width: 360 + } + Loader { + height: 360 + width: 360 + } + + } + } + Image { + height: 360 + width: 360 + } +} diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml new file mode 100644 index 0000000000..94e97076b1 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml @@ -0,0 +1,137 @@ +import QtQml + +QtObject { + + function set1() { + const array = [1, 2, 3, 4]; + const [a, b] = [1, 2]; + const [aa, , bb] = array; + const [aaa = 23, bbb] = array; + const [a1, b1, ...rest1] = array; + const [a2, , b2, ...rest2] = array; + const [a3, b3, ...{ + pop, + push + }] = array; + const [a4, b4, ...[c, d]] = array; + + const obj = { + _a: 1, + _b: 2 + }; + const { + a5, + b5 + } = obj; + const { + a6: a_, + b6: b1_ + } = obj; + const { + a7: a11 = 4, + b11 = 34, + c1: b111, + d1 + } = obj; + let key = a; + const { + [key]: a___ + } = obj; + } + + function set2() { + // declare first + let a, b, a1, b1, c, d, rest, pop, push; + const array = [1, 2, 3, 4]; + [a, b] = array; + [a, , b] = array; + [a = aDefault, b] = array; + [a, b, ...rest] = array; + [a, , b, ...rest] = array; + [a, b, ...{ + pop, + push + }] = array; + [a, b, ...[c, d]] = array; + + const obj = { + _a: 1, + _b: 2 + }; + ({ + a, + b + } = obj); // brackets are required + ({ + a: a1, + b: b1 + } = obj); + + const complicatedObject = { + a: 1, + b: { + c: 2, + d: { + e: 3, + f: [4, 5, 6] + } + }, + g: [7, 8, 9] + }; + + const { + patron, + b: { + mafik, + d: { + e, + f: [, secondF, ...restF] + } + }, + g: [firstG, ...restG] + } = complicatedObject; + } + + Component.onCompleted: { + const myFunction = myLambda => { + const myObject = { + a: 1, + b: { + c: 2, + d: [3, 4, 5] + }, + e: { + f: 6, + g: { + h: 7, + i: [8, 9, 10] + } + } + }; + + myLambda(myObject); + }; + + myFunction(({ + a, + b: { + c, + d: [firstD] + }, + e: { + f, + g: { + h, + i: [, secondI] + } + } + }) => { + console.log(a); // 1 + console.log(c); // 2 + console.log(firstD); // 3 + console.log(f); // 6 + console.log(h); // 7 + console.log(secondI); // 9 + }); + } +} diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.qml new file mode 100644 index 0000000000..0487153125 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/objectDestructuring.qml @@ -0,0 +1,77 @@ +import QtQml + +QtObject { + + function set1() { + const array = [1,2,3,4]; + const [a, b] = [1,2]; + const [aa, , bb] = array; + const [aaa = 23, bbb] = array; + const [a1, b1, ...rest1] = array; + const [a2, , b2, ...rest2] = array; + const [a3, b3, ...{ pop, push }] = array; + const [a4, b4, ...[c, d]] = array; + + const obj = {_a:1,_b:2}; + const { a5, b5 } = obj; + const { a6: a_, b6: b1_ } = obj; + const { a7: a11 = 4, b11 = 34, c1: b111, d1 } = obj; + let key = a; + const { [key]: a___ } = obj; + } + + function set2() { + // declare first + let a, b, a1, b1, c, d, rest, pop, push; + const array = [1,2,3,4]; + [a, b] = array; + [a, , b] = array; + [a = aDefault, b] = array; + [a, b, ...rest] = array; + [a, , b, ...rest] = array; + [a, b, ...{ pop, push }] = array; + [a, b, ...[c, d]] = array; + + const obj = {_a:1,_b:2}; + ({ a, b } = obj); // brackets are required + ({ a: a1, b: b1 } = obj); + + const complicatedObject = { + a: 1, + b: { + c: 2, + d: { + e: 3, + f: [4, 5, 6] + } + }, + g: [7, 8, 9] + }; + + const { patron, b: { mafik, d: { e, f: [ , secondF, ...restF ] } }, g: [ firstG, ...restG ] } = complicatedObject; + } + + Component.onCompleted: { + const myFunction = (myLambda) => { + const myObject = { + a: 1, + b: {c: 2, d: [3, 4, 5] }, e: { + f: 6, + g: { h: 7, i: [8, 9, 10] + } + } + }; + + myLambda(myObject); + }; + + myFunction(({ a, b: { c, d: [ firstD ] }, e: { f, g: { h, i: [ , secondI ] } } }) => { + console.log(a); // 1 + console.log(c); // 2 + console.log(firstD); // 3 + console.log(f); // 6 + console.log(h); // 7 + console.log(secondI); // 9 + }); + } +} diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml new file mode 100644 index 0000000000..df26a9b599 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml @@ -0,0 +1,33 @@ +Item { + + Button {} + + Button { + id: foo + } + + height: 360 + width: 360 + + Rectangle { + color: "salmon" + height: 360 + width: 360 + + Item { + + Loader { + height: 360 + width: 360 + } + Loader { + height: 360 + width: 360 + } + } + } + Image { + height: 360 + width: 360 + } +} diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.qml new file mode 100644 index 0000000000..0239b05145 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/objectsSpacing.qml @@ -0,0 +1,35 @@ +Item { + + Button { + } + + Button { + id: foo + } + + height: 360 + width: 360 + + Rectangle { + color: "salmon" + height: 360 + width: 360 + + Item { + + Loader { + height: 360 + width: 360 + } + Loader { + height: 360 + width: 360 + } + + } + } + Image { + height: 360 + width: 360 + } +} diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.js b/tests/auto/qml/qmlformat/data/pragma.formatted.js new file mode 100644 index 0000000000..3f57e537ac --- /dev/null +++ b/tests/auto/qml/qmlformat/data/pragma.formatted.js @@ -0,0 +1,4 @@ +"use strict"; +{ + function f() {} +} diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.qml b/tests/auto/qml/qmlformat/data/pragma.formatted.qml new file mode 100644 index 0000000000..143db39888 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/pragma.formatted.qml @@ -0,0 +1,8 @@ +pragma Singleton +pragma ComponentBehavior: Bound +pragma FunctionSignatureBehavior: Enforced +pragma ValueTypeBehavior: Copy, Addressable + +import QtQml + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/pragma.js b/tests/auto/qml/qmlformat/data/pragma.js new file mode 100644 index 0000000000..b81d52d853 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/pragma.js @@ -0,0 +1 @@ +"use strict";{function f(){}} diff --git a/tests/auto/qml/qmlformat/data/pragma.qml b/tests/auto/qml/qmlformat/data/pragma.qml new file mode 100644 index 0000000000..7469277395 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/pragma.qml @@ -0,0 +1,8 @@ +pragma Singleton + pragma ComponentBehavior: Bound + pragma FunctionSignatureBehavior: Enforced +pragma ValueTypeBehavior: Copy, Addressable + +import QtQml + +QtObject {} diff --git a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml index c7d50abb32..9214014889 100644 --- a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml +++ b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml @@ -3,12 +3,11 @@ Item { var copiedItem = "copied value"; var computedItem = "computedName"; var obj = { - "identifierName": "identifier value", + identifierName: "identifier value", "string name": "string value", - "Infinity": "numeric value", + Infinity: "numeric value", [computedItem]: "computed value", - "copiedItem": copiedItem + copiedItem }; } - } diff --git a/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml index 6e7cc31dcf..354f2ba979 100644 --- a/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml +++ b/tests/auto/qml/qmlformat/data/readOnlyProps.formatted.qml @@ -2,11 +2,9 @@ import QtQuick 2.0 QtObject { // Testing UiObjectBinding - readonly property Item - item: Item { + readonly property Item item: Item { id: test - - signal foo() + signal foo } // End comment @@ -14,16 +12,16 @@ QtObject { readonly property list<Item> array: [ Item { id: test1 - - signal foo() + signal foo }, Item { id: test2 - - signal bar() + signal bar } ] + // Testing UiScriptBinding readonly property int script: Math.sin(Math.PI) + property bool normalProperty: true } diff --git a/tests/auto/qml/qmlformat/data/settings/.qmlformat.ini b/tests/auto/qml/qmlformat/data/settings/.qmlformat.ini new file mode 100644 index 0000000000..ae1eed5254 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/settings/.qmlformat.ini @@ -0,0 +1,5 @@ +[General] +IndentWidth=2 +NewlineType=macos +NormalizeOrder=true +UseTabs= diff --git a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml new file mode 100644 index 0000000000..767bfe7e61 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml @@ -0,0 +1 @@ +/* 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 {
// 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
}
// Orphan comment
// Another orphan
// More orphans
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool some_bool: false
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
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";
}()
signal say(string name, bool caps)
// This one to aFunc()
function aFunc() {
var x = 3;
return x;
}
x: 3 // Very cool
myFavouriteThings: [
// This is an orphan
// This is a cool text
Text {
},
// This is a cool rectangle
Rectangle {
}
]
// This comment is related to the property animation
PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
}
Component.onCompleted: console.log("Foo!")
Text {
required property string batman
signal boo(int count, int times, real duration)
text: "Bla"
}
}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/data/settings/Example1.qml b/tests/auto/qml/qmlformat/data/settings/Example1.qml new file mode 100644 index 0000000000..36ffc6b058 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/settings/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: foo2; 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/data/simpleJSStatement.formatted.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js new file mode 100644 index 0000000000..fbdec1038c --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js @@ -0,0 +1 @@ +let v = 1; diff --git a/tests/auto/qml/qmlformat/data/simpleJSStatement.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.js new file mode 100644 index 0000000000..d954a87fc0 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.js @@ -0,0 +1 @@ +let v=1; diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js new file mode 100644 index 0000000000..435fc145bf --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js @@ -0,0 +1,4 @@ +var a = 1; +for (var ii = 1; ii < 10; ++ii) { + a = a * ii; +} diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.js b/tests/auto/qml/qmlformat/data/simpleLoop.js new file mode 100644 index 0000000000..08b172991f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleLoop.js @@ -0,0 +1 @@ +var a=1;for(var ii=1;ii<10;++ii){a=a*ii;} diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js new file mode 100644 index 0000000000..d5b34291e6 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js @@ -0,0 +1,4 @@ +function f() { + let a = 0; + return a; +} diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js new file mode 100644 index 0000000000..c49be5e2bd --- /dev/null +++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js @@ -0,0 +1 @@ +function f(){let a=0;return a; } diff --git a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml index bd063ac498..923f0642d7 100644 --- a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml +++ b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml @@ -1,16 +1,13 @@ QtObject { id: foo - // This needs to be *before* states and transitions after formatting - Item { - } - states: [ - State { - } + State {} ] transitions: [ - Transition { - } + Transition {} ] + + // This needs to be *before* states and transitions after formatting + Item {} } diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js new file mode 100644 index 0000000000..592db7a02b --- /dev/null +++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js @@ -0,0 +1,11 @@ +function one() { + var a=1; +} + +function two(a, b) { + console.log(a,b); +} + +function three(c) { + var a=c; +} diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js new file mode 100644 index 0000000000..6575a9fbd8 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js @@ -0,0 +1,9 @@ +function one() { + var a = 1; +} +function two(a, b) { + console.log(a, b); +} +function three(c) { + var a = c; +} diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js new file mode 100644 index 0000000000..afcf8acf02 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js @@ -0,0 +1,9 @@ +function one() { + var a = 1; +} +function two(a, b) { + console.log(a, b); +} +function three(c) { + var a = c; +} diff --git a/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js new file mode 100644 index 0000000000..648591f221 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js @@ -0,0 +1 @@ +function one() {var a=1;}function two(a, b) {console.log(a,b);}function three(c){var a=c;} diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js new file mode 100644 index 0000000000..b7414de053 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js @@ -0,0 +1,12 @@ +function one() { + var a = 1; + if (a === true) { + a = 5; + } +} + +function two(a, b) { + for (; b < 5; ++b) { + a = a * b; + } +} diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.js b/tests/auto/qml/qmlformat/data/twoFunctions.js new file mode 100644 index 0000000000..b410ebd167 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/twoFunctions.js @@ -0,0 +1,3 @@ +function one(){var a=1;if (a===true){a=5;}} + +function two(a,b){for(;b<5;++b){a=a*b;}} diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index 165be7e973..da3ebc69a2 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTest> #include <QDir> @@ -32,16 +7,46 @@ #include <QProcess> #include <QString> #include <QTemporaryDir> +#include <QtTest/private/qemulationdetector_p.h> +#include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQmlDom/private/qqmldomitem_p.h> +#include <QtQmlDom/private/qqmldomlinewriter_p.h> +#include <QtQmlDom/private/qqmldomoutwriter_p.h> +#include <QtQmlDom/private/qqmldomtop_p.h> -#include <util.h> +using namespace QQmlJS::Dom; + +// TODO refactor extension helpers +const QString QML_EXT = ".qml"; +const QString JS_EXT = ".js"; +const QString MJS_EXT = ".mjs"; + +static QStringView fileExt(QStringView filename) +{ + if (filename.endsWith(QML_EXT)) { + return QML_EXT; + } + if (filename.endsWith(JS_EXT)) { + return JS_EXT; + } + if (filename.endsWith(MJS_EXT)) { + return MJS_EXT; + } + Q_UNREACHABLE(); +}; class TestQmlformat: public QQmlDataTest { Q_OBJECT +public: + enum class RunOption { OnCopy, OrigToCopy }; + TestQmlformat(); + private Q_SLOTS: void initTestCase() override; + //actually testFormat tests CLI of qmlformat void testFormat(); void testFormat_data(); @@ -49,20 +54,46 @@ private Q_SLOTS: #if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void testExample(); void testExample_data(); + void normalizeExample(); + void normalizeExample_data(); #endif + void testBackupFileLimit(); + + void testFilesOption_data(); + void testFilesOption(); + + void plainJS_data(); + void plainJS(); + + void ecmascriptModule(); + private: QString readTestFile(const QString &path); - QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true); + //TODO(QTBUG-117849) refactor this helper function + QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true, + RunOption rOption = RunOption::OnCopy, QStringView ext = QML_EXT); + QString formatInMemory(const QString &fileToFormat, bool *didSucceed = nullptr, + LineWriterOptions options = LineWriterOptions(), + WriteOutChecks extraChecks = WriteOutCheck::ReparseCompare, + WriteOutChecks largeChecks = WriteOutCheck::None); QString m_qmlformatPath; QStringList m_excludedDirs; QStringList m_invalidFiles; + QStringList m_ignoreFiles; QStringList findFiles(const QDir &); bool isInvalidFile(const QFileInfo &fileName) const; + bool isIgnoredFile(const QFileInfo &fileName) const; }; +// Don't fail on warnings because we read a lot of QML files that might intentionally be malformed. +TestQmlformat::TestQmlformat() + : QQmlDataTest(QT_QMLTEST_DATADIR, FailOnWarningsPolicy::DoNotFailOnWarnings) +{ +} + void TestQmlformat::initTestCase() { QQmlDataTest::initTestCase(); @@ -85,6 +116,7 @@ void TestQmlformat::initTestCase() m_excludedDirs << "doc/src/snippets/qtquick1/qtbinding"; m_excludedDirs << "doc/src/snippets/qtquick1/imports"; m_excludedDirs << "tests/manual/v4"; + m_excludedDirs << "tests/manual/qmllsformatter"; m_excludedDirs << "tests/auto/qml/ecmascripttests"; m_excludedDirs << "tests/auto/qml/qmllint"; @@ -101,6 +133,9 @@ void TestQmlformat::initTestCase() m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidRoot.1.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.1.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.2.qml"; + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidQmlEnumValue.3.qml"; + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidID.4.qml"; + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/questionDotEOF.qml"; m_invalidFiles << "tests/auto/qml/qquickfolderlistmodel/data/dummy.qml"; m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.1.qml"; m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.2.qml"; @@ -123,16 +158,43 @@ void TestQmlformat::initTestCase() m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml"; m_invalidFiles << "tests/auto/qml/qqmllanguage/data/typeAnnotations.2.qml"; m_invalidFiles << "tests/auto/qml/qqmlparser/data/disallowedtypeannotations/qmlnestedfunction.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/emptyFile.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/completions/afterDots.qml"; + m_invalidFiles << "tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml"; + m_invalidFiles << "tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml"; + m_invalidFiles << "tests/auto/qmlls/utils/data/qualifiedModule.qml"; + + // Files that get changed: + // rewrite of import "bla/bla/.." to import "bla" + m_invalidFiles << "tests/auto/qml/qqmlcomponent/data/componentUrlCanonicalization.4.qml"; + // block -> object in internal update + m_invalidFiles << "tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml"; + // removal of unsupported indexing of Object declaration + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/hangOnWarning.qml"; + // removal of duplicated id + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/component.3.qml"; + // Optional chains are not permitted on the left-hand-side in assignments + m_invalidFiles << "tests/auto/qml/qqmllanguage/data/optionalChaining.LHS.qml"; + // object literal with = assignements + m_invalidFiles << "tests/auto/quickcontrols/controls/data/tst_scrollbar.qml"; // These files rely on exact formatting m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon1.qml"; m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml"; m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon2.qml"; + + // These files are too big + m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/longQmlFile.qml"; + m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/deeplyNested.qml"; } QStringList TestQmlformat::findFiles(const QDir &d) { - for (int ii = 0; ii < m_excludedDirs.count(); ++ii) { + for (int ii = 0; ii < m_excludedDirs.size(); ++ii) { QString s = m_excludedDirs.at(ii); if (d.absolutePath().endsWith(s)) return QStringList(); @@ -140,15 +202,17 @@ QStringList TestQmlformat::findFiles(const QDir &d) QStringList rv; - QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"), - QDir::Files); - foreach (const QString &file, files) { - rv << d.absoluteFilePath(file); + const QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"), + QDir::Files); + for (const QString &file: files) { + QString absoluteFilePath = d.absoluteFilePath(file); + if (!isIgnoredFile(QFileInfo(absoluteFilePath))) + rv << absoluteFilePath; } - QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | - QDir::NoSymLinks); - foreach (const QString &dir, dirs) { + const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | + QDir::NoSymLinks); + for (const QString &dir: dirs) { QDir sub = d; sub.cd(dir); rv << findFiles(sub); @@ -166,6 +230,15 @@ bool TestQmlformat::isInvalidFile(const QFileInfo &fileName) const return false; } +bool TestQmlformat::isIgnoredFile(const QFileInfo &fileName) const +{ + for (const QString &file : m_ignoreFiles) { + if (fileName.absoluteFilePath().endsWith(file)) + return true; + } + return false; +} + QString TestQmlformat::readTestFile(const QString &path) { QFile file(testFile(path)); @@ -200,49 +273,145 @@ void TestQmlformat::testFormat_data() QTest::addColumn<QString>("file"); QTest::addColumn<QString>("fileFormatted"); QTest::addColumn<QStringList>("args"); + QTest::addColumn<RunOption>("runOption"); - QTest::newRow("example1") + QTest::newRow("example1") << "Example1.qml" + << "Example1.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("example1 (tabs)") << "Example1.qml" - << "Example1.formatted.qml" << QStringList {}; - QTest::newRow("example1 (tabs)") << "Example1.qml" - << "Example1.formatted.tabs.qml" << QStringList { "-t" }; + << "Example1.formatted.tabs.qml" << QStringList { "-t" } << RunOption::OnCopy; QTest::newRow("example1 (two spaces)") << "Example1.qml" - << "Example1.formatted.2spaces.qml" << QStringList { "-w", "2" }; - QTest::newRow("annotation") - << "Annotations.qml" - << "Annotations.formatted.qml" << QStringList {}; + << "Example1.formatted.2spaces.qml" << QStringList { "-w", "2" } << RunOption::OnCopy; + QTest::newRow("annotation") << "Annotations.qml" + << "Annotations.formatted.qml" << QStringList {} + << RunOption::OnCopy; QTest::newRow("front inline") << "FrontInline.qml" - << "FrontInline.formatted.qml" << QStringList {}; + << "FrontInline.formatted.qml" << QStringList {} + << RunOption::OnCopy; QTest::newRow("if blocks") << "IfBlocks.qml" - << "IfBlocks.formatted.qml" << QStringList {}; - QTest::newRow("read-only properties") << "readOnlyProps.qml" - << "readOnlyProps.formatted.qml" << QStringList {}; + << "IfBlocks.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("read-only properties") + << "readOnlyProps.qml" + << "readOnlyProps.formatted.qml" << QStringList {} << RunOption::OnCopy; QTest::newRow("states and transitions") << "statesAndTransitions.qml" - << "statesAndTransitions.formatted.qml" << QStringList {}; - QTest::newRow("large bindings") << "largeBindings.qml" - << "largeBindings.formatted.qml" << QStringList {}; - QTest::newRow("verbatim strings") << "verbatimString.qml" - << "verbatimString.formatted.qml" << QStringList {}; - QTest::newRow("inline components") << "inlineComponents.qml" - << "inlineComponents.formatted.qml" << QStringList {}; + << "statesAndTransitions.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("large bindings") + << "largeBindings.qml" + << "largeBindings.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("verbatim strings") + << "verbatimString.qml" + << "verbatimString.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("inline components") + << "inlineComponents.qml" + << "inlineComponents.formatted.qml" << QStringList {} << RunOption::OnCopy; QTest::newRow("nested ifs") << "nestedIf.qml" - << "nestedIf.formatted.qml" << QStringList {}; + << "nestedIf.formatted.qml" << QStringList {} << RunOption::OnCopy; QTest::newRow("QTBUG-85003") << "QtBug85003.qml" - << "QtBug85003.formatted.qml" << QStringList {}; - QTest::newRow("nested functions") << "nestedFunctions.qml" - << "nestedFunctions.formatted.qml" << QStringList {}; - QTest::newRow("multiline comments") << "multilineComment.qml" - << "multilineComment.formatted.qml" << QStringList {}; + << "QtBug85003.formatted.qml" << QStringList {} + << RunOption::OnCopy; + QTest::newRow("nested functions") + << "nestedFunctions.qml" + << "nestedFunctions.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("multiline comments") + << "multilineComment.qml" + << "multilineComment.formatted.qml" << QStringList {} << RunOption::OnCopy; QTest::newRow("for of") << "forOf.qml" - << "forOf.formatted.qml" << QStringList {}; - QTest::newRow("property names") << "propertyNames.qml" - << "propertyNames.formatted.qml" << QStringList {}; + << "forOf.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("property names") + << "propertyNames.qml" + << "propertyNames.formatted.qml" << QStringList {} << RunOption::OnCopy; QTest::newRow("empty object") << "emptyObject.qml" - << "emptyObject.formatted.qml" << QStringList {}; - QTest::newRow("arrow functions") << "arrowFunctions.qml" - << "arrowFunctions.formatted.qml" << QStringList {}; + << "emptyObject.formatted.qml" << QStringList {} + << RunOption::OnCopy; + QTest::newRow("arrow functions") + << "arrowFunctions.qml" + << "arrowFunctions.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("settings") << "settings/Example1.qml" + << "settings/Example1.formatted_mac_cr.qml" << QStringList {} + << RunOption::OrigToCopy; + QTest::newRow("forWithLet") + << "forWithLet.qml" + << "forWithLet.formatted.qml" << QStringList {} << RunOption::OnCopy; + + QTest::newRow("objects spacing (no changes)") + << "objectsSpacing.qml" + << "objectsSpacing.formatted.qml" << QStringList { "--objects-spacing" } << RunOption::OnCopy; + + QTest::newRow("normalize + objects spacing") + << "normalizedObjectsSpacing.qml" + << "normalizedObjectsSpacing.formatted.qml" << QStringList { "-n", "--objects-spacing" } << RunOption::OnCopy; + + QTest::newRow("ids new lines") + << "checkIdsNewline.qml" + << "checkIdsNewline.formatted.qml" << QStringList { "-n" } << RunOption::OnCopy; + + QTest::newRow("functions spacing (no changes)") + << "functionsSpacing.qml" + << "functionsSpacing.formatted.qml" << QStringList { "--functions-spacing" } << RunOption::OnCopy; + + QTest::newRow("normalize + functions spacing") + << "normalizedFunctionsSpacing.qml" + << "normalizedFunctionsSpacing.formatted.qml" << QStringList { "-n", "--functions-spacing" } << RunOption::OnCopy; + QTest::newRow("dontRemoveComments") + << "dontRemoveComments.qml" + << "dontRemoveComments.formatted.qml" << QStringList {} << RunOption::OnCopy; + QTest::newRow("ecmaScriptClassInQml") + << "ecmaScriptClassInQml.qml" + << "ecmaScriptClassInQml.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("arrowFunctionWithBinding") + << "arrowFunctionWithBinding.qml" + << "arrowFunctionWithBinding.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("blanklinesAfterComment") + << "blanklinesAfterComment.qml" + << "blanklinesAfterComment.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("pragmaValueList") + << "pragma.qml" + << "pragma.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("objectDestructuring") + << "objectDestructuring.qml" + << "objectDestructuring.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("destructuringFunctionParameter") + << "destructuringFunctionParameter.qml" + << "destructuringFunctionParameter.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("ellipsisFunctionArgument") + << "ellipsisFunctionArgument.qml" + << "ellipsisFunctionArgument.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("importStatements") + << "importStatements.qml" + << "importStatements.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("arrayEndComma") + << "arrayEndComma.qml" + << "arrayEndComma.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("escapeChars") + << "escapeChars.qml" + << "escapeChars.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("javascriptBlock") + << "javascriptBlock.qml" + << "javascriptBlock.formatted.qml" << QStringList{} << RunOption::OnCopy; + + //plainJS + QTest::newRow("nestedLambdaWithIfElse") + << "lambdaWithIfElseInsideLambda.js" + << "lambdaWithIfElseInsideLambda.formatted.js" << QStringList{} << RunOption::OnCopy; + + QTest::newRow("indentEquals2") + << "threeFunctionsOneLine.js" + << "threeFunctions.formattedW2.js" << QStringList{"-w=2"} << RunOption::OnCopy; + + QTest::newRow("tabIndents") + << "threeFunctionsOneLine.js" + << "threeFunctions.formattedTabs.js" << QStringList{"-t"} << RunOption::OnCopy; + + QTest::newRow("normalizedFunctionSpacing") + << "threeFunctionsOneLine.js" + << "threeFunctions.formattedFuncSpacing.js" + << QStringList{ "-n", "--functions-spacing" } << RunOption::OnCopy; + + QTest::newRow("esm_tabIndents") + << "mini_esm.mjs" + << "mini_esm.formattedTabs.mjs" << QStringList{ "-t" } << RunOption::OnCopy; } void TestQmlformat::testFormat() @@ -250,21 +419,144 @@ void TestQmlformat::testFormat() QFETCH(QString, file); QFETCH(QString, fileFormatted); QFETCH(QStringList, args); + QFETCH(RunOption, runOption); - QCOMPARE(runQmlformat(testFile(file), args), readTestFile(fileFormatted)); + auto formatted = runQmlformat(testFile(file), args, true, runOption, fileExt(file)); + QEXPECT_FAIL("normalizedFunctionSpacing", + "Normalize && function spacing are not yet supported for JS", Abort); + auto exp = readTestFile(fileFormatted); + QCOMPARE(formatted, exp); +} + +void TestQmlformat::plainJS_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("fileFormatted"); + + QTest::newRow("simpleStatement") << "simpleJSStatement.js" + << "simpleJSStatement.formatted.js"; + QTest::newRow("simpleFunction") << "simpleOnelinerJSFunc.js" + << "simpleOnelinerJSFunc.formatted.js"; + QTest::newRow("simpleLoop") << "simpleLoop.js" + << "simpleLoop.formatted.js"; + QTest::newRow("messyIfStatement") << "messyIfStatement.js" + << "messyIfStatement.formatted.js"; + QTest::newRow("lambdaFunctionWithLoop") << "lambdaFunctionWithLoop.js" + << "lambdaFunctionWithLoop.formatted.js"; + QTest::newRow("lambdaWithIfElse") << "lambdaWithIfElse.js" + << "lambdaWithIfElse.formatted.js"; + QTest::newRow("nestedLambdaWithIfElse") << "lambdaWithIfElseInsideLambda.js" + << "lambdaWithIfElseInsideLambda.formatted.js"; + QTest::newRow("twoFunctions") << "twoFunctions.js" + << "twoFunctions.formatted.js"; + QTest::newRow("pragma") << "pragma.js" + << "pragma.formatted.js"; + QTest::newRow("classConstructor") << "class.js" + << "class.formatted.js"; + QTest::newRow("legacyDirectives") << "directives.js" + << "directives.formatted.js"; + QTest::newRow("legacyDirectivesWithComments") << "directivesWithComments.js" + << "directivesWithComments.formatted.js"; +} + +void TestQmlformat::plainJS() +{ + QFETCH(QString, file); + QFETCH(QString, fileFormatted); + + bool wasSuccessful; + LineWriterOptions opts; +#ifdef Q_OS_WIN + opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows; +#endif + QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None); + + QVERIFY(wasSuccessful && !output.isEmpty()); + + // TODO(QTBUG-119404) + QEXPECT_FAIL("classConstructor", "see QTBUG-119404", Abort); + // TODO(QTBUG-119770) + QEXPECT_FAIL("legacyDirectivesWithComments", "see QTBUG-119770", Abort); + auto exp = readTestFile(fileFormatted); + QCOMPARE(output, exp); +} + +void TestQmlformat::ecmascriptModule() +{ + QString file("esm.mjs"); + QString formattedFile("esm.formatted.mjs"); + + bool wasSuccessful; + LineWriterOptions opts; +#ifdef Q_OS_WIN + opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows; +#endif + QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None); + + QVERIFY(wasSuccessful && !output.isEmpty()); + + auto exp = readTestFile(formattedFile); + QCOMPARE(output, readTestFile(formattedFile)); } #if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void TestQmlformat::testExample_data() { + if (QTestPrivate::isRunningArmOnX86()) + QSKIP("Crashes in QEMU. (timeout)"); QTest::addColumn<QString>("file"); QString examples = QLatin1String(SRCDIR) + "/../../../../examples/"; QString tests = QLatin1String(SRCDIR) + "/../../../../tests/"; + QStringList exampleFiles; + QStringList testFiles; QStringList files; - files << findFiles(QDir(examples)); - files << findFiles(QDir(tests)); + exampleFiles << findFiles(QDir(examples)); + testFiles << findFiles(QDir(tests)); + + // Actually this test is an e2e test and not the unit test. + // At the moment of writing, CI lacks providing instruments for the automated tests + // which might be time-consuming, as for example this one. + // Therefore as part of QTBUG-122990 this test was copied to the /manual/e2e/qml/qmlformat + // however very small fraction of the test data is still preserved here for the sake of + // testing automatically at least a small part of the examples + const int nBatch = 10; + files << exampleFiles.mid(0, nBatch) << exampleFiles.mid(exampleFiles.size() / 2, nBatch) + << exampleFiles.mid(exampleFiles.size() - nBatch, nBatch); + files << testFiles.mid(0, nBatch) << testFiles.mid(exampleFiles.size() / 2, nBatch) + << testFiles.mid(exampleFiles.size() - nBatch, nBatch); + + for (const QString &file : files) + QTest::newRow(qPrintable(file)) << file; +} + +void TestQmlformat::normalizeExample_data() +{ + if (QTestPrivate::isRunningArmOnX86()) + QSKIP("Crashes in QEMU. (timeout)"); + QTest::addColumn<QString>("file"); + + QString examples = QLatin1String(SRCDIR) + "/../../../../examples/"; + QString tests = QLatin1String(SRCDIR) + "/../../../../tests/"; + + // normalizeExample is similar to testExample, so we test it only on nExamples + nTests + // files to avoid making too many + QStringList files; + const int nExamples = 10; + int i = 0; + for (const auto &f : findFiles(QDir(examples))) { + files << f; + if (++i == nExamples) + break; + } + const int nTests = 10; + i = 0; + for (const auto &f : findFiles(QDir(tests))) { + files << f; + if (++i == nTests) + break; + } for (const QString &file : files) QTest::newRow(qPrintable(file)) << file; @@ -276,26 +568,138 @@ void TestQmlformat::testExample() { QFETCH(QString, file); const bool isInvalid = isInvalidFile(QFileInfo(file)); - QString output = runQmlformat(file, {}, !isInvalid); + bool wasSuccessful; + LineWriterOptions opts; + opts.attributesSequence = LineWriterOptions::AttributesSequence::Preserve; + QString output = formatInMemory(file, &wasSuccessful, opts); + + if (!isInvalid) + QVERIFY(wasSuccessful && !output.isEmpty()); +} + +void TestQmlformat::normalizeExample() +{ + QFETCH(QString, file); + const bool isInvalid = isInvalidFile(QFileInfo(file)); + bool wasSuccessful; + LineWriterOptions opts; + opts.attributesSequence = LineWriterOptions::AttributesSequence::Normalize; + QString output = formatInMemory(file, &wasSuccessful, opts); if (!isInvalid) - QVERIFY(!output.isEmpty()); + QVERIFY(wasSuccessful && !output.isEmpty()); } #endif +void TestQmlformat::testBackupFileLimit() +{ + // Create a temporary directory + QTemporaryDir tempDir; + + // Unformatted file to format + const QString fileToFormat{ testFile("Annotations.qml") }; + + { + const QString tempFile = tempDir.path() + QDir::separator() + "test_0.qml"; + const QString backupFile = tempFile + QStringLiteral("~"); + QFile::copy(fileToFormat, tempFile); + + QProcess process; + process.start(m_qmlformatPath, QStringList{ "--verbose", "--inplace", tempFile }); + QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); + QVERIFY(QFileInfo::exists(tempFile)); + QVERIFY(!QFileInfo::exists(backupFile)); + }; +} + +void TestQmlformat::testFilesOption_data() +{ + QTest::addColumn<QString>("containerFile"); + QTest::addColumn<QStringList>("individualFiles"); + + QTest::newRow("initial") << "fileListToFormat" + << QStringList{"valid1.qml", "invalidEntry:cannot be parsed", "valid2.qml"}; +} + +void TestQmlformat::testFilesOption() +{ + QFETCH(QString, containerFile); + QFETCH(QStringList, individualFiles); + + // Create a temporary directory + QTemporaryDir tempDir; + tempDir.setAutoRemove(false); + QStringList actualFormattedFilesPath; + + // Iterate through files in the source directory and copy them to the temporary directory + const auto sourceDir = dataDirectory() + QDir::separator() + "filesOption"; + + // Create a file that contains the list of files to be formatted + const QString tempFilePath = tempDir.path() + QDir::separator() + containerFile; + QFile container(tempFilePath); + if (container.open(QIODevice::Text | QIODevice::WriteOnly)) { + QTextStream out(&container); + + for (const auto &file : individualFiles) { + QString destinationFilePath = tempDir.path() + QDir::separator() + file; + if (QFile::copy(sourceDir + QDir::separator() + file, destinationFilePath)) + actualFormattedFilesPath << destinationFilePath; + out << destinationFilePath << "\n"; + } + + container.close(); + } else { + QFAIL("Cannot create temp test file\n"); + return; + } + + { + QProcess process; + process.start(m_qmlformatPath, QStringList{"-F", tempFilePath}); + QVERIFY(process.waitForFinished()); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + } + + const auto readFile = [](const QString &filePath){ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Error on opening the file " << filePath; + return QByteArray{}; + } + + return file.readAll(); + }; + + for (const auto &filePath : actualFormattedFilesPath) { + auto expectedFormattedFile = QFileInfo(filePath).fileName(); + const auto expectedFormattedFilePath = sourceDir + QDir::separator() + + expectedFormattedFile.replace(".qml", ".formatted.qml"); + + QCOMPARE(readFile(filePath), readFile(expectedFormattedFilePath)); + } +} + QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList args, - bool shouldSucceed) + bool shouldSucceed, RunOption rOptions, QStringView ext) { // Copy test file to temporary location QTemporaryDir tempDir; - const QString tempFile = tempDir.path() + QDir::separator() + "to_format.qml"; - QFile::copy(fileToFormat, tempFile); - - args << QLatin1String("-i"); - args << tempFile; + const QString tempFile = (tempDir.path() + QDir::separator() + "to_format") % ext; + + if (rOptions == RunOption::OnCopy) { + QFile::copy(fileToFormat, tempFile); + args << QLatin1String("-i"); + args << tempFile; + } else { + args << fileToFormat; + } auto verify = [&]() { QProcess process; + if (rOptions == RunOption::OrigToCopy) + process.setStandardOutputFile(tempFile); process.start(m_qmlformatPath, args); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); @@ -306,11 +710,48 @@ QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList arg QFile temp(tempFile); - temp.open(QIODevice::ReadOnly); + if (!temp.open(QIODevice::ReadOnly)) + qFatal("Could not open %s", qPrintable(tempFile)); QString formatted = QString::fromUtf8(temp.readAll()); return formatted; } +QString TestQmlformat::formatInMemory(const QString &fileToFormat, bool *didSucceed, + LineWriterOptions options, WriteOutChecks extraChecks, + WriteOutChecks largeChecks) +{ + auto env = DomEnvironment::create( + QStringList(), // as we load no dependencies we do not need any paths + QQmlJS::Dom::DomEnvironment::Option::SingleThreaded + | QQmlJS::Dom::DomEnvironment::Option::NoDependencies); + DomItem tFile; + env->loadFile(FileToLoad::fromFileSystem(env, fileToFormat), + [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; }); + env->loadPendingDependencies(); + MutableDomItem myFile = tFile.field(Fields::currentItem); + + bool writtenOut; + QString resultStr; + if (myFile.field(Fields::isValid).value().toBool()) { + WriteOutChecks checks = extraChecks; + const qsizetype largeFileSize = 32000; + if (tFile.field(Fields::code).value().toString().size() > largeFileSize) + checks = largeChecks; + + 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); + writtenOut = qmlFile.writeOutForFile(ow, checks); + lw.eof(); + res.flush(); + } + if (didSucceed) + *didSucceed = writtenOut; + return resultStr; +} + QTEST_MAIN(TestQmlformat) #include "tst_qmlformat.moc" |