From: Matthew Vogt Date: Fri, 13 Jul 2012 05:34:05 +0000 (+1000) Subject: Select appropriate version for located module components X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=20cecd7b003f27485789e93b4c2b6f5f734e5bea;p=konrad%2Fqtdeclarative.git Select appropriate version for located module components When a located module is imported with a version specifier, ensure that the components resolved from that module use the appropriate version. Task-number: QTBUG-26473 Change-Id: I33209ddef3fe9bb0ab9d096dfe19aff233744afc Reviewed-by: Chris Adams --- diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 00ea8c5..55c07ac 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -508,41 +508,43 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } } - bool typeWasDeclaredInQmldir = false; - if (!qmlDirComponents.isEmpty()) { - QQmlDirComponents::ConstIterator it = qmlDirComponents.find(type); - if (it != qmlDirComponents.end()) { - typeWasDeclaredInQmldir = true; - // first found is last inserted - process in reverse - QQmlDirComponents::ConstIterator begin = it; - while (++it != qmlDirComponents.end() && it.key() == type) {} - do { - --it; - const QQmlDirParser::Component &c = *it; - - // importing version -1 means import ALL versions - if ((majversion == -1) || (c.majorVersion == majversion && - minversion >= c.minorVersion)) { - - QString candidate = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); + QQmlDirComponents::ConstIterator it = qmlDirComponents.find(type), end = qmlDirComponents.end(); + if (it != end) { + QString componentUrl; + QQmlDirComponents::ConstIterator candidate = end; + for ( ; it != end && it.key() == type; ++it) { + const QQmlDirParser::Component &c = *it; + + // importing version -1 means import ALL versions + if ((majversion == -1) || + (c.majorVersion == majversion && c.minorVersion <= minversion)) { + // Is this better than the previous candidate? + if ((candidate == end) || + (c.majorVersion > candidate->majorVersion) || + ((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) { + componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); if (c.internal && base) { - if (resolveLocalUrl(*base, c.fileName) != candidate) + if (resolveLocalUrl(*base, c.fileName) != componentUrl) continue; // failed attempt to access an internal type } - if (base && *base == candidate) { + if (base && (*base == componentUrl)) { if (typeRecursionDetected) *typeRecursionDetected = true; continue; // no recursion } - if (url_return) - *url_return = candidate; - return true; + + // This is our best candidate so far + candidate = it; } - } while (it != begin); + } } - } - if (!typeWasDeclaredInQmldir && !isLibrary) { + if (candidate != end) { + if (url_return) + *url_return = componentUrl; + return true; + } + } else if (!isLibrary) { QString qmlUrl = url + QString::fromRawData(type.constData(), type.length()) + dotqml_string; bool exists = false; @@ -554,7 +556,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } if (exists) { - if (base && *base == qmlUrl) { // no recursion + if (base && (*base == qmlUrl)) { // no recursion if (typeRecursionDetected) *typeRecursionDetected = true; } else { diff --git a/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.0.qml b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.0.qml new file mode 100644 index 0000000..ad757fd --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.0.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Item { + property int majorVersion: 1 + property int minorVersion: 0 +} diff --git a/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.1.qml b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.1.qml new file mode 100644 index 0000000..531912b --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.1.1.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Item { + property int majorVersion: 1 + property int minorVersion: 1 +} diff --git a/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.2.0.qml b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.2.0.qml new file mode 100644 index 0000000..74c9948 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/localModule/TestComponent.2.0.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Item { + property int majorVersion: 2 + property int minorVersion: 0 +} diff --git a/tests/auto/qml/qqmlmoduleplugin/data/localModule/qmldir b/tests/auto/qml/qqmlmoduleplugin/data/localModule/qmldir new file mode 100644 index 0000000..052e2d9 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/localModule/qmldir @@ -0,0 +1,3 @@ +TestComponent 1.0 TestComponent.1.0.qml +TestComponent 1.1 TestComponent.1.1.qml +TestComponent 2.0 TestComponent.2.0.qml diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index b649075..67b3d00 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -72,6 +72,8 @@ private slots: void implicitQmldir_data(); void importsNested(); void importsNested_data(); + void importLocalModule(); + void importLocalModule_data(); private: QString m_importsDirectory; @@ -395,6 +397,55 @@ void tst_qqmlmoduleplugin::importsNested() } } +void tst_qqmlmoduleplugin::importLocalModule() +{ + QFETCH(QString, qml); + QFETCH(int, majorVersion); + QFETCH(int, minorVersion); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(qml.toUtf8(), testFileUrl("empty.qml")); + + QScopedPointer object(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->property("majorVersion").value(), majorVersion); + QCOMPARE(object->property("minorVersion").value(), minorVersion); +} + +void tst_qqmlmoduleplugin::importLocalModule_data() +{ + QTest::addColumn("qml"); + QTest::addColumn("majorVersion"); + QTest::addColumn("minorVersion"); + + QTest::newRow("default version") + << "import \"localModule\"\n" + "TestComponent {}" + << 2 << 0; + + QTest::newRow("specific version") + << "import \"localModule\" 1.1\n" + "TestComponent {}" + << 1 << 1; + + QTest::newRow("lesser version") + << "import \"localModule\" 1.0\n" + "TestComponent {}" + << 1 << 0; + + // Note: this does not match the behaviour of installed modules, which fail for this case: + QTest::newRow("nonexistent version") + << "import \"localModule\" 1.3\n" + "TestComponent {}" + << 1 << 1; + + QTest::newRow("high version") + << "import \"localModule\" 2.0\n" + "TestComponent {}" + << 2 << 0; +} + QTEST_MAIN(tst_qqmlmoduleplugin) #include "tst_qqmlmoduleplugin.moc"