diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-02-17 01:01:00 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-02-17 10:21:59 +0100 |
commit | 3e758800b4daf8fbc870a2ff5d54fce9d4402ce8 (patch) | |
tree | ba237b9da1c7dfd08bf13e71c5dbd6b3c2e77633 /tests/auto | |
parent | 925a0e499a5dbdb180fd9969a79abf96006ce4fd (diff) | |
parent | 55546991e24ca6799709cbe0171b9ab87216c35f (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
src/imports/qtqml/plugin.cpp
src/qml/qml/qqml.h
src/qml/qml/qqmlmetatype.cpp
src/qml/qml/qqmlmetatype_p.h
src/qml/qml/qqmltypeloader.cpp
src/qml/types/qqmlbind.cpp
src/quick/items/qquickitemsmodule.cpp
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
Change-Id: I52548938a582cb6510271ed4bc3a9aa0c3c11df6
Diffstat (limited to 'tests/auto')
43 files changed, 3327 insertions, 79 deletions
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro index 5c328fbfcc..890e722aa3 100644 --- a/tests/auto/qml/debugger/debugger.pro +++ b/tests/auto/qml/debugger/debugger.pro @@ -4,6 +4,7 @@ SUBDIRS += qqmldebugjsserver PUBLICTESTS += \ qdebugmessageservice \ + qqmldebugtranslationservice \ qqmlenginedebugservice \ qqmldebugjs \ qqmlinspector \ diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml index deba24cf91..a7231df48b 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml +++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml @@ -36,5 +36,9 @@ Item { } id: root property int a: 10 + + Item { + property int b: 11 + } } diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 3f424d16f2..91470e0651 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -896,6 +896,16 @@ void tst_QQmlDebugJS::evaluateInContext() QVERIFY(waitForClientSignal(SIGNAL(result()))); QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 20); + + auto childObjects = object.children; + QVERIFY(childObjects.count() > 0); // QQmlComponentAttached is also in there + QCOMPARE(childObjects[0].className, QString::fromLatin1("Item")); + + // "b" accessible in context of surrounding (child) object + m_client->evaluate(QLatin1String("b"), -1, childObjects[0].debugId); + QVERIFY(waitForClientSignal(SIGNAL(result()))); + + QTRY_COMPARE(responseBody(m_client).value("value").toInt(), 11); } void tst_QQmlDebugJS::getScripts() diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml new file mode 100644 index 0000000000..234496577a --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 2.12 + +Item { + width: 360 + height: 360 + + Text { + text: qsTr("hello") + width: parent.width / 10 + elide: Text.ElideRight + } +} diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro new file mode 100644 index 0000000000..32e60e306d --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/qqmldebugtranslationservice.pro @@ -0,0 +1,12 @@ +CONFIG += testcase +TARGET = tst_qdebugtranslationservice +QT += network testlib gui-private core-private qmldebug-private +macos:CONFIG -= app_bundle + +SOURCES += tst_qqmldebugtranslationservice.cpp + +include(../shared/debugutil.pri) + +TESTDATA = data/* + +OTHER_FILES += data/test.qml diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp new file mode 100644 index 0000000000..01ee805dee --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +//QQmlDebugTest +#include <debugutil_p.h> +#include <qqmldebugprocess_p.h> + +#include <private/qqmldebugclient_p.h> +#include <private/qqmldebugtranslationclient_p.h> +#include <private/qqmldebugconnection_p.h> +#include <private/qpacket_p.h> + +#include <QtCore/qstring.h> +#include <QtCore/qlibraryinfo.h> +#include <QtTest/qtest.h> + +const char *QMLFILE = "test.qml"; + +class tst_QQmlDebugTranslationService : public QQmlDebugTest +{ + Q_OBJECT + +private slots: + void pluginConnection(); + +private: + QList<QQmlDebugClient *> createClients() override; + QPointer<QQmlDebugTranslationClient> m_client; +}; + +QList<QQmlDebugClient *> tst_QQmlDebugTranslationService::createClients() +{ + m_client = new QQmlDebugTranslationClient(m_connection); + + QObject::connect(m_client, &QQmlDebugClient::stateChanged, m_client, [this](QQmlDebugClient::State newState) { + QCOMPARE(newState, m_client->state()); + }); + + return {m_client}; +} + +void tst_QQmlDebugTranslationService::pluginConnection() +{ + auto executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml"; + auto services = "DebugTranslation"; + auto extraArgs = testFile(QMLFILE); + auto block = true; + + auto result = QQmlDebugTest::connectTo(executable, services, extraArgs, block); + QCOMPARE(result, ConnectSuccess); +} + +QTEST_MAIN(tst_QQmlDebugTranslationService) + +#include "tst_qqmldebugtranslationservice.moc" diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index d6e85f973f..b561e5f398 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1128,6 +1128,10 @@ void tst_QJSValue::toVariant() // array { + auto handler = qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &, const QString &) { + if (type == QtMsgType::QtWarningMsg) + QFAIL("Converting QJSValue to QVariant should not cause error messages"); + }); QVariantList listIn; listIn << 123 << "hello"; QJSValue array = eng.toScriptValue(listIn); @@ -1145,8 +1149,9 @@ void tst_QJSValue::toVariant() QCOMPARE(array2.property("length").toInt(), array.property("length").toInt()); for (int i = 0; i < array.property("length").toInt(); ++i) QVERIFY(array2.property(i).strictlyEquals(array.property(i))); - } + qInstallMessageHandler(handler); + } } void tst_QJSValue::toQObject_nonQObject_data() diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml new file mode 100644 index 0000000000..a05c2125dc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.nosort.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + +@Pippo { + atg1: 3 +} +@Annotation2 { +} +Item { + //![1] + + @AnnotateMore { + property int x: 5 + } + @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() + } + PieSeries { + id: pieSeries + + 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 + } + + } + + } + +} diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml new file mode 100644 index 0000000000..a142d4cb74 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +//![2] +import QtCharts 2.0 +//![2] +import QtQuick 2.0 + +@Pippo { + atg1: 3 +} +@Annotation2 { +} +Item { + //![1] + + @AnnotateMore { + property int x: 5 + } + @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() + } + PieSeries { + id: pieSeries + + 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 + } + + } + + } + +} diff --git a/tests/auto/qml/qmlformat/data/Annotations.qml b/tests/auto/qml/qmlformat/data/Annotations.qml new file mode 100644 index 0000000000..2d3d7d2cfd --- /dev/null +++ b/tests/auto/qml/qmlformat/data/Annotations.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +//![2] +import QtQuick 2.0 +//![2] +import QtCharts 2.0 + +@Pippo{ atg1:3 } +@Annotation2{} +Item { + @Annotate{} + anchors.fill: parent + @AnnotateMore{ + property int x: 5 + } + @AnnotateALot{} + property variant othersSlice: 0 + + //![1] + ChartView { + id: chart + title: "Top-5 car brand shares in Finland" + anchors.fill: parent + legend.alignment: Qt.AlignBottom + antialiasing: true + +@ExtraAnnotation{ + signal pippo +} + PieSeries { + id: pieSeries + 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 } + } + } + +@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/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index c7714304b8..21d5ae46a9 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -41,6 +41,8 @@ private Q_SLOTS: void testFormat(); void testFormatNoSort(); + void testAnnotations(); + void testAnnotationsNoSort(); void testReadOnlyProps(); void testStatesAndTransitions(); @@ -185,6 +187,16 @@ void TestQmlformat::testFormatNoSort() QCOMPARE(runQmlformat(testFile("Example1.qml"), false, true), readTestFile("Example1.formatted.nosort.qml")); } +void TestQmlformat::testAnnotations() +{ + QCOMPARE(runQmlformat(testFile("Annotations.qml"), true, true), readTestFile("Annotations.formatted.qml")); +} + +void TestQmlformat::testAnnotationsNoSort() +{ + QCOMPARE(runQmlformat(testFile("Annotations.qml"), false, true), readTestFile("Annotations.formatted.nosort.qml")); +} + void TestQmlformat::testReadOnlyProps() { QCOMPARE(runQmlformat(testFile("readOnlyProps.qml"), false, true), readTestFile("readOnlyProps.formatted.qml")); diff --git a/tests/auto/qml/qqmlconnections/data/underscore.qml b/tests/auto/qml/qqmlconnections/data/underscore.qml new file mode 100644 index 0000000000..0f73dc8f17 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/underscore.qml @@ -0,0 +1,14 @@ +import QtQuick 2.12 + +Item { + id: item + property bool success: false + property bool sanityCheck: false + property int __underscore_property: 0 + on__Underscore_propertyChanged: item.sanityCheck = true + + Connections { + target: item + on__Underscore_propertyChanged: item.success = true + } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index 07af519a3d..f144002875 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -77,6 +77,8 @@ private slots: void noAcceleratedGlobalLookup_data() { prefixes(); } void noAcceleratedGlobalLookup(); + void bindToPropertyWithUnderscoreChangeHandler(); + private: QQmlEngine engine; void prefixes(); @@ -474,6 +476,19 @@ void tst_qqmlconnections::noAcceleratedGlobalLookup() QCOMPARE(val.toInt(), int(Proxy::EnumValue)); } +void tst_qqmlconnections::bindToPropertyWithUnderscoreChangeHandler() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("underscore.qml")); + QScopedPointer<QObject> root {component.create()}; + QVERIFY(root); + QQmlProperty underscoreProperty(root.get(), "__underscore_property"); + QVERIFY(underscoreProperty.isValid()); + underscoreProperty.write(42); + QVERIFY(root->property("sanityCheck").toBool()); + QVERIFY(root->property("success").toBool()); +} + QTEST_MAIN(tst_qqmlconnections) #include "tst_qqmlconnections.moc" diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml index 75beafd1ee..c2c8c1b52b 100644 --- a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml +++ b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.write.error.qml @@ -12,7 +12,7 @@ Item { function performTest() { // we have NOT registered QList<QPoint> as a type - var pointList = [ Qt.point(7,7), Qt.point(8,8), Qt.point(9,9) ]; + var pointList = [ Qt.point(7,7), "hello world", Qt.point(8,8), Qt.point(9,9) ]; msco.pointListProperty = pointList; // error. } } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index a05933d071..61dc393998 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -74,6 +74,7 @@ public: private slots: void initTestCase(); + void arrayIncludesValueType(); void assignBasicTypes(); void assignDate_data(); void assignDate(); @@ -414,6 +415,36 @@ void tst_qqmlecmascript::initTestCase() registerTypes(); } +void tst_qqmlecmascript::arrayIncludesValueType() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + // It is vital that QtQuick is imported below else we get a warning about + // QQml_colorProvider and tst_qqmlecmascript::signalParameterTypes fails due + // to some static variable being initialized with the wrong value + component.setData(R"( + import QtQuick 2.15 + import QtQml 2.15 + QtObject { + id: root + property color r: Qt.rgba(1, 0, 0) + property color g: Qt.rgba(0, 1, 0) + property color b: Qt.rgba(0, 0, 1) + property var colors: [r, g, b] + property bool success: false + + Component.onCompleted: { + root.success = root.colors.includes(root.g) + } + } + )", QUrl("testData")); + QScopedPointer<QObject> o(component.create()); + QVERIFY(o); + auto success = o->property("success"); + QVERIFY(success.isValid()); + QVERIFY(success.toBool()); +} + void tst_qqmlecmascript::assignBasicTypes() { QQmlEngine engine; @@ -5792,13 +5823,12 @@ void tst_qqmlecmascript::sequenceConversionWrite() MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); QVERIFY(seq != nullptr); - // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work. - QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to QVector<QPoint>"); - QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData()); - + // Behavior change in 5.14: due to added auto-magical conversions, it is possible to assign to + // QList<QPoint>, even though it is not a registered sequence type + QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression("Could not convert array value at position 1 from QString to QPoint")); QMetaObject::invokeMethod(object, "performTest"); - QList<QPoint> pointList; pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); // original values, shouldn't have changed + QList<QPoint> pointList; pointList << QPoint(7, 7) << QPoint(0,0) << QPoint(8, 8) << QPoint(9, 9); // original values, shouldn't have changed QCOMPARE(seq->pointListProperty(), pointList); delete object; diff --git a/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml new file mode 100644 index 0000000000..4bb8dfb486 --- /dev/null +++ b/tests/auto/qml/qqmlenginecleanup/data/MyItem.qml @@ -0,0 +1,2 @@ +import QtQuick 2.12 +Item {} diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp index 0e70933ec6..26b2b839ea 100644 --- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp +++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp @@ -45,6 +45,7 @@ private slots: void test_qmlClearTypeRegistrations(); void test_valueTypeProviderModule(); // QTBUG-43004 void test_customModuleCleanup(); + void test_qmlListCleared(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -187,6 +188,18 @@ void tst_qqmlenginecleanup::test_customModuleCleanup() } } +void tst_qqmlenginecleanup::test_qmlListCleared() +{ + { + QQmlEngine engine; + auto url = testFileUrl("MyItem.qml"); + QQmlComponent comp(&engine, url); + QScopedPointer<QObject> item {comp.create()}; + QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 1); + } + QCOMPARE(QQmlMetaType::qmlRegisteredListTypeCount(), 0); +} + QTEST_MAIN(tst_qqmlenginecleanup) #include "tst_qqmlenginecleanup.moc" diff --git a/tests/auto/qml/qqmllanguage/data/SimpleItem.qml b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml new file mode 100644 index 0000000000..c7bce2bc78 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + property int i: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml new file mode 100644 index 0000000000..ee400eb41f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml @@ -0,0 +1,7 @@ +import QtQml 2.14 +import qt.test 1.0 + +TestItem { + property var vector + positions: vector +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml new file mode 100644 index 0000000000..ab125e9323 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml @@ -0,0 +1,17 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + width: i + Rectangle { + id: rect + color: "lime" + } + property alias color: rect.color + } + width: 200 + IC { + objectName: "icInstance" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml new file mode 100644 index 0000000000..c4093bad2f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml @@ -0,0 +1,14 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + id: root + width: root.i + property color color: "red" + } + width: 200 + IC { + objectName: "icInstance" + } +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 39502372e6..148179cb9c 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1440,17 +1440,22 @@ public: int base() const { return 43; } }; +class Local : public QObject +{ + Q_OBJECT +}; + class Foreign { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(Foreign) }; class ForeignExtended { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(ForeignExtended) QML_EXTENDED(Extension) }; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 1e382d7ee2..d4760fa7e9 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -325,6 +325,9 @@ private slots: void overrideSingleton(); void revisionedPropertyOfAttachedObjectProperty(); + void arrayToContainer(); + void qualifiedScopeInCustomParser(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -5627,6 +5630,9 @@ void tst_qqmllanguage::inlineComponent_data() QTest::newRow("Non-toplevel IC is found") << testFileUrl("inlineComponentUser5.qml") << QColorConstants::Svg::red << 24; QTest::newRow("Resolved in correct order") << testFileUrl("inlineComponentOrder.qml") << QColorConstants::Blue << 200; + + QTest::newRow("ID resolves correctly") << testFileUrl("inlineComponentWithId.qml") << QColorConstants::Svg::red << 42; + QTest::newRow("Alias resolves correctly") << testFileUrl("inlineComponentWithAlias.qml") << QColorConstants::Svg::lime << 42; } void tst_qqmllanguage::inlineComponentReferenceCycle_data() @@ -5717,6 +5723,60 @@ void tst_qqmllanguage::nonExistingInlineComponent() QCOMPARE(error.column(), column); } +class TestItem : public QObject +{ + Q_OBJECT + Q_PROPERTY( QVector<QPointF> positions MEMBER m_points ) + +public: + TestItem() = default; + QVector< QPointF > m_points; +}; + + +Q_DECLARE_METATYPE(QVector<QPointF>); +void tst_qqmllanguage::arrayToContainer() +{ + QQmlEngine engine; + qmlRegisterType<TestItem>("qt.test", 1, 0, "TestItem"); + QVector<QPointF> points { QPointF (2.0, 3.0) }; + engine.rootContext()->setContextProperty("test", QVariant::fromValue(points)); + QQmlComponent component(&engine, testFileUrl("arrayToContainer.qml")); + VERIFY_ERRORS(0); + QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}} ))); + QVERIFY(root); + QCOMPARE(root->m_points.at(0), QPointF (2.0, 3.0) ); +} + +class EnumTester : public QObject +{ + Q_OBJECT +public: + enum Types + { + FIRST = 0, + SECOND, + THIRD + }; + Q_ENUM(Types) +}; + +void tst_qqmllanguage::qualifiedScopeInCustomParser() +{ + qmlRegisterUncreatableType<EnumTester>("scoped.custom.test", 1, 0, "EnumTester", + "Object only creatable in C++"); + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQml.Models 2.12\n" + "import scoped.custom.test 1.0 as BACKEND\n" + "ListModel {\n" + " ListElement { text: \"a\"; type: BACKEND.EnumTester.FIRST }\n" + "}\n", QUrl()); + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlparser/qqmlparser.pro b/tests/auto/qml/qqmlparser/qqmlparser.pro index d8e4b0dd06..7f117b3157 100644 --- a/tests/auto/qml/qqmlparser/qqmlparser.pro +++ b/tests/auto/qml/qqmlparser/qqmlparser.pro @@ -11,3 +11,4 @@ cross_compile: DEFINES += QTEST_CROSS_COMPILED TESTDATA = data/* include (../../shared/util.pri) +include (../../shared/astdump.pri) diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp index 981fe7407e..8483bd1f95 100644 --- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp +++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp @@ -33,6 +33,7 @@ #include <private/qqmljsast_p.h> #include "../../shared/util.h" +#include "../../shared/qqmljsastdumper.h" #include <qtest.h> #include <QDir> @@ -583,7 +584,7 @@ void tst_qqmlparser::annotations() Parser parser2(&engine2); QVERIFY(parser2.parse()); - // to do: compare for equality skipping annotations + QCOMPARE(AstDumper::diff(parser.ast(), parser2.rootNode(), 3, DumperOptions::NoAnnotations | DumperOptions::NoLocations), QString()); } } diff --git a/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml new file mode 100644 index 0000000000..e7c5dc7344 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/interfaceBinding2.qml @@ -0,0 +1,27 @@ +import QtQuick 2.12 +import io.qt.bugreports 2.0 +Item { + InterfaceConsumer2 { + objectName: "a1" + i: A2 { + property int i: 42 + } + } + + InterfaceConsumer2 { + objectName: "a2" + property A2 a: A2 { + property int i: 43 + } + i: a + } + + InterfaceConsumer2 { + objectName: "a3" + property A2 a: A2 { + id : aa + property int i: 44 + } + i: aa + } +} diff --git a/tests/auto/qml/qqmlproperty/interfaces.h b/tests/auto/qml/qqmlproperty/interfaces.h new file mode 100644 index 0000000000..2c06c5f594 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/interfaces.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +#ifndef INTERFACES_H +#define INTERFACES_H + +#include <QtQml/qqml.h> + +struct Interface { +}; + +QT_BEGIN_NAMESPACE +#define MyInterface_iid "io.qt.bugreports.Interface" +Q_DECLARE_INTERFACE(Interface, MyInterface_iid); +QT_END_NAMESPACE + +class A : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class B : public QObject, Interface { + Q_OBJECT + Q_INTERFACES(Interface) +}; + +class C : public QObject { + Q_OBJECT +}; + +struct Interface2 +{ + Q_GADGET + QML_INTERFACE +}; + +QT_BEGIN_NAMESPACE +#define MyInterface2_iid "io.qt.bugreports.Interface2" +Q_DECLARE_INTERFACE(Interface2, MyInterface2_iid); +QT_END_NAMESPACE + +class A2 : public QObject, Interface2 { + Q_OBJECT + QML_ELEMENT + Q_INTERFACES(Interface2) +}; + +class B2 : public QObject, Interface2 { + Q_OBJECT + QML_ELEMENT + Q_INTERFACES(Interface2) +}; + +class C2 : public QObject { + Q_OBJECT + QML_ELEMENT +}; + +class InterfaceConsumer : public QObject { + Q_OBJECT + Q_PROPERTY(Interface *i READ interface WRITE setInterface NOTIFY interfaceChanged) + Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) + +public: + + Interface* interface() const + { + return m_interface; + } + void setInterface(Interface* interface) + { + QObject* object = reinterpret_cast<QObject*>(interface); + m_testValue = object->property("i").toInt(); + emit testValueChanged(); + if (m_interface == interface) + return; + + m_interface = interface; + emit interfaceChanged(); + } + + int testValue() { + return m_testValue; + } + +signals: + void interfaceChanged(); + void testValueChanged(); + +private: + Interface* m_interface = nullptr; + int m_testValue = 0; +}; + + +class InterfaceConsumer2 : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Interface2 *i READ interface WRITE setInterface NOTIFY interfaceChanged) + Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) + + QML_ELEMENT + +public: + + Interface2* interface() const + { + return m_interface; + } + void setInterface(Interface2* interface2) + { + QObject* object = reinterpret_cast<QObject*>(interface2); + m_testValue = object->property("i").toInt(); + emit testValueChanged(); + if (m_interface == interface2) + return; + + m_interface = interface2; + emit interfaceChanged(); + } + + int testValue() { + return m_testValue; + } + +signals: + void interfaceChanged(); + void testValueChanged(); + +private: + Interface2 *m_interface = nullptr; + int m_testValue = 0; +}; + +#endif // INTERFACES_H diff --git a/tests/auto/qml/qqmlproperty/qqmlproperty.pro b/tests/auto/qml/qqmlproperty/qqmlproperty.pro index b1bcf1f17d..4d42975369 100644 --- a/tests/auto/qml/qqmlproperty/qqmlproperty.pro +++ b/tests/auto/qml/qqmlproperty/qqmlproperty.pro @@ -1,7 +1,10 @@ -CONFIG += testcase +CONFIG += testcase qmltypes TARGET = tst_qqmlproperty macx:CONFIG -= app_bundle +QML_IMPORT_NAME = io.qt.bugreports +QML_IMPORT_VERSION = 2.0 + SOURCES += tst_qqmlproperty.cpp include (../../shared/util.pri) @@ -9,3 +12,6 @@ include (../../shared/util.pri) TESTDATA = data/* QT += core-private gui-private qml-private testlib + +HEADERS += \ + interfaces.h diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 83e173f379..8a96fc52c5 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -25,6 +25,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "interfaces.h" #include <qtest.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -160,6 +162,8 @@ private slots: void bindingToAlias(); void nestedQQmlPropertyMap(); + + void underscorePropertyChangeHandler(); private: QQmlEngine engine; }; @@ -2090,74 +2094,20 @@ void tst_qqmlproperty::nullPropertyBinding() QMetaObject::invokeMethod(root.get(), "tog"); } -struct Interface { -}; - -QT_BEGIN_NAMESPACE -#define MyInterface_iid "io.qt.bugreports.Interface" -Q_DECLARE_INTERFACE(Interface, MyInterface_iid); -QT_END_NAMESPACE - -class A : public QObject, Interface { - Q_OBJECT - Q_INTERFACES(Interface) -}; - -class B : public QObject, Interface { - Q_OBJECT - Q_INTERFACES(Interface) -}; - -class C : public QObject { - Q_OBJECT -}; - -class InterfaceConsumer : public QObject { - Q_OBJECT - Q_PROPERTY(Interface* i READ interface WRITE setInterface NOTIFY interfaceChanged) - Q_PROPERTY(int testValue READ testValue NOTIFY testValueChanged) - - -public: - - Interface* interface() const - { - return m_interface; - } - void setInterface(Interface* interface) - { - QObject* object = reinterpret_cast<QObject*>(interface); - m_testValue = object->property("i").toInt(); - emit testValueChanged(); - if (m_interface == interface) - return; - - m_interface = interface; - emit interfaceChanged(); - } - - int testValue() { - return m_testValue; - } - -signals: - void interfaceChanged(); - void testValueChanged(); - -private: - Interface* m_interface = nullptr; - int m_testValue = 0; -}; void tst_qqmlproperty::interfaceBinding() { - - qmlRegisterInterface<Interface>("Interface"); - qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A"); - qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B"); - qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C"); - qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer"); - - const QUrl url = testFileUrl("interfaceBinding.qml"); + qmlRegisterInterface<Interface>("Interface"); + qmlRegisterType<A>("io.qt.bugreports", 1, 0, "A"); + qmlRegisterType<B>("io.qt.bugreports", 1, 0, "B"); + qmlRegisterType<C>("io.qt.bugreports", 1, 0, "C"); + qmlRegisterType<InterfaceConsumer>("io.qt.bugreports", 1, 0, "InterfaceConsumer"); + + const QVector<QUrl> urls = { + testFileUrl("interfaceBinding.qml"), + testFileUrl("interfaceBinding2.qml") + }; + + for (const QUrl &url : urls) { QQmlEngine engine; QQmlComponent component(&engine, url); QScopedPointer<QObject> root(component.create()); @@ -2165,6 +2115,7 @@ void tst_qqmlproperty::interfaceBinding() QCOMPARE(root->findChild<QObject*>("a1")->property("testValue").toInt(), 42); QCOMPARE(root->findChild<QObject*>("a2")->property("testValue").toInt(), 43); QCOMPARE(root->findChild<QObject*>("a3")->property("testValue").toInt(), 44); + } } void tst_qqmlproperty::floatToStringPrecision_data() @@ -2241,6 +2192,24 @@ void tst_qqmlproperty::nestedQQmlPropertyMap() QCOMPARE(success.read().toString(), QLatin1String("success")); } +void tst_qqmlproperty::underscorePropertyChangeHandler() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(R"( + import QtQuick 2.12 + + Item { + property int __withUnderScore + } + )", QUrl::fromLocalFile(".")); + QScopedPointer<QObject> root { component.create() }; + QVERIFY(root); + QQmlProperty changeHandler(root.get(), "on__WithUnderScoreChanged"); + QVERIFY(changeHandler.isValid()); + QVERIFY(changeHandler.isSignalProperty()); +} + QTEST_MAIN(tst_qqmlproperty) #include "tst_qqmlproperty.moc" diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp index d0b3bc3d36..ca6463f365 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp @@ -55,6 +55,7 @@ private slots: void initTestCase(); void singleTouch(); + void tabletStylus(); void simultaneousMultiTouch(); void pressedMultipleButtons_data(); void pressedMultipleButtons(); @@ -136,6 +137,65 @@ void tst_PointHandler::singleTouch() QCOMPARE(translationSpy.count(), 3); } +void tst_PointHandler::tabletStylus() +{ + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents, false); + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "pointTracker.qml"); + QQuickView * window = windowPtr.data(); + QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler"); + QVERIFY(handler); + handler->setAcceptedDevices(QQuickPointerDevice::Stylus); + + QSignalSpy activeSpy(handler, SIGNAL(activeChanged())); + QSignalSpy pointSpy(handler, SIGNAL(pointChanged())); + QSignalSpy translationSpy(handler, SIGNAL(translationChanged())); + + QPoint point(100,100); + const qint64 stylusId = 1234567890; + + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.5, 25, 35, 0.6, 12.3, 3, stylusId, Qt::NoModifier); + QTRY_COMPARE(handler->active(), true); + QCOMPARE(activeSpy.count(), 1); + QCOMPARE(pointSpy.count(), 1); + QCOMPARE(handler->point().position().toPoint(), point); + QCOMPARE(handler->point().scenePosition().toPoint(), point); + QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton); + QCOMPARE(handler->point().pressure(), 0.5); + QCOMPARE(handler->point().rotation(), 12.3); + QCOMPARE(handler->point().uniqueId().numericId(), stylusId); + QCOMPARE(handler->translation(), QVector2D()); + QCOMPARE(translationSpy.count(), 1); + + point += QPoint(10, 10); + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::LeftButton, 0.45, 23, 33, 0.57, 15.6, 3.4, stylusId, Qt::NoModifier); + QTRY_COMPARE(pointSpy.count(), 2); + QCOMPARE(handler->active(), true); + QCOMPARE(activeSpy.count(), 1); + QCOMPARE(handler->point().position().toPoint(), point); + QCOMPARE(handler->point().scenePosition().toPoint(), point); + QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100)); + QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100)); + QCOMPARE(handler->point().pressedButtons(), Qt::LeftButton); + QCOMPARE(handler->point().pressure(), 0.45); + QCOMPARE(handler->point().rotation(), 15.6); + QCOMPARE(handler->point().uniqueId().numericId(), stylusId); + QVERIFY(handler->point().velocity().x() > 0); + QVERIFY(handler->point().velocity().y() > 0); + QCOMPARE(handler->translation(), QVector2D(10, 10)); + QCOMPARE(translationSpy.count(), 2); + + QWindowSystemInterface::handleTabletEvent(window, point, window->mapToGlobal(point), + QTabletEvent::Stylus, QTabletEvent::Pen, Qt::NoButton, 0, 0, 0, 0, 0, 0, stylusId, Qt::NoModifier); + QTRY_COMPARE(handler->active(), false); + QCOMPARE(activeSpy.count(), 2); + QCOMPARE(pointSpy.count(), 3); + QCOMPARE(handler->translation(), QVector2D()); + QCOMPARE(translationSpy.count(), 3); +} + void tst_PointHandler::simultaneousMultiTouch() { QScopedPointer<QQuickView> windowPtr; diff --git a/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml new file mode 100644 index 0000000000..6f7bc89793 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/visibleAreaBinding.qml @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +import QtQuick 2.14 + +Flickable { + id: flickable + // Deliberately has no size set. + + Text { + text: flickable.visibleArea.xPosition + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 5364530ca8..f3659290eb 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -205,6 +205,7 @@ private slots: void overshoot_reentrant(); void synchronousDrag_data(); void synchronousDrag(); + void visibleAreaBinding(); private: void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); @@ -2540,6 +2541,16 @@ void tst_qquickflickable::synchronousDrag() QTest::touchEvent(window, touchDevice).release(0, p5, window); } +// QTBUG-81098: tests that a binding to visibleArea doesn't result +// in a division-by-zero exception (when exceptions are enabled). +void tst_qquickflickable::visibleAreaBinding() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("visibleAreaBinding.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + // Shouldn't crash. +} + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml index 07af6a77ac..0732884c97 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml @@ -1100,5 +1100,36 @@ Item { waitForRendering(rootRect.layout) compare(rootRect.item1.width, 100) } + +//--------------------------- + Component { + id: rowlayoutWithTextItems_Component + RowLayout { + Text { + Layout.fillWidth: true + text: "OneWord" + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + Text { + Layout.fillWidth: true + text: "OneWord" + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + } + } + + // QTBUG-73683 + function test_rowlayoutWithTextItems() { + var layout = createTemporaryObject(rowlayoutWithTextItems_Component, container) + waitForRendering(layout) + for (var i = 0; i < 3; i++) { + ignoreWarning(/Qt Quick Layouts: Detected recursive rearrange. Aborting after two iterations./) + } + ignoreWarning(/Qt Quick Layouts: Polish loop detected. Aborting after two iterations./) + layout.width = layout.width - 2 // set the size to be smaller than its "minimum size" + waitForRendering(layout) // do not exit before all warnings have been received + + // DO NOT CRASH due to stack overflow (or loop endlessly due to updatePolish()/polish() loop) + } } } diff --git a/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml new file mode 100644 index 0000000000..1e5a811630 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/headerSnapToItem.qml @@ -0,0 +1,67 @@ +import QtQuick 2.12 + +Rectangle { + + width: 240 + height: 320 + color: "#ffffff" + + Component { + id: myDelegate + Rectangle { + id: wrapper + objectName: "wrapper" + width: list.orientation == ListView.Vertical ? 240 : 20 + height: list.orientation == ListView.Vertical ? 20 : 240 + border.width: 1 + border.color: "black" + Text { + text: index + ":" + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(0) + } + color: ListView.isCurrentItem ? "lightsteelblue" : "white" + } + } + + ListView { + id: list + objectName: "list" + focus: true + width: 240 + height: 200 + clip: true + snapMode: ListView.SnapToItem + headerPositioning: ListView.OverlayHeader + model: 30 + delegate: myDelegate + orientation: ListView.Vertical + verticalLayoutDirection: ListView.BottomToTop + + header: Rectangle { + width: list.orientation == Qt.Vertical ? 240 : 30 + height: list.orientation == Qt.Vertical ? 30 : 240 + objectName: "header"; + color: "green" + z: 11 + Text { + anchors.centerIn: parent + text: "header " + (list.orientation == ListView.Vertical ? parent.y : parent.x).toFixed(1) + } + } + } + + Rectangle { + color: "red" + opacity: 0.5 + width: txt.implicitWidth + 50 + height: txt.implicitHeight + anchors.bottom: parent.bottom + anchors.right: parent.right + + Text { + id: txt + anchors.centerIn: parent + text: "header position: " + (list.orientation == ListView.Vertical ? list.headerItem.y : list.headerItem.x).toFixed(1) + + "\ncontent position: " + (list.orientation == ListView.Vertical ? list.contentY : list.contentX).toFixed(1) + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml new file mode 100644 index 0000000000..f6380ed5aa --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/requiredObjectListModel.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +ListView { + width: 100 + height: 100 + required model + + delegate: Rectangle { + required color + required property string name + + height: 25 + width: 100 + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 9a8dfee9d2..b141e235d5 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -30,6 +30,7 @@ #include <QtCore/QStringListModel> #include <QtCore/QSortFilterProxyModel> #include <QtGui/QStandardItemModel> +#include <QtGui/QStyleHints> #include <QtQuick/qquickview.h> #include <QtQuickTest/QtQuickTest> #include <QtQml/qqmlengine.h> @@ -40,6 +41,7 @@ #include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquicktext_p.h> +#include <QtQuick/private/qquickrectangle_p.h> #include <QtQmlModels/private/qqmlobjectmodel_p.h> #include <QtQmlModels/private/qqmllistmodel_p.h> #include <QtQmlModels/private/qqmldelegatemodel_p.h> @@ -185,6 +187,8 @@ private slots: void creationContext(); void snapToItem_data(); void snapToItem(); + void headerSnapToItem_data(); + void headerSnapToItem(); void snapToItemWithSpacing_QTBUG_59852(); void snapOneItemResize_QTBUG_43555(); void snapOneItem_data(); @@ -291,6 +295,8 @@ private slots: void moveObjectModelItemToAnotherObjectModel(); void changeModelAndDestroyTheOldOne(); + void requiredObjectListModel(); + private: template <class T> void items(const QUrl &source); template <class T> void changed(const QUrl &source); @@ -5412,6 +5418,604 @@ void tst_QQuickListView::snapToItemWithSpacing_QTBUG_59852() releaseView(window); } +static void drag_helper(QWindow *window, QPoint *startPos, const QPoint &delta) +{ + QPoint pos = *startPos; + int dragDistance = delta.manhattanLength(); + Q_ASSERT(qAbs(delta.x()) >= 1 || qAbs(delta.y()) >= 1); + + const int stepSize = 8; + QPoint unitVector(0, 0); + if (delta.x()) + unitVector.setX(qBound(-1, delta.x(), 1)); + if (delta.y()) + unitVector.setY(qBound(-1, delta.y(), 1)); + QPoint dragStepSize = unitVector * stepSize; + int nDragSteps = qAbs(dragDistance/stepSize); + + for (int i = 0 ; i < nDragSteps; ++i) { + QTest::mouseMove(window, pos); + pos += dragStepSize; + } + // Move to the final position + pos = *startPos + delta; + QTest::mouseMove(window, pos); + *startPos = pos; +} + +static void dragtwice(QWindow *window, QPoint *startPos, const QPoint &delta1, const QPoint &delta2) +{ + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + QPoint &pos = *startPos; + QPoint unitVector(0, 0); + if (delta1.x()) + unitVector.setX(qBound(-1, delta1.x(), 1)); + if (delta1.y()) + unitVector.setY(qBound(-1, delta1.y(), 1)); + + // go just beyond the drag theshold + drag_helper(window, &pos, unitVector * (dragThreshold + 1)); + drag_helper(window, &pos, unitVector); + + // next drag will actually scroll the listview + if (delta1.manhattanLength() >= 1) + drag_helper(window, &pos, delta1); + if (delta2.manhattanLength() >= 1) + drag_helper(window, &pos, delta2); +} + +struct MyListView : public QQuickListView{ + qreal contentPosition() const + { + return (orientation() == QQuickListView::Horizontal ? contentX(): contentY()); + } + + qreal headerPosition() const + { + return (orientation() == QQuickListView::Horizontal ? headerItem()->x() : headerItem()->y()); + } +}; + +void tst_QQuickListView::headerSnapToItem() +{ + QFETCH(QQuickItemView::LayoutDirection, layoutDirection); + QFETCH(QQuickListView::HeaderPositioning, headerPositioning); + QFETCH(int, firstDragDistance); + QFETCH(int, secondDragDistance); + QFETCH(int, expectedContentPosition); + QFETCH(int, expectedHeaderPosition); + + QQuickView *window = getView(); + window->setSource(testFileUrl("headerSnapToItem.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + MyListView *listview = static_cast<MyListView *>(findItem<QQuickListView>(window->rootObject(), "list")); + QVERIFY(listview != nullptr); + + const bool horizontal = layoutDirection < QQuickItemView::VerticalTopToBottom; + listview->setOrientation(horizontal ? QQuickListView::Horizontal : QQuickListView::Vertical); + + if (horizontal) + listview->setLayoutDirection(static_cast<Qt::LayoutDirection>(layoutDirection)); + else + listview->setVerticalLayoutDirection(static_cast<QQuickItemView::VerticalLayoutDirection>(layoutDirection)); + + listview->setHeaderPositioning(headerPositioning); + QVERIFY(QQuickTest::qWaitForItemPolished(listview)); + + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != nullptr); + QQuickItem *header = findItem<QQuickItem>(contentItem, "header"); + QVERIFY(header != nullptr); + QCOMPARE(header, listview->headerItem()); + + QPoint startPos = (QPointF(listview->width(), listview->height())/2).toPoint(); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); + + QPoint firstDragDelta(0, firstDragDistance); + QPoint secondDragDelta = QPoint(0, secondDragDistance); + if (horizontal) { + firstDragDelta = firstDragDelta.transposed(); + secondDragDelta = secondDragDelta.transposed(); + } + + dragtwice(window, &startPos, firstDragDelta, secondDragDelta); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, startPos, 200); // Wait 200 ms before we release to avoid trigger a flick + + // wait for the "fixup" animation to finish + QTest::qWaitFor([&]() + { return !listview->isMoving();} + ); + + QCOMPARE(listview->contentPosition(), expectedContentPosition); + QCOMPARE(listview->headerPosition(), expectedHeaderPosition); +} + +void tst_QQuickListView::headerSnapToItem_data() +{ + QTest::addColumn<QQuickItemView::LayoutDirection>("layoutDirection"); + QTest::addColumn<QQuickListView::HeaderPositioning>("headerPositioning"); + QTest::addColumn<int>("firstDragDistance"); + QTest::addColumn<int>("secondDragDistance"); + QTest::addColumn<int>("expectedContentPosition"); + QTest::addColumn<int>("expectedHeaderPosition"); + + // -------------------- + // InlineHeader TopToBottom + QTest::newRow("InlineHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -30") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -39") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader TopToBottom -41") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader BottomToTop + QTest::newRow("InlineHeader BottomToTop +10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 10 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 14 << 0 + << -170 << 0; + + QTest::newRow("InlineHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 16 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +30") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 30 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +39") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 39 << 0 + << -200 << 0; + + QTest::newRow("InlineHeader BottomToTop +41") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 41 << 0 + << -220 << 0; + + QTest::newRow("InlineHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::InlineHeader + << 65 << -10 + << -220 << 0; + + // -------------------- + // InlineHeader LeftToRight + QTest::newRow("InlineHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -14 << 0 + << -30 << -30; + + QTest::newRow("InlineHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -30") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -30 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -39") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -39 << 0 + << 0 << -30; + + QTest::newRow("InlineHeader LeftToRight -41") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -41 << 0 + << 20 << -30; + + QTest::newRow("InlineHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::InlineHeader + << -65 << 10 + << 20 << -30; + + // -------------------- + // InlineHeader RightToLeft + QTest::newRow("InlineHeader RightToLeft +10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 10 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 14 << 0 + << -210 << 0; + + QTest::newRow("InlineHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 16 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +30") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 30 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +39") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 39 << 0 + << -240 << 0; + + QTest::newRow("InlineHeader RightToLeft +41") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 41 << 0 + << -260 << 0; + + QTest::newRow("InlineHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::InlineHeader + << 65 << -10 + << -260 << 0; + + // -------------------- + // OverlayHeader TopToBottom + QTest::newRow("OverlayHeader TopToBottom +9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -9") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -29") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader TopToBottom -31") << QQuickItemView::VerticalTopToBottom + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader BottomToTop + QTest::newRow("OverlayHeader BottomToTop -9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << -9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 9 << 0 + << -170 << 0; + + QTest::newRow("OverlayHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 11 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +29") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 29 << 0 + << -190 << -20; + + QTest::newRow("OverlayHeader BottomToTop +31") << QQuickItemView::VerticalBottomToTop + << QQuickListView::OverlayHeader + << 31 << 0 + << -210 << -40; + + // -------------------- + // OverlayHeader LeftToRight + QTest::newRow("OverlayHeader LeftToRight +9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << 9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -9") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -9 << 0 + << -30 << -30; + + QTest::newRow("OverlayHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -29") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -29 << 0 + << -10 << -10; + + QTest::newRow("OverlayHeader LeftToRight -31") << QQuickItemView::LeftToRight + << QQuickListView::OverlayHeader + << -31 << 0 + << 10 << 10; + + // -------------------- + // OverlayHeader RightToLeft + QTest::newRow("OverlayHeader RightToLeft -9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << -9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 9 << 0 + << -210 << 0; + + QTest::newRow("OverlayHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 11 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +29") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 29 << 0 + << -230 << -20; + + QTest::newRow("OverlayHeader RightToLeft +31") << QQuickItemView::RightToLeft + << QQuickListView::OverlayHeader + << 31 << 0 + << -250 << -40; + + // -------------------- + // PullbackHeader TopToBottom + QTest::newRow("PullbackHeader TopToBottom -2") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader TopToBottom -11") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -14") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader TopToBottom -16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader TopToBottom -65+10") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader TopToBottom -65+20") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentY doesn't move (its aligned with top) + QTest::newRow("PullbackHeader TopToBottom -55+5") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader TopToBottom -76+16") << QQuickItemView::VerticalTopToBottom + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader BottomToTop + QTest::newRow("PullbackHeader BottomToTop +2") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +2 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +9") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +9 << 0 + << -170 << 0; + + QTest::newRow("PullbackHeader BottomToTop +11") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +11 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +14") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +14 << 0 + << -190 << -20; + + QTest::newRow("PullbackHeader BottomToTop +16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +16 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +20 << 0 + << -200 << 0; + + QTest::newRow("PullbackHeader BottomToTop +65-10") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -10 + << -220 << -20; + + QTest::newRow("PullbackHeader BottomToTop +65-20") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << +65 << -20 + << -210 << -40; + + // Should move header even if contentY doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader BottomToTop +55-5") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 55 << -5 + << -220 << -20; + + // Should move header even if contentY doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader BottomToTop +76-16") << QQuickItemView::VerticalBottomToTop + << QQuickListView::PullBackHeader + << 76 << -16 + << -230 << -60; + + // -------------------- + // PullbackHeader LeftToRight + QTest::newRow("PullbackHeader LeftToRight -2") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -2 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -10 << 0 + << -30 << -30; + + QTest::newRow("PullbackHeader LeftToRight -11") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -11 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -14") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -14 << 0 + << -10 << -10; + + QTest::newRow("PullbackHeader LeftToRight -16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -16 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -20 << 0 + << 0 << -30; + + QTest::newRow("PullbackHeader LeftToRight -65+10") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 10 + << 20 << -10; + + QTest::newRow("PullbackHeader LeftToRight -65+20") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -65 << 20 + << 10 << 10; + + // Should move header even if contentX doesn't move (its aligned with top) + QTest::newRow("PullbackHeader LeftToRight -55+5") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -55 << 5 + << 20 << -10; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader LeftToRight -76+16") << QQuickItemView::LeftToRight + << QQuickListView::PullBackHeader + << -76 << 16 + << 30 << 30; + + // -------------------- + // PullbackHeader RightToLeft + QTest::newRow("PullbackHeader RightToLeft +2") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +2 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +9") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +9 << 0 + << -210 << 0; + + QTest::newRow("PullbackHeader RightToLeft +11") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +11 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +14") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +14 << 0 + << -230 << -20; + + QTest::newRow("PullbackHeader RightToLeft +16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +16 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +20 << 0 + << -240 << 0; + + QTest::newRow("PullbackHeader RightToLeft +65-10") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -10 + << -260 << -20; + + QTest::newRow("PullbackHeader RightToLeft +65-20") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << +65 << -20 + << -250 << -40; + + // Should move header even if contentX doesn't move (it's aligned with top) + QTest::newRow("PullbackHeader RightToLeft +55-5") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 55 << -5 + << -260 << -20; + + // Should move header even if contentX doesn't move (it's aligned with header) + QTest::newRow("PullbackHeader RightToLeft +76-16") << QQuickItemView::RightToLeft + << QQuickListView::PullBackHeader + << 76 << -16 + << -270 << -60; + +} + void tst_QQuickListView::snapOneItemResize_QTBUG_43555() { QScopedPointer<QQuickView> window(createView()); @@ -9431,6 +10035,60 @@ void tst_QQuickListView::changeModelAndDestroyTheOldOne() // QTBUG-80203 // no crash } +class DataObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString color READ color CONSTANT) + +public: + DataObject(QObject *parent = nullptr) : QObject(parent) {} + DataObject(const QString &name, const QString &color, QObject *parent = nullptr) + : QObject(parent), m_name(name), m_color(color) {} + + QString name() const { return m_name; } + QString color() const { return m_color; } + +private: + QString m_name; + QString m_color; +}; + +void tst_QQuickListView::requiredObjectListModel() +{ + QList<QObject *> dataList = { + new DataObject("Item 1", "red", this), + new DataObject("Item 2", "green", this), + new DataObject("Item 3", "blue", this), + new DataObject("Item 4", "yellow", this) + }; + + const auto deleter = qScopeGuard([&](){ qDeleteAll(dataList); }); + Q_UNUSED(deleter); + + QQuickView view; + view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }}); + view.setSource(testFileUrl("requiredObjectListModel.qml")); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + const auto *root = qobject_cast<QQuickListView *>(view.rootObject()); + QVERIFY(root); + + QCOMPARE(root->count(), dataList.count()); + + for (int i = 0, end = dataList.count(); i != end; ++i) { + const auto *rect = qobject_cast<QQuickRectangle *>(root->itemAtIndex(i)); + QVERIFY(rect); + const auto *data = qobject_cast<DataObject *>(dataList.at(i)); + QVERIFY(data); + + QCOMPARE(rect->color(), QColor(data->color())); + QCOMPARE(rect->property("name").toString(), data->name()); + } +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquickloader/data/statusChanged.qml b/tests/auto/quick/qquickloader/data/statusChanged.qml new file mode 100644 index 0000000000..fe46bc7b24 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/statusChanged.qml @@ -0,0 +1,16 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 + +Window { + id: root + property int statusChangedCounter: 0 + property alias status: loader.status + visible: true; width: 640; height: 480 + Loader { + id: loader + anchors.fill: parent + asynchronous: true + source: "./RedRect.qml" + onStatusChanged: root.statusChangedCounter++ + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index e05b7ae9ce..91d0bcab2e 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -39,6 +39,7 @@ #include "testhttpserver.h" #include "../../shared/util.h" #include "../shared/geometrytestutil.h" +#include <QQmlApplicationEngine> Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") @@ -128,6 +129,7 @@ private slots: void rootContext(); void sourceURLKeepComponent(); + void statusChangeOnlyEmittedOnce(); }; Q_DECLARE_METATYPE(QList<QQmlError>) @@ -1456,6 +1458,18 @@ void tst_QQuickLoader::sourceURLKeepComponent() } +// QTBUG-82002 +void tst_QQuickLoader::statusChangeOnlyEmittedOnce() +{ + QQmlApplicationEngine engine; + auto url = testFileUrl("statusChanged.qml"); + engine.load(url); + auto root = engine.rootObjects().at(0); + QVERIFY(root); + QTRY_COMPARE(QQuickLoader::Status(root->property("status").toInt()), QQuickLoader::Ready); + QCOMPARE(root->property("statusChangedCounter").toInt(), 2); // 1xLoading + 1xReady*/ +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" diff --git a/tests/auto/quick/qquickmousearea/BLACKLIST b/tests/auto/quick/qquickmousearea/BLACKLIST index 6dbe3e11b6..1491116f59 100644 --- a/tests/auto/quick/qquickmousearea/BLACKLIST +++ b/tests/auto/quick/qquickmousearea/BLACKLIST @@ -1,2 +1,6 @@ [pressAndHold] macos ci + +# QTBUG-78153 +[nestedStopAtBounds] +opensuse-leap diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index bf58ce961c..0bf83c267a 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -2860,7 +2860,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount() QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1)); - QQuickPointerMouseEvent pme; + QQuickPointerMouseEvent pme(nullptr, QQuickPointerDevice::genericMouseDevice()); pme.reset(&me); QCOMPARE(pme.asMouseEvent(localPosition), &me); QVERIFY(pme.asPointerMouseEvent()); @@ -2872,7 +2872,7 @@ void tst_qquickwindow::pointerEventTypeAndPointCount() QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition); QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition); - QQuickPointerTouchEvent pte; + QQuickPointerTouchEvent pte(nullptr, QQuickPointerDevice::touchDevice(touchDevice)); pte.reset(&te); QCOMPARE(pte.asTouchEvent(), &te); QVERIFY(!pte.asPointerMouseEvent()); diff --git a/tests/auto/shared/astdump.pri b/tests/auto/shared/astdump.pri new file mode 100644 index 0000000000..365b12fc51 --- /dev/null +++ b/tests/auto/shared/astdump.pri @@ -0,0 +1,7 @@ + +INCLUDEPATH += $$PWD +HEADERS += \ + $$PWD/qqmljsastdumper.h + +SOURCES += \ + $$PWD/qqmljsastdumper.cpp diff --git a/tests/auto/shared/qqmljsastdumper.cpp b/tests/auto/shared/qqmljsastdumper.cpp new file mode 100644 index 0000000000..bc21d8d4e5 --- /dev/null +++ b/tests/auto/shared/qqmljsastdumper.cpp @@ -0,0 +1,1081 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +**/ +#include "qqmljsastdumper.h" +#include <private/qqmljsast_p.h> +#include <QtCore/QDebug> +#include <QtCore/QString> +#include <QtCore/QTextStream> + +QT_BEGIN_NAMESPACE + +namespace QQmlJS { +using namespace AST; +/*! +\internal +\enum QQmlJS::DumperOptions + +This enum type specifies the options for the AstDumper. +The values can be combined with the '|' operator, and checked using the '&' operator. + +\value None + Default dumping options +\value NoLocations + Does not dump SourceLocations, allowing one to compare equivalent AST + generated by code formatted differently +\value NoAnnotations + Does not dump annotations +\value DumpNode + Does dump a <Node></Node> in preVisit/postVisit +*/ + +/*! +\internal +\class QQmlJS::AstDumper +\brief Dumps or compares AST in an xml like format, mostly for testing/debugging + +Initialize it with a lambda that dumps a string, and configure it with .setX methods. +If \l{indent} is set to a non zero value the xml is indented by that amount, and +\l{baseIndent} is the initial indent. +If \l{emitNode} is true the node tag is emitted in the preVisit/postVisit. +If \l{emitLocation} is true the SourceLocations are emitted. +If \l{emitAnnotations} is true annotations are emitted + +The implementation has unnecessary roundtrips to QString, but it is supposed to be used +for debugging purposes... + +Probably you will not use the visitor at all but rather the static method diff or +the qDebug() and ostream operator << that use the visitor... + +\fn AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent) + +\brief compares the two AST::Node n1 and n2 and returns a string describing their first difference + +If there are no differences the empty string is returned, so .isEmpty() can be use to check +for no differences. +\l{nContext} decides how much context is printed out. + +*/ + + +QDebug operator<<(QDebug d, AST::Node *n) { + QDebug noQuote = d.noquote().nospace(); + AstDumper visitor([&noQuote](const QString &s){ noQuote << s; }); + Node::accept(n, &visitor); + return d; +} + + +std::ostream &operator<<(std::ostream &stream, AST::Node *n) { + AstDumper visitor([&stream](const QString &s){ stream << s.toStdString(); }); + Node::accept(n, &visitor); + return stream; +} + +bool operator & (DumperOptions lhs, DumperOptions rhs) { + return bool(static_cast<int>(lhs) & static_cast<int>(rhs)); +} + +DumperOptions operator | (DumperOptions lhs, DumperOptions rhs) { + return DumperOptions(static_cast<int>(lhs) | static_cast<int>(rhs)); +} + +QString AstDumper::diff(AST::Node *n1, AST::Node *n2, int nContext, DumperOptions opt, int indent) { + QString s1, s2; + QTextStream d1(&s1), d2(&s2); + AstDumper visitor1=AstDumper([&d1](const QString &s){ d1 << s; }, opt, indent); + AstDumper visitor2=AstDumper([&d2](const QString &s){ d2 << s; }, opt, indent); + Node::accept(n1, &visitor1); + Node::accept(n2, &visitor2); + d1.seek(0); + d2.seek(0); + std::vector<QString> preLines(nContext); + int nLine = 0; + bool same = true; + QString l1, l2; + while (same && !d1.atEnd() && !d2.atEnd()) { + l1=d1.readLine(); + l2=d2.readLine(); + if (l1 == l2) + preLines[nLine++ % nContext] = l1; + else + same = false; + } + QString res; + QTextStream ss(&res); + if (!same || !d1.atEnd() || !d2.atEnd()) { + for (int iline = qMin(nLine, nContext); iline > 0; --iline) { + ss << QLatin1String(" ") << preLines[(nLine - iline) % nContext] << QLatin1String("\n"); + } + int iline = 0; + if (!same) { + ss << QLatin1String("-") << l1 << QLatin1String("\n"); + ++iline; + } + if (same && nContext == 0) + nContext = 1; + for (;iline < nContext && !d1.atEnd(); iline ++) { + l1 = d1.readLine(); + ss << QLatin1String("-") << l1 << QLatin1String("\n"); + } + iline = 0; + if (!same) { + ss << QLatin1String("+") << l2 << QLatin1String("\n"); + ++iline; + } + for (;iline < nContext && !d2.atEnd(); iline ++) { + l2 = d2.readLine(); + ss << QLatin1String("+") << l2 << QLatin1String("\n"); + } + } + return res; +} + +QString AstDumper::printNode(Node *n, DumperOptions opt, int indent, int baseIndent) +{ + QString res; + QTextStream d(&res); + AstDumper visitor=AstDumper([&d](const QString &s){ d << s; }, opt, indent, baseIndent); + Node::accept(n, &visitor); + return res; +} + +AstDumper::AstDumper(const std::function<void(const QString &)> &dumper, DumperOptions options, int indent, int baseIndent): + dumper(dumper), options(options), indent(indent), baseIndent(baseIndent) {} + +void AstDumper::start(const QString &str) { + dumper(QString::fromLatin1(" ").repeated(baseIndent)); + dumper(QLatin1String("<")); + dumper(str); + dumper(QLatin1String(">\n")); + baseIndent += indent; +} + +void AstDumper::start(const char *str) { + start(QLatin1String(str)); +} + +void AstDumper::stop(const QString &str) { + baseIndent -= indent; + dumper(QString::fromLatin1(" ").repeated(baseIndent)); + dumper(QLatin1String("</")); + dumper(str); + dumper(QLatin1String(">\n")); +} + +void AstDumper::stop(const char *str) { + stop(QLatin1String(str)); +} + +QString AstDumper::qs(const QString &s) { + QString res(s); + return QLatin1String("\"") + res + .replace(QLatin1String("\\"), QLatin1String("\\\\")) + .replace(QLatin1String("\""), QLatin1String("\\\"")) + QLatin1String("\""); +} + +QString AstDumper::qs(const char *s) { + return qs(QLatin1String(s)); +} + +QString AstDumper::qs(const QStringRef &s) { + return qs(s.toString()); +} + +QString AstDumper::loc(const AST::SourceLocation &s) { + if (noLocations() || !s.isValid()) + return QLatin1String("\"\""); + else { + return QLatin1String("\"off:%1 len:%2 l:%3 c:%4\"").arg(QString::number(s.offset), QString::number(s.length), QString::number(s.startLine), QString::number(s.startColumn)); + } +} + +QString AstDumper::boolStr(bool v) { return (v ? qs("true"): qs("false")); } + +bool AstDumper::preVisit(Node *) { if (dumpNode()) start("Node"); return true; } + +void AstDumper::postVisit(Node *) { if (dumpNode()) stop("Node"); } + +bool AstDumper::visit(UiProgram *) { start("UiProgram"); return true; } + +bool AstDumper::visit(UiHeaderItemList *) { start("UiHeaderItemList"); return true; } + +bool AstDumper::visit(UiPragma *el) { + start(QLatin1String("UiPragma name=%1 pragmaToken=%2 semicolonToken=%3") + .arg(qs(el->name), loc(el->pragmaToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiImport *el) +{ + start(QLatin1String("UiImport fileName=%1 importId=%2 importToken=%3 fileNameToken=%4 asToken=%5 importIdToken=%6 semicolonToken=%7") + .arg(qs(el->fileName), qs(el->importId), loc(el->importToken), loc(el->fileNameToken), loc(el->asToken), loc(el->importIdToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiPublicMember *el) { + QString typeStr = ((el->type == UiPublicMember::Signal) ? QLatin1String("Signal") : + (el->type == UiPublicMember::Property) ? QLatin1String("Property") : QLatin1String("Unexpected(%1)").arg(el->type)); + start(QLatin1String("UiPublicMember type=%1 typeModifier=%2 name=%3 isDefaultMember=%4 isReadonlyMember=%5 isRequired=%6 " + "defaultToken=%7 readonlyToken=%8 propertyToken=%9 requiredToken=%10 typeModifierToken=%11 typeToken=%12 " + "identifierToken=%13 colonToken=%14 semicolonToken=%15") + .arg(qs(typeStr), qs(el->typeModifier), qs(el->name), + el->isDefaultMember, el->isReadonlyMember, el->isRequired, + loc(el->defaultToken), loc(el->readonlyToken), loc(el->propertyToken), + loc(el->requiredToken), loc(el->typeModifierToken), loc(el->typeToken), + loc(el->identifierToken), loc(el->colonToken), loc(el->semicolonToken) + )); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + Node::accept(el->memberType, this); + return true; +} + +bool AstDumper::visit(AST::UiSourceElement *el) { + start(QLatin1String("UiSourceElement")); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectDefinition *el) { + start("UiObjectDefinition"); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectInitializer *el) { + start(QLatin1String("UiObjectInitializer lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} + +bool AstDumper::visit(AST::UiObjectBinding *el) { + start(QLatin1String("UiObjectBinding colonToken=%1 hasOnToken=%2") + .arg(loc(el->colonToken), boolStr(el->hasOnToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiScriptBinding *el) { + start(QLatin1String("UiScriptBinding colonToken=%1") + .arg(loc(el->colonToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiArrayBinding *el) { + start(QLatin1String("UiArrayBinding colonToken=%1 lbracketToken=%2 rbracketToken=%3") + .arg(loc(el->colonToken), loc(el->lbracketToken), loc(el->rbracketToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiParameterList *el) { + start(QLatin1String("UiArrayBinding name=%1 commaToken=%2 propertyTypeToken=%3 identifierToken=%4 colonToken=%5") + .arg(qs(el->name), loc(el->commaToken), loc(el->propertyTypeToken), loc(el->identifierToken), loc(el->colonToken))); + Node::accept(el->type, this); + return true; +} + +bool AstDumper::visit(AST::UiObjectMemberList *) { start("UiObjectMemberList"); return true; } + +bool AstDumper::visit(AST::UiArrayMemberList *el) { + start(QLatin1String("UiArrayMemberList commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} + +bool AstDumper::visit(AST::UiQualifiedId *el) { + start(QLatin1String("UiQualifiedId name=%1 identifierToken=%2") + .arg(qs(el->name), loc(el->identifierToken))); + Node::accept(el->next, this); + return true; +} + +bool AstDumper::visit(AST::UiEnumDeclaration *el) { + start(QLatin1String("UiEnumDeclaration enumToken=%1 rbraceToken=%2 name=%3") + .arg(loc(el->enumToken), loc(el->rbraceToken), qs(el->name))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(AST::UiEnumMemberList *el) { + start(QLatin1String("UiEnumMemberList member=%1 value=%2 memberToken=%3 valueToken=%4") + .arg(qs(el->member), qs(QString::number(el->value)), loc(el->memberToken), loc(el->valueToken))); + return true; +} + +bool AstDumper::visit(AST::UiVersionSpecifier *el) { + start(QLatin1String("UiVersionSpecifier majorVersion=%1 minorVersion=%2 majorToken=%3 minorToken=%4") + .arg(qs(QString::number(el->version.majorVersion())), + qs(QString::number(el->version.minorVersion())), + loc(el->majorToken), loc(el->minorToken))); + return true; +} + +bool AstDumper::visit(AST::UiInlineComponent *el) { + start(QLatin1String("UiInlineComponent name=%1 componentToken=%2") + .arg(qs(el->name), loc(el->componentToken))); + if (!noAnnotations()) // put annotations inside the node they refer to + Node::accept(el->annotations, this); + return true; +} + +bool AstDumper::visit(UiRequired *el) +{ + start(QLatin1String("UiRequired name=%1 requiredToken=%2 semicolonToken=%3") + .arg(qs(el->name), loc(el->requiredToken), loc(el->semicolonToken))); + return true; +} + +bool AstDumper::visit(UiAnnotation *) +{ + start(QLatin1String("UiAnnotation")); + return true; +} + +bool AstDumper::visit(UiAnnotationList *) +{ + start(QLatin1String("UiAnnotationList")); + return true; +} + +void AstDumper::endVisit(AST::UiProgram *) { stop("UiProgram"); } + +void AstDumper::endVisit(AST::UiImport *el) { + Node::accept(el->version, this); + stop("UiImport"); +} + +void AstDumper::endVisit(AST::UiHeaderItemList *) { stop("UiHeaderItemList"); } + +void AstDumper::endVisit(AST::UiPragma *) { stop("UiPragma"); } + +void AstDumper::endVisit(AST::UiPublicMember *el) { + Node::accept(el->parameters, this); + stop("UiPublicMember"); +} + +void AstDumper::endVisit(AST::UiSourceElement *) { stop("UiSourceElement"); } +void AstDumper::endVisit(AST::UiObjectDefinition *) { stop("UiObjectDefinition"); } +void AstDumper::endVisit(AST::UiObjectInitializer *) { stop("UiObjectInitializer"); } +void AstDumper::endVisit(AST::UiObjectBinding *) { stop("UiObjectBinding"); } +void AstDumper::endVisit(AST::UiScriptBinding *) { stop("UiScriptBinding"); } +void AstDumper::endVisit(AST::UiArrayBinding *) { stop("UiArrayBinding"); } +void AstDumper::endVisit(AST::UiParameterList *el) { + stop("UiParameterList"); + Node::accept(el->next, this); // put other args at the same level as this one... +} +void AstDumper::endVisit(AST::UiObjectMemberList *) { stop("UiObjectMemberList"); } +void AstDumper::endVisit(AST::UiArrayMemberList *) { stop("UiArrayMemberList"); } +void AstDumper::endVisit(AST::UiQualifiedId *) { stop("UiQualifiedId"); } +void AstDumper::endVisit(AST::UiEnumDeclaration *) { stop("UiEnumDeclaration"); } +void AstDumper::endVisit(AST::UiEnumMemberList *el) { + stop("UiEnumMemberList"); + Node::accept(el->next, this); // put other enum members at the same level as this one... +} +void AstDumper::endVisit(AST::UiVersionSpecifier *) { stop("UiVersionSpecifier"); } +void AstDumper::endVisit(AST::UiInlineComponent *) { stop("UiInlineComponent"); } +void AstDumper::endVisit(UiRequired *) { stop("UiRequired"); } +void AstDumper::endVisit(UiAnnotation *) { stop("UiAnnotation"); } +void AstDumper::endVisit(UiAnnotationList *) { stop("UiAnnotationList"); } + +// QQmlJS +bool AstDumper::visit(AST::ThisExpression *el) { + start(QLatin1String("ThisExpression thisToken=%1") + .arg(loc(el->thisToken))); + return true; +} +void AstDumper::endVisit(AST::ThisExpression *) { stop("ThisExpression"); } + +bool AstDumper::visit(AST::IdentifierExpression *el) { + start(QLatin1String("IdentifierExpression name=%1 identiferToken=%2") + .arg(qs(el->name), loc(el->identifierToken))); + return true; +} +void AstDumper::endVisit(AST::IdentifierExpression *) { stop("IdentifierExpression"); } + +bool AstDumper::visit(AST::NullExpression *el) { + start(QLatin1String("NullExpression nullToken=%1") + .arg(loc(el->nullToken))); + return true; +} +void AstDumper::endVisit(AST::NullExpression *) { stop("NullExpression"); } + +bool AstDumper::visit(AST::TrueLiteral *el) { + start(QLatin1String("TrueLiteral trueToken=%1") + .arg(loc(el->trueToken))); + return true; +} +void AstDumper::endVisit(AST::TrueLiteral *) { stop("TrueLiteral"); } + +bool AstDumper::visit(AST::FalseLiteral *el) { + start(QLatin1String("FalseLiteral falseToken=%1") + .arg(loc(el->falseToken))); + return true; +} +void AstDumper::endVisit(AST::FalseLiteral *) { stop("FalseLiteral"); } + +bool AstDumper::visit(AST::SuperLiteral *el) { + start(QLatin1String("SuperLiteral superToken=%1") + .arg(loc(el->superToken))); + return true; +} +void AstDumper::endVisit(AST::SuperLiteral *) { stop("SuperLiteral"); } + +bool AstDumper::visit(AST::StringLiteral *el) { + start(QLatin1String("StringLiteral value=%1 literalToken=%2") + .arg(qs(el->value), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::StringLiteral *) { stop("StringLiteral"); } + +bool AstDumper::visit(AST::TemplateLiteral *el) { + start(QLatin1String("TemplateLiteral value=%1 rawValue=%2 literalToken=%3") + .arg(qs(el->value), qs(el->rawValue), loc(el->literalToken))); + Node::accept(el->expression, this); + return true; +} +void AstDumper::endVisit(AST::TemplateLiteral *) { stop("TemplateLiteral"); } + +bool AstDumper::visit(AST::NumericLiteral *el) { + start(QLatin1String("NumericLiteral value=%1 literalToken=%2") + .arg(qs(QString::number(el->value)), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::NumericLiteral *) { stop("NumericLiteral"); } + +bool AstDumper::visit(AST::RegExpLiteral *el) { + start(QLatin1String("RegExpLiteral pattern=%1 flags=%2 literalToken=%3") + .arg(qs(el->pattern), qs(QString::number(el->flags, 16)), loc(el->literalToken))); + return true; +} +void AstDumper::endVisit(AST::RegExpLiteral *) { stop("RegExpLiteral"); } + +bool AstDumper::visit(AST::ArrayPattern *el) { + start(QLatin1String("ArrayPattern lbracketToken=%1, commaToken=%2, rbracketToken=%3 parseMode=%4") + .arg(loc(el->lbracketToken),loc(el->commaToken),loc(el->rbracketToken), qs(QString::number(el->parseMode, 16)))); + return true; +} +void AstDumper::endVisit(AST::ArrayPattern *) { stop("ArrayPattern"); } + +bool AstDumper::visit(AST::ObjectPattern *el) { + start(QLatin1String("ObjectPattern lbraceToken=%1 rbraceToken=%2 parseMode=%3") + .arg(loc(el->lbraceToken), loc(el->rbraceToken), qs(QString::number(el->parseMode, 16)))); + return true; +} +void AstDumper::endVisit(AST::ObjectPattern *) { stop("ObjectPattern"); } + +bool AstDumper::visit(AST::PatternElementList *) { start("PatternElementList"); return true; } +void AstDumper::endVisit(AST::PatternElementList *) { stop("PatternElementList"); } + +bool AstDumper::visit(AST::PatternPropertyList *) { start("PatternPropertyList"); return true; } +void AstDumper::endVisit(AST::PatternPropertyList *) { stop("PatternPropertyList"); } + +bool AstDumper::visit(AST::PatternElement *el) { + start(QLatin1String("PatternElement identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5") + .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)), + qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration))); + return true; +} +void AstDumper::endVisit(AST::PatternElement *) { stop("PatternElement"); } + +bool AstDumper::visit(AST::PatternProperty *el) { + start(QLatin1String("PatternProperty identifierToken=%1 bindingIdentifier=%2 type=%3 scope=%4 isForDeclaration=%5 colonToken=%6") + .arg(loc(el->identifierToken), qs(el->bindingIdentifier), qs(QString::number(el->type, 16)), + qs(QString::number(static_cast<int>(el->scope), 16)), boolStr(el->isForDeclaration), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::PatternProperty *) { stop("PatternProperty"); } + +bool AstDumper::visit(AST::Elision *el) { + start(QLatin1String("Elision commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::Elision *el) { + stop("Elision"); + Node::accept(el->next, this); // emit other elisions at the same level +} + +bool AstDumper::visit(AST::NestedExpression *el) { + start(QLatin1String("NestedExpression lparenToken=%1 rparenToken=%2") + .arg(loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::NestedExpression *) { stop("NestedExpression"); } + +bool AstDumper::visit(AST::IdentifierPropertyName *el) { + start(QLatin1String("IdentifierPropertyName id=%1 propertyNameToken=%2") + .arg(qs(el->id), loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::IdentifierPropertyName *) { stop("IdentifierPropertyName"); } + +bool AstDumper::visit(AST::StringLiteralPropertyName *el) { + start(QLatin1String("StringLiteralPropertyName id=%1 propertyNameToken=%2") + .arg(qs(el->id), loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::StringLiteralPropertyName *) { stop("StringLiteralPropertyName"); } + +bool AstDumper::visit(AST::NumericLiteralPropertyName *el) { + start(QLatin1String("NumericLiteralPropertyName id=%1 propertyNameToken=%2") + .arg(qs(QString::number(el->id)),loc(el->propertyNameToken))); + return true; +} +void AstDumper::endVisit(AST::NumericLiteralPropertyName *) { stop("NumericLiteralPropertyName"); } + +bool AstDumper::visit(AST::ComputedPropertyName *) { + start(QLatin1String("ComputedPropertyName")); + return true; +} +void AstDumper::endVisit(AST::ComputedPropertyName *) { stop("ComputedPropertyName"); } + +bool AstDumper::visit(AST::ArrayMemberExpression *el) { + start(QLatin1String("ArrayMemberExpression lbraketToken=%1 rbraketToken=%2") + .arg(loc(el->lbracketToken), loc(el->rbracketToken))); + return true; +} +void AstDumper::endVisit(AST::ArrayMemberExpression *) { stop("ArrayMemberExpression"); } + +bool AstDumper::visit(AST::FieldMemberExpression *el) { + start(QLatin1String("FieldMemberExpression name=%1 dotToken=%2 identifierToken=%3") + .arg(qs(el->name), loc(el->dotToken), loc(el->identifierToken))); + return true; +} +void AstDumper::endVisit(AST::FieldMemberExpression *) { stop("FieldMemberExpression"); } + +bool AstDumper::visit(AST::TaggedTemplate *) { + start(QLatin1String("TaggedTemplate")); + return true; +} +void AstDumper::endVisit(AST::TaggedTemplate *) { stop("TaggedTemplate"); } + +bool AstDumper::visit(AST::NewMemberExpression *el) { + start(QLatin1String("NewMemberExpression newToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->newToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::NewMemberExpression *) { stop("NewMemberExpression"); } + +bool AstDumper::visit(AST::NewExpression *el) { + start(QLatin1String("NewExpression newToken=%1") + .arg(loc(el->newToken))); + return true; +} +void AstDumper::endVisit(AST::NewExpression *) { stop("NewExpression"); } + +bool AstDumper::visit(AST::CallExpression *el) { + start(QLatin1String("CallExpression lparenToken=%1 rparenToken=%2") + .arg(loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::CallExpression *) { stop("CallExpression"); } + +bool AstDumper::visit(AST::ArgumentList *el) { + start(QLatin1String("ArgumentList commaToken=%1 isSpreadElement=%2") + .arg(loc(el->commaToken), boolStr(el->isSpreadElement))); + return true; +} +void AstDumper::endVisit(AST::ArgumentList *) { stop("ArgumentList"); } + +bool AstDumper::visit(AST::PostIncrementExpression *el) { + start(QLatin1String("PostIncrementExpression incrementToken=%1") + .arg(loc(el->incrementToken))); + return true; +} +void AstDumper::endVisit(AST::PostIncrementExpression *) { stop("PostIncrementExpression"); } + +bool AstDumper::visit(AST::PostDecrementExpression *el) { + start(QLatin1String("PostDecrementExpression decrementToken=%1") + .arg(loc(el->decrementToken))); + return true; +} +void AstDumper::endVisit(AST::PostDecrementExpression *) { stop("PostDecrementExpression"); } + +bool AstDumper::visit(AST::DeleteExpression *el) { + start(QLatin1String("DeleteExpression deleteToken=%1") + .arg(loc(el->deleteToken))); + return true; +} +void AstDumper::endVisit(AST::DeleteExpression *) { stop("DeleteExpression"); } + +bool AstDumper::visit(AST::VoidExpression *el) { + start(QLatin1String("VoidExpression voidToken=%1") + .arg(loc(el->voidToken))); + return true; +} +void AstDumper::endVisit(AST::VoidExpression *) { stop("VoidExpression"); } + +bool AstDumper::visit(AST::TypeOfExpression *el) { + start(QLatin1String("TypeOfExpression typeofToken=%1") + .arg(loc(el->typeofToken))); + return true; +} +void AstDumper::endVisit(AST::TypeOfExpression *) { stop("TypeOfExpression"); } + +bool AstDumper::visit(AST::PreIncrementExpression *el) { + start(QLatin1String("PreIncrementExpression incrementToken=%1") + .arg(loc(el->incrementToken))); + return true; +} +void AstDumper::endVisit(AST::PreIncrementExpression *) { stop("PreIncrementExpression"); } + +bool AstDumper::visit(AST::PreDecrementExpression *el) { + start(QLatin1String("PreDecrementExpression decrementToken=%1") + .arg(loc(el->decrementToken))); + return true; +} +void AstDumper::endVisit(AST::PreDecrementExpression *) { stop("PreDecrementExpression"); } + +bool AstDumper::visit(AST::UnaryPlusExpression *el) { + start(QLatin1String("UnaryPlusExpression plusToken=%1") + .arg(loc(el->plusToken))); + return true; +} +void AstDumper::endVisit(AST::UnaryPlusExpression *) { stop("UnaryPlusExpression"); } + +bool AstDumper::visit(AST::UnaryMinusExpression *el) { + start(QLatin1String("UnaryMinusExpression minusToken=%1") + .arg(loc(el->minusToken))); + return true; +} +void AstDumper::endVisit(AST::UnaryMinusExpression *) { stop("UnaryMinusExpression"); } + +bool AstDumper::visit(AST::TildeExpression *el) { + start(QLatin1String("TildeExpression tildeToken=%1") + .arg(loc(el->tildeToken))); + return true; +} +void AstDumper::endVisit(AST::TildeExpression *) { stop("TildeExpression"); } + +bool AstDumper::visit(AST::NotExpression *el) { + start(QLatin1String("NotExpression notToken=%1") + .arg(loc(el->notToken))); + return true; +} +void AstDumper::endVisit(AST::NotExpression *) { stop("NotExpression"); } + +bool AstDumper::visit(AST::BinaryExpression *el) { + start(QLatin1String("BinaryExpression op=%1 operatorToken=%2") + .arg(qs(QString::number(el->op,16)), loc(el->operatorToken))); + return true; +} +void AstDumper::endVisit(AST::BinaryExpression *) { stop("BinaryExpression"); } + +bool AstDumper::visit(AST::ConditionalExpression *el) { + start(QLatin1String("ConditionalExpression questionToken=%1 colonToken=%2") + .arg(loc(el->questionToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::ConditionalExpression *) { stop("ConditionalExpression"); } + +bool AstDumper::visit(AST::Expression *el) { + start(QLatin1String("Expression commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::Expression *) { stop("Expression"); } + +bool AstDumper::visit(AST::Block *el) { + start(QLatin1String("Block lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::Block *) { stop("Block"); } + +bool AstDumper::visit(AST::StatementList *) { + start(QLatin1String("StatementList")); + return true; +} +void AstDumper::endVisit(AST::StatementList *) { stop("StatementList"); } + +bool AstDumper::visit(AST::VariableStatement *el) { + start(QLatin1String("VariableStatement declarationKindToken=%1") + .arg(loc(el->declarationKindToken))); + return true; +} +void AstDumper::endVisit(AST::VariableStatement *) { stop("VariableStatement"); } + +bool AstDumper::visit(AST::VariableDeclarationList *el) { + start(QLatin1String("VariableDeclarationList commaToken=%1") + .arg(loc(el->commaToken))); + return true; +} +void AstDumper::endVisit(AST::VariableDeclarationList *) { stop("VariableDeclarationList"); } + +bool AstDumper::visit(AST::EmptyStatement *el) { + start(QLatin1String("EmptyStatement semicolonToken=%1") + .arg(loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::EmptyStatement *) { stop("EmptyStatement"); } + +bool AstDumper::visit(AST::ExpressionStatement *el) { + start(QLatin1String("ExpressionStatement semicolonToken=%1") + .arg(loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ExpressionStatement *) { stop("ExpressionStatement"); } + +bool AstDumper::visit(AST::IfStatement *el) { + start(QLatin1String("IfStatement ifToken=%1 lparenToken=%2 rparenToken=%3 elseToken=%4") + .arg(loc(el->ifToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->elseToken))); + return true; +} +void AstDumper::endVisit(AST::IfStatement *) { stop("IfStatement"); } + +bool AstDumper::visit(AST::DoWhileStatement *el) { + start(QLatin1String("DoWhileStatement doToken=%1 whileToken=%2 lparenToken=%3 rparenToken=%4 semicolonToken=%5") + .arg(loc(el->doToken), loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::DoWhileStatement *) { stop("DoWhileStatement"); } + +bool AstDumper::visit(AST::WhileStatement *el) { + start(QLatin1String("WhileStatement whileToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->whileToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::WhileStatement *) { stop("WhileStatement"); } + +bool AstDumper::visit(AST::ForStatement *el) { + start(QLatin1String("ForStatement forToken=%1 lparenToken=%2 firstSemicolonToken=%3 secondSemicolonToken=%4 rparenToken=%5") + .arg(loc(el->forToken), loc(el->lparenToken), loc(el->firstSemicolonToken), loc(el->secondSemicolonToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::ForStatement *) { stop("ForStatement"); } + +bool AstDumper::visit(AST::ForEachStatement *el) { + start(QLatin1String("ForEachStatement forToken=%1 lparenToken=%2 inOfToken=%3 rparenToken=%4 type=%5") + .arg(loc(el->forToken), loc(el->lparenToken), loc(el->inOfToken), loc(el->rparenToken), qs(QString::number(static_cast<int>(el->type), 16)))); + return true; +} +void AstDumper::endVisit(AST::ForEachStatement *) { stop("ForEachStatement"); } + +bool AstDumper::visit(AST::ContinueStatement *el) { + start(QLatin1String("ContinueStatement label=%1 continueToken=%2 identifierToken=%3 semicolonToken=%4") + .arg(qs(el->label), loc(el->continueToken), loc(el->identifierToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ContinueStatement *) { stop("ContinueStatement"); } + +bool AstDumper::visit(AST::BreakStatement *el) { + start(QLatin1String("BreakStatement label=%1 breakToken=%2 identifierToken=%3 semicolonToken=%4") + .arg(qs(el->label), loc(el->breakToken), loc(el->identifierToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::BreakStatement *) { stop("BreakStatement"); } + +bool AstDumper::visit(AST::ReturnStatement *el) { + start(QLatin1String("ReturnStatement returnToken=%1 semicolonToken=%2") + .arg(loc(el->returnToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ReturnStatement *) { stop("ReturnStatement"); } + +bool AstDumper::visit(AST::YieldExpression *el) { + start(QLatin1String("YieldExpression isYieldStar=%1 yieldToken=%2") + .arg(boolStr(el->isYieldStar), loc(el->yieldToken))); + return true; +} +void AstDumper::endVisit(AST::YieldExpression *) { stop("YieldExpression"); } + +bool AstDumper::visit(AST::WithStatement *el) { + start(QLatin1String("WithStatement withToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->withToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::WithStatement *) { stop("WithStatement"); } + +bool AstDumper::visit(AST::SwitchStatement *el) { + start(QLatin1String("SwitchStatement switchToken=%1 lparenToken=%2 rparenToken=%3") + .arg(loc(el->switchToken), loc(el->lparenToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::SwitchStatement *) { stop("SwitchStatement"); } + +bool AstDumper::visit(AST::CaseBlock *el) { + start(QLatin1String("CaseBlock lbraceToken=%1 rbraceToken=%2") + .arg(loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::CaseBlock *) { stop("CaseBlock"); } + +bool AstDumper::visit(AST::CaseClauses *) { + start(QLatin1String("CaseClauses")); + return true; +} +void AstDumper::endVisit(AST::CaseClauses *) { stop("CaseClauses"); } + +bool AstDumper::visit(AST::CaseClause *el) { + start(QLatin1String("CaseClause caseToken=%1 colonToken=%2") + .arg(loc(el->caseToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::CaseClause *) { stop("CaseClause"); } + +bool AstDumper::visit(AST::DefaultClause *el) { + start(QLatin1String("DefaultClause defaultToken=%1 colonToken=%2") + .arg(loc(el->defaultToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::DefaultClause *) { stop("DefaultClause"); } + +bool AstDumper::visit(AST::LabelledStatement *el) { + start(QLatin1String("LabelledStatement label=%1 identifierToken=%2 colonToken=%3") + .arg(qs(el->label), loc(el->identifierToken), loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::LabelledStatement *) { stop("LabelledStatement"); } + +bool AstDumper::visit(AST::ThrowStatement *el) { + start(QLatin1String("ThrowStatement throwToken=%1 semicolonToken=%2") + .arg(loc(el->throwToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::ThrowStatement *) { stop("ThrowStatement"); } + +bool AstDumper::visit(AST::TryStatement *el) { + start(QLatin1String("TryStatement tryToken=%1") + .arg(loc(el->tryToken))); + return true; +} +void AstDumper::endVisit(AST::TryStatement *) { stop("TryStatement"); } + +bool AstDumper::visit(AST::Catch *el) { + start(QLatin1String("Catch catchToken=%1 lparenToken=%2 identifierToken=%3 rparenToken=%4") + .arg(loc(el->catchToken), loc(el->lparenToken), loc(el->identifierToken), loc(el->rparenToken))); + return true; +} +void AstDumper::endVisit(AST::Catch *) { stop("Catch"); } + +bool AstDumper::visit(AST::Finally *el) { + start(QLatin1String("Finally finallyToken=%1") + .arg(loc(el->finallyToken))); + return true; +} +void AstDumper::endVisit(AST::Finally *) { stop("Finally"); } + +bool AstDumper::visit(AST::FunctionDeclaration *el) { + start(QLatin1String("FunctionDeclaration name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 " + "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9") + .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken), + loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken), + loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::FunctionDeclaration *) { stop("FunctionDeclaration"); } + +bool AstDumper::visit(AST::FunctionExpression *el) { + start(QLatin1String("FunctionExpression name=%1 isArrowFunction=%2 isGenerator=%3 functionToken=%4 " + "identifierToken=%5 lparenToken=%6 rparenToken=%7 lbraceToken=%8 rbraceToken=%9") + .arg(qs(el->name), boolStr(el->isArrowFunction), boolStr(el->isGenerator), loc(el->functionToken), + loc(el->identifierToken), loc(el->lparenToken), loc(el->rparenToken), loc(el->lbraceToken), + loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::FunctionExpression *) { stop("FunctionExpression"); } + +bool AstDumper::visit(AST::FormalParameterList *) { + start(QLatin1String("FormalParameterList")); + return true; +} +void AstDumper::endVisit(AST::FormalParameterList *) { stop("FormalParameterList"); } + +bool AstDumper::visit(AST::ClassExpression *el) { + start(QLatin1String("ClassExpression name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5") + .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::ClassExpression *) { stop("ClassExpression"); } + +bool AstDumper::visit(AST::ClassDeclaration *el) { + start(QLatin1String("ClassDeclaration name=%1 classToken=%2 identifierToken=%3 lbraceToken=%4 rbraceToken=%5") + .arg(qs(el->name), loc(el->classToken), loc(el->identifierToken), loc(el->lbraceToken), loc(el->rbraceToken))); + return true; +} +void AstDumper::endVisit(AST::ClassDeclaration *) { stop("ClassDeclaration"); } + +bool AstDumper::visit(AST::ClassElementList *el) { + start(QLatin1String("ClassElementList isStatic=%1") + .arg(boolStr(el->isStatic))); + return true; +} +void AstDumper::endVisit(AST::ClassElementList *) { stop("ClassElementList"); } + +bool AstDumper::visit(AST::Program *) { + start(QLatin1String("Program")); + return true; +} +void AstDumper::endVisit(AST::Program *) { stop("Program"); } + +bool AstDumper::visit(AST::NameSpaceImport *el) { + start(QLatin1String("NameSpaceImport starToken=%1 importedBindingToken=%2 importedBinding=%3") + .arg(loc(el->starToken), loc(el->importedBindingToken), qs(el->importedBinding))); + return true; +} +void AstDumper::endVisit(AST::NameSpaceImport *) { stop("NameSpaceImport"); } + +bool AstDumper::visit(AST::ImportSpecifier *el) { + start(QLatin1String("ImportSpecifier identifierToken=%1 importedBindingToken=%2 identifier=%3 importedBinding=%4") + .arg(loc(el->identifierToken), loc(el->importedBindingToken), qs(el->identifier), qs(el->importedBinding))); + return true; +} +void AstDumper::endVisit(AST::ImportSpecifier *) { stop("ImportSpecifier"); } + +bool AstDumper::visit(AST::ImportsList *el) { + start(QLatin1String("ImportsList importSpecifierToken=%1") + .arg(loc(el->importSpecifierToken))); + return true; +} +void AstDumper::endVisit(AST::ImportsList *) { stop("ImportsList"); } + +bool AstDumper::visit(AST::NamedImports *el) { + start(QLatin1String("NamedImports leftBraceToken=%1 rightBraceToken=%2") + .arg(loc(el->leftBraceToken), loc(el->rightBraceToken))); + return true; +} +void AstDumper::endVisit(AST::NamedImports *) { stop("NamedImports"); } + +bool AstDumper::visit(AST::FromClause *el) { + start(QLatin1String("FromClause fromToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3") + .arg(loc(el->fromToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier))); + return true; +} +void AstDumper::endVisit(AST::FromClause *) { stop("FromClause"); } + +bool AstDumper::visit(AST::ImportClause *el) { + start(QLatin1String("ImportClause importedDefaultBindingToken=%1 importedDefaultBinding=%2") + .arg(loc(el->importedDefaultBindingToken), qs(el->importedDefaultBinding))); + return true; +} +void AstDumper::endVisit(AST::ImportClause *) { stop("ImportClause"); } + +bool AstDumper::visit(AST::ImportDeclaration *el) { + start(QLatin1String("ImportDeclaration importToken=%1 moduleSpecifierToken=%2 moduleSpecifier=%3") + .arg(loc(el->importToken), loc(el->moduleSpecifierToken), qs(el->moduleSpecifier))); + return true; +} +void AstDumper::endVisit(AST::ImportDeclaration *) { stop("ImportDeclaration"); } + +bool AstDumper::visit(AST::ExportSpecifier *el) { + start(QLatin1String("ExportSpecifier identifierToken=%1 exportedIdentifierToken=%2 identifier=%3 exportedIdentifier=%4") + .arg(loc(el->identifierToken), loc(el->exportedIdentifierToken), qs(el->identifier), qs(el->exportedIdentifier))); + return true; +} +void AstDumper::endVisit(AST::ExportSpecifier *) { stop("ExportSpecifier"); } + +bool AstDumper::visit(AST::ExportsList *) { + start(QLatin1String("ExportsList")); + return true; +} +void AstDumper::endVisit(AST::ExportsList *) { stop("ExportsList"); } + +bool AstDumper::visit(AST::ExportClause *el) { + start(QLatin1String("ExportClause leftBraceToken=%1 rightBraceToken=%2") + .arg(loc(el->leftBraceToken), loc(el->rightBraceToken))); + return true; +} +void AstDumper::endVisit(AST::ExportClause *) { stop("ExportClause"); } + +bool AstDumper::visit(AST::ExportDeclaration *el) { + start(QLatin1String("ExportDeclaration exportToken=%1 exportAll=%2 exportDefault=%3") + .arg(loc(el->exportToken), boolStr(el->exportAll), boolStr(el->exportDefault))); + return true; +} +void AstDumper::endVisit(AST::ExportDeclaration *) { stop("ExportDeclaration"); } + +bool AstDumper::visit(AST::ESModule *) { + start(QLatin1String("ESModule")); + return true; +} +void AstDumper::endVisit(AST::ESModule *) { stop("ESModule"); } + +bool AstDumper::visit(AST::DebuggerStatement *el) { + start(QLatin1String("DebuggerStatement debuggerToken=%1 semicolonToken=%2") + .arg(loc(el->debuggerToken), loc(el->semicolonToken))); + return true; +} +void AstDumper::endVisit(AST::DebuggerStatement *) { stop("DebuggerStatement"); } + +bool AstDumper::visit(AST::Type *) { + start(QLatin1String("Type")); + return true; +} +void AstDumper::endVisit(AST::Type *) { stop("Type"); } + +bool AstDumper::visit(AST::TypeArgumentList *) { + start(QLatin1String("TypeArgumentList")); + return true; +} +void AstDumper::endVisit(AST::TypeArgumentList *) { stop("TypeArgumentList"); } + +bool AstDumper::visit(AST::TypeAnnotation *el) { + start(QLatin1String("TypeAnnotation colonToken=%1") + .arg(loc(el->colonToken))); + return true; +} +void AstDumper::endVisit(AST::TypeAnnotation *) { stop("TypeAnnotation"); } + +void AstDumper::throwRecursionDepthError() +{ + qDebug() << "Maximum statement or expression depth exceeded in AstDumper"; +} + +bool AstDumper::dumpNode() { + return options & DumperOptions::DumpNode; +} + +bool AstDumper::noLocations() { + return options & DumperOptions::NoLocations; +} + +bool AstDumper::noAnnotations() { + return options & DumperOptions::NoAnnotations; +} + +} // end namespace QQmlJS + +QT_END_NAMESPACE diff --git a/tests/auto/shared/qqmljsastdumper.h b/tests/auto/shared/qqmljsastdumper.h new file mode 100644 index 0000000000..d8d19e351d --- /dev/null +++ b/tests/auto/shared/qqmljsastdumper.h @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +**/ +#ifndef ASTDUMPER_H +#define ASTDUMPER_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qqmljsglobal_p.h> +#include <private/qqmljsastvisitor_p.h> +#include <QtCore/QString> +#include <functional> +#include <ostream> + +QT_BEGIN_NAMESPACE +class QDebug; + +namespace QQmlJS { + +enum class DumperOptions { + None=0, + NoLocations=0x1, + NoAnnotations=0x2, + DumpNode=0x4 +}; +bool operator & (DumperOptions lhs, DumperOptions rhs); +DumperOptions operator | (DumperOptions lhs, DumperOptions rhs); + +// no export, currently just a supporting file... +class AstDumper: public AST::BaseVisitor +{ +public: + static QString printNode2(AST::Node *); + + static QString diff(AST::Node *n1, AST::Node *n2, int nContext=3, DumperOptions opt=DumperOptions::None, int indent=0); + static QString printNode(AST::Node *n, DumperOptions opt=DumperOptions::None, int indent=1, int baseIndent=0); + + AstDumper(const std::function <void (const QString &)> &dumper, DumperOptions options=DumperOptions::None, + int indent=1, int baseIndent=0); + + void start(const QString &str); + void start(const char *str); + void stop(const QString &str); + void stop(const char *str); + + QString qs(const QString &s); + QString qs(const char *s); + QString qs(const QStringRef &s); + + QString loc(const AST::SourceLocation &s); + + QString boolStr(bool v); + + bool preVisit(AST::Node *el) override; + void postVisit(AST::Node *el) override; + + // Ui + bool visit(AST::UiProgram *el) override; + bool visit(AST::UiHeaderItemList *) override; + bool visit(AST::UiPragma *el) override; + bool visit(AST::UiImport *el) override; + bool visit(AST::UiPublicMember *el) override; + bool visit(AST::UiSourceElement *) override; + bool visit(AST::UiObjectDefinition *) override; + bool visit(AST::UiObjectInitializer *) override; + bool visit(AST::UiObjectBinding *) override; + bool visit(AST::UiScriptBinding *) override; + bool visit(AST::UiArrayBinding *) override; + bool visit(AST::UiParameterList *) override; + bool visit(AST::UiObjectMemberList *) override; + bool visit(AST::UiArrayMemberList *) override; + bool visit(AST::UiQualifiedId *) override; + bool visit(AST::UiEnumDeclaration *) override; + bool visit(AST::UiEnumMemberList *) override; + bool visit(AST::UiVersionSpecifier *) override; + bool visit(AST::UiInlineComponent *) override; + bool visit(AST::UiRequired *) override; + bool visit(AST::UiAnnotation *) override; + bool visit(AST::UiAnnotationList *) override; + + void endVisit(AST::UiProgram *) override; + void endVisit(AST::UiImport *) override; + void endVisit(AST::UiHeaderItemList *) override; + void endVisit(AST::UiPragma *) override; + void endVisit(AST::UiPublicMember *) override; + void endVisit(AST::UiSourceElement *) override; + void endVisit(AST::UiObjectDefinition *) override; + void endVisit(AST::UiObjectInitializer *) override; + void endVisit(AST::UiObjectBinding *) override; + void endVisit(AST::UiScriptBinding *) override; + void endVisit(AST::UiArrayBinding *) override; + void endVisit(AST::UiParameterList *) override; + void endVisit(AST::UiObjectMemberList *) override; + void endVisit(AST::UiArrayMemberList *) override; + void endVisit(AST::UiQualifiedId *) override; + void endVisit(AST::UiEnumDeclaration *) override; + void endVisit(AST::UiEnumMemberList *) override; + void endVisit(AST::UiVersionSpecifier *) override; + void endVisit(AST::UiInlineComponent *) override; + void endVisit(AST::UiRequired *) override; + void endVisit(AST::UiAnnotation *) override; + void endVisit(AST::UiAnnotationList *) override; + + // QQmlJS + bool visit(AST::ThisExpression *) override; + void endVisit(AST::ThisExpression *) override; + + bool visit(AST::IdentifierExpression *) override; + void endVisit(AST::IdentifierExpression *) override; + + bool visit(AST::NullExpression *) override; + void endVisit(AST::NullExpression *) override; + + bool visit(AST::TrueLiteral *) override; + void endVisit(AST::TrueLiteral *) override; + + bool visit(AST::FalseLiteral *) override; + void endVisit(AST::FalseLiteral *) override; + + bool visit(AST::SuperLiteral *) override; + void endVisit(AST::SuperLiteral *) override; + + bool visit(AST::StringLiteral *) override; + void endVisit(AST::StringLiteral *) override; + + bool visit(AST::TemplateLiteral *) override; + void endVisit(AST::TemplateLiteral *) override; + + bool visit(AST::NumericLiteral *) override; + void endVisit(AST::NumericLiteral *) override; + + bool visit(AST::RegExpLiteral *) override; + void endVisit(AST::RegExpLiteral *) override; + + bool visit(AST::ArrayPattern *) override; + void endVisit(AST::ArrayPattern *) override; + + bool visit(AST::ObjectPattern *) override; + void endVisit(AST::ObjectPattern *) override; + + bool visit(AST::PatternElementList *) override; + void endVisit(AST::PatternElementList *) override; + + bool visit(AST::PatternPropertyList *) override; + void endVisit(AST::PatternPropertyList *) override; + + bool visit(AST::PatternElement *) override; + void endVisit(AST::PatternElement *) override; + + bool visit(AST::PatternProperty *) override; + void endVisit(AST::PatternProperty *) override; + + bool visit(AST::Elision *) override; + void endVisit(AST::Elision *) override; + + bool visit(AST::NestedExpression *) override; + void endVisit(AST::NestedExpression *) override; + + bool visit(AST::IdentifierPropertyName *) override; + void endVisit(AST::IdentifierPropertyName *) override; + + bool visit(AST::StringLiteralPropertyName *) override; + void endVisit(AST::StringLiteralPropertyName *) override; + + bool visit(AST::NumericLiteralPropertyName *) override; + void endVisit(AST::NumericLiteralPropertyName *) override; + + bool visit(AST::ComputedPropertyName *) override; + void endVisit(AST::ComputedPropertyName *) override; + + bool visit(AST::ArrayMemberExpression *) override; + void endVisit(AST::ArrayMemberExpression *) override; + + bool visit(AST::FieldMemberExpression *) override; + void endVisit(AST::FieldMemberExpression *) override; + + bool visit(AST::TaggedTemplate *) override; + void endVisit(AST::TaggedTemplate *) override; + + bool visit(AST::NewMemberExpression *) override; + void endVisit(AST::NewMemberExpression *) override; + + bool visit(AST::NewExpression *) override; + void endVisit(AST::NewExpression *) override; + + bool visit(AST::CallExpression *) override; + void endVisit(AST::CallExpression *) override; + + bool visit(AST::ArgumentList *) override; + void endVisit(AST::ArgumentList *) override; + + bool visit(AST::PostIncrementExpression *) override; + void endVisit(AST::PostIncrementExpression *) override; + + bool visit(AST::PostDecrementExpression *) override; + void endVisit(AST::PostDecrementExpression *) override; + + bool visit(AST::DeleteExpression *) override; + void endVisit(AST::DeleteExpression *) override; + + bool visit(AST::VoidExpression *) override; + void endVisit(AST::VoidExpression *) override; + + bool visit(AST::TypeOfExpression *) override; + void endVisit(AST::TypeOfExpression *) override; + + bool visit(AST::PreIncrementExpression *) override; + void endVisit(AST::PreIncrementExpression *) override; + + bool visit(AST::PreDecrementExpression *) override; + void endVisit(AST::PreDecrementExpression *) override; + + bool visit(AST::UnaryPlusExpression *) override; + void endVisit(AST::UnaryPlusExpression *) override; + + bool visit(AST::UnaryMinusExpression *) override; + void endVisit(AST::UnaryMinusExpression *) override; + + bool visit(AST::TildeExpression *) override; + void endVisit(AST::TildeExpression *) override; + + bool visit(AST::NotExpression *) override; + void endVisit(AST::NotExpression *) override; + + bool visit(AST::BinaryExpression *) override; + void endVisit(AST::BinaryExpression *) override; + + bool visit(AST::ConditionalExpression *) override; + void endVisit(AST::ConditionalExpression *) override; + + bool visit(AST::Expression *) override; + void endVisit(AST::Expression *) override; + + bool visit(AST::Block *) override; + void endVisit(AST::Block *) override; + + bool visit(AST::StatementList *) override; + void endVisit(AST::StatementList *) override; + + bool visit(AST::VariableStatement *) override; + void endVisit(AST::VariableStatement *) override; + + bool visit(AST::VariableDeclarationList *) override; + void endVisit(AST::VariableDeclarationList *) override; + + bool visit(AST::EmptyStatement *) override; + void endVisit(AST::EmptyStatement *) override; + + bool visit(AST::ExpressionStatement *) override; + void endVisit(AST::ExpressionStatement *) override; + + bool visit(AST::IfStatement *) override; + void endVisit(AST::IfStatement *) override; + + bool visit(AST::DoWhileStatement *) override; + void endVisit(AST::DoWhileStatement *) override; + + bool visit(AST::WhileStatement *) override; + void endVisit(AST::WhileStatement *) override; + + bool visit(AST::ForStatement *) override; + void endVisit(AST::ForStatement *) override; + + bool visit(AST::ForEachStatement *) override; + void endVisit(AST::ForEachStatement *) override; + + bool visit(AST::ContinueStatement *) override; + void endVisit(AST::ContinueStatement *) override; + + bool visit(AST::BreakStatement *) override; + void endVisit(AST::BreakStatement *) override; + + bool visit(AST::ReturnStatement *) override; + void endVisit(AST::ReturnStatement *) override; + + bool visit(AST::YieldExpression *) override; + void endVisit(AST::YieldExpression *) override; + + bool visit(AST::WithStatement *) override; + void endVisit(AST::WithStatement *) override; + + bool visit(AST::SwitchStatement *) override; + void endVisit(AST::SwitchStatement *) override; + + bool visit(AST::CaseBlock *) override; + void endVisit(AST::CaseBlock *) override; + + bool visit(AST::CaseClauses *) override; + void endVisit(AST::CaseClauses *) override; + + bool visit(AST::CaseClause *) override; + void endVisit(AST::CaseClause *) override; + + bool visit(AST::DefaultClause *) override; + void endVisit(AST::DefaultClause *) override; + + bool visit(AST::LabelledStatement *) override; + void endVisit(AST::LabelledStatement *) override; + + bool visit(AST::ThrowStatement *) override; + void endVisit(AST::ThrowStatement *) override; + + bool visit(AST::TryStatement *) override; + void endVisit(AST::TryStatement *) override; + + bool visit(AST::Catch *) override; + void endVisit(AST::Catch *) override; + + bool visit(AST::Finally *) override; + void endVisit(AST::Finally *) override; + + bool visit(AST::FunctionDeclaration *) override; + void endVisit(AST::FunctionDeclaration *) override; + + bool visit(AST::FunctionExpression *) override; + void endVisit(AST::FunctionExpression *) override; + + bool visit(AST::FormalParameterList *) override; + void endVisit(AST::FormalParameterList *) override; + + bool visit(AST::ClassExpression *) override; + void endVisit(AST::ClassExpression *) override; + + bool visit(AST::ClassDeclaration *) override; + void endVisit(AST::ClassDeclaration *) override; + + bool visit(AST::ClassElementList *) override; + void endVisit(AST::ClassElementList *) override; + + bool visit(AST::Program *) override; + void endVisit(AST::Program *) override; + + bool visit(AST::NameSpaceImport *) override; + void endVisit(AST::NameSpaceImport *) override; + + bool visit(AST::ImportSpecifier *) override; + void endVisit(AST::ImportSpecifier *) override; + + bool visit(AST::ImportsList *) override; + void endVisit(AST::ImportsList *) override; + + bool visit(AST::NamedImports *) override; + void endVisit(AST::NamedImports *) override; + + bool visit(AST::FromClause *) override; + void endVisit(AST::FromClause *) override; + + bool visit(AST::ImportClause *) override; + void endVisit(AST::ImportClause *) override; + + bool visit(AST::ImportDeclaration *) override; + void endVisit(AST::ImportDeclaration *) override; + + bool visit(AST::ExportSpecifier *) override; + void endVisit(AST::ExportSpecifier *) override; + + bool visit(AST::ExportsList *) override; + void endVisit(AST::ExportsList *) override; + + bool visit(AST::ExportClause *) override; + void endVisit(AST::ExportClause *) override; + + bool visit(AST::ExportDeclaration *) override; + void endVisit(AST::ExportDeclaration *) override; + + bool visit(AST::ESModule *) override; + void endVisit(AST::ESModule *) override; + + bool visit(AST::DebuggerStatement *) override; + void endVisit(AST::DebuggerStatement *) override; + + bool visit(AST::Type *) override; + void endVisit(AST::Type *) override; + + bool visit(AST::TypeArgumentList *) override; + void endVisit(AST::TypeArgumentList *) override; + + bool visit(AST::TypeAnnotation *) override; + void endVisit(AST::TypeAnnotation *) override; + + void throwRecursionDepthError() override; + +private: + // attributes + std::function <void (const QString &)> dumper; + DumperOptions options = DumperOptions::None; + int indent = 0; + int baseIndent = 0; + bool dumpNode(); + bool noLocations(); + bool noAnnotations(); +}; + +QDebug operator<<(QDebug d, AST::Node *n); + +std::ostream &operator<<(std::ostream &stream, AST::Node *n); + +} // namespace AST + +QT_END_NAMESPACE + +#endif // ASTDUMPER_H |