diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-23 10:03:00 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-27 10:42:06 +0100 |
commit | ddba87612d2be25863135669e81bc3391dc40e82 (patch) | |
tree | 839f35beafff47adeb1df12d2958cf8f36e9704a /tests/auto | |
parent | 08c086b9977d9275c53b58d6ffc766740e248c2c (diff) |
QML: Turn singleton/type mismatch into a run time type error
There are many ways to "hide" the qmldir from the engine at run time,
which turns singletons into regular types. While all of this is invalid,
we should not assert on it, but rather produce a legible warning.
Furthermore, sharpen the importing of extra modules from qrc as implicit
imports. We should really only import modules the file in question can
ever be part of. Otherwise we needlessly produce the above situation and
hide legitimate warning messages.
Amends commit 7517c1b3ae9aa92f36b19d74a4b2de5e8531309b.
Now we need to teach our tools about the default import paths in the
resorurce file system. They cannot guess any type they may find in any
resource file anymore.
Pick-to: 6.5
Task-number: QTBUG-106929
Change-Id: Ic8c02396d10830a7f461e8a81649bb8c9a1add1f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'tests/auto')
10 files changed, 74 insertions, 18 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 34865cb43c..0737d77005 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -105,6 +105,8 @@ set(qml_files functionReturningVoid.qml functionTakingVar.qml globals.qml + hidden/Main.qml + hidden/Style.qml idAccess.qml immediateQuit.qml imports/QmlBench/Globals.qml @@ -209,6 +211,9 @@ set_source_files_properties("shared/Slider.qml" PROPERTIES QT_RESOURCE_ALIAS "Slider.qml" ) +set_source_files_properties("hidden/Style.qml" + PROPERTIES QT_QML_SINGLETON_TYPE TRUE) + qt_add_library(codegen_test_module STATIC) qt_autogen_tools_initial_setup(codegen_test_module) diff --git a/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml b/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml new file mode 100644 index 0000000000..dd97728433 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/hidden/Main.qml @@ -0,0 +1,5 @@ +import QtQuick + +QtObject { + property color c: Style.windowColor +} diff --git a/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml b/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml new file mode 100644 index 0000000000..8bff4ef96b --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/hidden/Style.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQuick + +QtObject { + readonly property color windowColor: "#4CAF50" +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 8b2b4bbbf4..dd30931868 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -163,6 +163,7 @@ private slots: void equalityQObjects(); void dateConversions(); void valueTypeBehavior(); + void invisibleSingleton(); }; void tst_QmlCppCodegen::initTestCase() @@ -3182,6 +3183,22 @@ void tst_QmlCppCodegen::valueTypeBehavior() QCOMPARE(o2->property("f").toDouble(), 5.0); } +void tst_QmlCppCodegen::invisibleSingleton() +{ + QQmlEngine engine; + const QUrl copy(u"qrc:/qt/qml/TestTypes/hidden/Main.qml"_s); + QQmlComponent c(&engine, copy); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QTest::ignoreMessage( + QtWarningMsg, + "qrc:/qt/qml/TestTypes/hidden/Main.qml:4:5: " + "Unable to assign [undefined] to QColor"); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor"))); +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" diff --git a/tests/auto/qml/qmllint/data/implicitImportResource.qrc b/tests/auto/qml/qmllint/data/implicitImportResource.qrc index e01bf3bb3e..026c8c4d4f 100644 --- a/tests/auto/qml/qmllint/data/implicitImportResource.qrc +++ b/tests/auto/qml/qmllint/data/implicitImportResource.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/"> + <file>additionalImplicitImport.qml</file> <file alias="qmldir">Things/qmldir</file> </qresource> </RCC> diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index ce5e24ed5e..80c3d17d78 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -397,13 +397,29 @@ void TestQmllint::autoqmltypes() void TestQmllint::resources() { - callQmllint(testFile("resource.qml"), true, nullptr, {}, {}, { testFile("resource.qrc") }); - callQmllint(testFile("badResource.qml"), false, nullptr, {}, {}, { testFile("resource.qrc") }); + { + // We need to clear the import cache before we add a qrc file with different + // contents for the same paths. + const auto guard = qScopeGuard([this]() { m_linter.clearCache(); }); + + callQmllint(testFile("resource.qml"), true, nullptr, {}, {}, { testFile("resource.qrc") }); + callQmllint(testFile("badResource.qml"), false, nullptr, {}, {}, { testFile("resource.qrc") }); + } + + callQmllint(testFile("resource.qml"), false); callQmllint(testFile("badResource.qml"), true); - callQmllint(testFile("T/b.qml"), true, nullptr, {}, {}, { testFile("T/a.qrc") }); - callQmllint(testFile("relPathQrc/Foo/Thing.qml"), true, nullptr, {}, {}, + + { + const auto guard = qScopeGuard([this]() { m_linter.clearCache(); }); + callQmllint(testFile("T/b.qml"), true, nullptr, {}, {}, { testFile("T/a.qrc") }); + } + + { + const auto guard = qScopeGuard([this]() { m_linter.clearCache(); }); + callQmllint(testFile("relPathQrc/Foo/Thing.qml"), true, nullptr, {}, {}, { testFile("relPathQrc/resources.qrc") }); + } } void TestQmllint::dirtyQmlCode_data() @@ -1367,13 +1383,13 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs if (type == LintFile) { lintResult = m_linter.lintFile( - lintedFile, nullptr, true, warnings ? &jsonOutput : nullptr, + lintedFile, nullptr, true, &jsonOutput, defaultImports == UseDefaultImports ? m_defaultImportPaths + importPaths : importPaths, qmldirFiles, resources, categories != nullptr ? *categories : QQmlJSLogger::defaultCategories()); } else { - lintResult = m_linter.lintModule(fileToLint, true, warnings ? &jsonOutput : nullptr); + lintResult = m_linter.lintModule(fileToLint, true, &jsonOutput); } bool success = lintResult == QQmlJSLinter::LintSuccess; @@ -1602,8 +1618,11 @@ void TestQmllint::settingsFile() void TestQmllint::additionalImplicitImport() { + // We're polluting the resource file system here, so let's clean up afterwards. + const auto guard = qScopeGuard([this]() {m_linter.clearCache(); }); runTest("additionalImplicitImport.qml", Result::clean(), {}, {}, { testFile("implicitImportResource.qrc") }); + } void TestQmllint::attachedPropertyReuse() diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml index a2a100ab3b..6570134ff9 100644 --- a/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml +++ b/tests/auto/qml/qmltc_qprocess/data/invalidSignalHandlers.qml @@ -1,3 +1,4 @@ +import QmltcQProcessTests TypeWithSignals { diff --git a/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml b/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml index d48a4ee186..210096b75f 100644 --- a/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml +++ b/tests/auto/qml/qmltc_qprocess/data/singletonUncreatable.qml @@ -1,4 +1,5 @@ pragma Singleton +import QmltcQProcessTests UncreatableType { diff --git a/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml b/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml index aad6ef3421..1a0e436665 100644 --- a/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml +++ b/tests/auto/qml/qmltc_qprocess/data/uncreatable.qml @@ -1,4 +1,5 @@ import QtQuick +import QmltcQProcessTests Item { // Illegal cases: diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp index 1cea44206f..7f12f29342 100644 --- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp +++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp @@ -193,20 +193,20 @@ void tst_qmltc_qprocess::singleton() { { const auto errors = runQmltc(u"singletonUncreatable.qml"_s, false); - QVERIFY(errors.contains("singletonUncreatable.qml:3:1: Type UncreatableType is not " + QVERIFY(errors.contains("singletonUncreatable.qml:4:1: Type UncreatableType is not " "creatable. [uncreatable-type]")); } { const auto errors = runQmltc(u"uncreatable.qml"_s, false); QVERIFY(errors.contains( - "uncreatable.qml:5:5: Type UncreatableType is not creatable. [uncreatable-type]")); - QVERIFY(errors.contains("uncreatable.qml:6:5: Singleton Type SingletonThing is not " + "uncreatable.qml:6:5: Type UncreatableType is not creatable. [uncreatable-type]")); + QVERIFY(errors.contains("uncreatable.qml:7:5: Singleton Type SingletonThing is not " "creatable. [uncreatable-type]")); - QVERIFY(errors.contains("uncreatable.qml:7:5: Singleton Type SingletonType is not " + QVERIFY(errors.contains("uncreatable.qml:8:5: Singleton Type SingletonType is not " "creatable. [uncreatable-type]")); - QVERIFY(errors.contains("uncreatable.qml:9:18: Singleton Type SingletonThing is not " + QVERIFY(errors.contains("uncreatable.qml:10:18: Singleton Type SingletonThing is not " "creatable. [uncreatable-type]")); - QVERIFY(errors.contains("uncreatable.qml:14:18: Singleton Type SingletonType is not " + QVERIFY(errors.contains("uncreatable.qml:15:18: Singleton Type SingletonType is not " "creatable. [uncreatable-type]")); QVERIFY(!errors.contains("NotSingletonType")); } @@ -247,17 +247,17 @@ void tst_qmltc_qprocess::invalidSignalHandlers() { const auto errors = runQmltc(u"invalidSignalHandlers.qml"_s, false); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:4:5: Type QFont of parameter in signal called signalWithConstPointerToGadget should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadget. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:5:5: Type QFont of parameter in signal called signalWithConstPointerToGadget should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadget. [signal-handler-parameters]"_s)); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:5:5: Type QFont of parameter in signal called signalWithConstPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadgetConst. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:6:5: Type QFont of parameter in signal called signalWithConstPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithConstPointerToGadgetConst. [signal-handler-parameters]"_s)); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:6:5: Type QFont of parameter in signal called signalWithPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithPointerToGadgetConst. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:7:5: Type QFont of parameter in signal called signalWithPointerToGadgetConst should be passed by value or const reference to be able to compile onSignalWithPointerToGadgetConst. [signal-handler-parameters]"_s)); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:7:5: Type QFont of parameter in signal called signalWithPointerToGadget should be passed by value or const reference to be able to compile onSignalWithPointerToGadget. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:8:5: Type QFont of parameter in signal called signalWithPointerToGadget should be passed by value or const reference to be able to compile onSignalWithPointerToGadget. [signal-handler-parameters]"_s)); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:8:5: Type int of parameter in signal called signalWithPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithPrimitivePointer. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:9:5: Type int of parameter in signal called signalWithPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithPrimitivePointer. [signal-handler-parameters]"_s)); QVERIFY(errors.contains( - u"invalidSignalHandlers.qml:9:5: Type int of parameter in signal called signalWithConstPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithConstPrimitivePointer. [signal-handler-parameters]"_s)); + u"invalidSignalHandlers.qml:10:5: Type int of parameter in signal called signalWithConstPrimitivePointer should be passed by value or const reference to be able to compile onSignalWithConstPrimitivePointer. [signal-handler-parameters]"_s)); } } |