aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/qtqml/CMakeLists.txt4
-rw-r--r--src/imports/qtqml/qtqml.pro4
-rw-r--r--src/imports/qtquick2/CMakeLists.txt2
-rw-r--r--src/imports/qtquick2/qmldir2
-rw-r--r--src/imports/window/qmldir2
-rw-r--r--src/qml/Qt6QmlMacros.cmake22
-rw-r--r--src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc17
-rw-r--r--src/qml/qml/qqml.cpp92
-rw-r--r--src/qml/qml/qqml.h16
-rw-r--r--src/qml/qml/qqmlmetatype.cpp47
-rw-r--r--src/qml/qml/qqmlmetatype_p.h9
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp14
-rw-r--r--src/qml/qml/qqmltypeloaderqmldircontent.cpp2
-rw-r--r--src/qml/qml/qqmltypeloaderqmldircontent_p.h2
-rw-r--r--src/qml/qml/qqmltypemodule.cpp18
-rw-r--r--src/qml/qml/qqmltypemodule_p.h6
-rw-r--r--src/qml/qmldirparser/qqmldirparser.cpp24
-rw-r--r--src/qml/qmldirparser/qqmldirparser_p.h16
-rw-r--r--tests/auto/qml/qqmltypeloader/data/implicitautoimporttest.qml8
-rw-r--r--tests/auto/qml/qqmltypeloader/data/implicitversionedimporttest.qml8
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/Test.qml3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/qmldir3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/Test.qml3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/qmldir2
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp23
-rw-r--r--tools/qmllint/findwarnings.cpp4
27 files changed, 280 insertions, 76 deletions
diff --git a/src/imports/qtqml/CMakeLists.txt b/src/imports/qtqml/CMakeLists.txt
index f50f2f69f5..c33aad5cc4 100644
--- a/src/imports/qtqml/CMakeLists.txt
+++ b/src/imports/qtqml/CMakeLists.txt
@@ -1,12 +1,12 @@
# Generated from qtqml.pro.
set(module_dynamic_qml_imports
- QtQml.Models
+ QtQml.Models/auto
)
if (QT_FEATURE_qml_worker_script)
list(APPEND module_dynamic_qml_imports
- QtQml.WorkerScript
+ QtQml.WorkerScript/auto
)
endif()
diff --git a/src/imports/qtqml/qtqml.pro b/src/imports/qtqml/qtqml.pro
index eac19954b6..ca162e65a9 100644
--- a/src/imports/qtqml/qtqml.pro
+++ b/src/imports/qtqml/qtqml.pro
@@ -15,9 +15,9 @@ DYNAMIC_QMLDIR = \
"classname QtQmlPlugin" \
"typeinfo plugins.qmltypes" \
"designersupported" \
- "import QtQml.Models"
+ "import QtQml.Models auto"
qtConfig(qml-worker-script): DYNAMIC_QMLDIR += \
- "import QtQml.WorkerScript"
+ "import QtQml.WorkerScript auto"
load(qml_plugin)
diff --git a/src/imports/qtquick2/CMakeLists.txt b/src/imports/qtquick2/CMakeLists.txt
index e007c476f8..1da9bad480 100644
--- a/src/imports/qtquick2/CMakeLists.txt
+++ b/src/imports/qtquick2/CMakeLists.txt
@@ -11,7 +11,7 @@ qt_add_qml_module(qtquick2plugin
CLASSNAME QtQuick2Plugin
SKIP_TYPE_REGISTRATION
IMPORTS
- QtQml
+ QtQml/auto
SOURCES
plugin.cpp
PUBLIC_LIBRARIES
diff --git a/src/imports/qtquick2/qmldir b/src/imports/qtquick2/qmldir
index d74aabd9e9..b5c754a36f 100644
--- a/src/imports/qtquick2/qmldir
+++ b/src/imports/qtquick2/qmldir
@@ -3,4 +3,4 @@ plugin qtquick2plugin
classname QtQuick2Plugin
typeinfo plugins.qmltypes
designersupported
-import QtQml
+import QtQml auto
diff --git a/src/imports/window/qmldir b/src/imports/window/qmldir
index 859cd341a1..c1cc5d89b7 100644
--- a/src/imports/window/qmldir
+++ b/src/imports/window/qmldir
@@ -1,2 +1,2 @@
module QtQuick.Window
-import QtQuick
+import QtQuick auto
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index d04d663656..4405db694a 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -57,7 +57,11 @@
# that can be read by QML tools such as Qt Creator to access information about
# the types defined by the module's plugins. (OPTIONAL)
#
-# IMPORTS: List of other Qml Modules that this module imports. (OPTIONAL)
+# IMPORTS: List of other Qml Modules that this module imports. A version can be
+# specified by appending it after a slash(/), e.g QtQuick/2.0. The minor
+# version may be omitted, e.g. QtQuick/2. Alternatively "auto" may be given
+# as version to forward the version the current module is being imported with,
+# e.g. QtQuick/auto. (OPTIONAL)
#
# RESOURCE_EXPORT: In static builds, when Qml files are processed via the Qt
# Quick Compiler generate a separate static library that will be linked in
@@ -254,7 +258,21 @@ function(qt6_add_qml_module target)
string(APPEND qmldir_file_contents "typeinfo plugins.qmltypes\n")
endif()
foreach(import IN LISTS arg_IMPORTS)
- string(APPEND qmldir_file_contents "import ${import}\n")
+ string(FIND ${import} "/" slash_position REVERSE)
+ if (slash_position EQUAL -1)
+ string(APPEND qmldir_file_contents "import ${import}\n")
+ else()
+ string(SUBSTRING ${import} 0 ${slash_position} import_module)
+ math(EXPR slash_position "${slash_position} + 1")
+ string(SUBSTRING ${import} ${slash_position} -1 import_version)
+ if (import_version MATCHES "[0-9]+\\.[0-9]+" OR import_version MATCHES "[0-9]+")
+ string(APPEND qmldir_file_contents "import ${import_module} ${import_version}\n")
+ elseif (import_version MATCHES "auto")
+ string(APPEND qmldir_file_contents "import ${import_module} auto\n")
+ else()
+ message(FATAL_ERROR "Invalid module import version number. Expected 'VersionMajor', 'VersionMajor.VersionMinor' or 'auto'.")
+ endif()
+ endif()
endforeach()
foreach(dependency IN LISTS arg_DEPENDENCIES)
diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
index e9dc5a043a..0be46f30d2 100644
--- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
+++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
@@ -246,6 +246,23 @@ depends MyOtherModule 1.0
load QML (perhaps conditionally) which then depends on other
modules. In such cases, the \c depends declaration is necessary
to include the other modules in application packages.
+ \row
+ \li
+ \code
+import <ModuleIdentifier> [<Version>]
+ \endcode
+ \li Declares that this module imports another.
+
+ Example:
+ \code
+import MyOtherModule 1.0
+ \endcode
+
+ The types from the other module are made available in the same type
+ namespace as this module is imported into. Omitting the version
+ imports the latest version available of the other module, specifying
+ \c auto as version imports the same version as the version of this
+ module specified in the QML \c import statement.
\row
\li
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 183818aca8..9d58fa7d9b 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -72,35 +72,107 @@ void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
QQmlMetaType::registerModule(uri, QTypeRevision::fromVersion(versionMajor, versionMinor));
}
+static QQmlDirParser::Import resolveImport(const QString &uri, int importMajor, int importMinor)
+{
+ if (importMajor == QQmlModuleImportAuto)
+ return QQmlDirParser::Import(uri, QTypeRevision(), true);
+ else if (importMajor == QQmlModuleImportLatest)
+ return QQmlDirParser::Import(uri, QTypeRevision(), false);
+ else if (importMinor == QQmlModuleImportLatest)
+ return QQmlDirParser::Import(uri, QTypeRevision::fromMajorVersion(importMajor), false);
+ return QQmlDirParser::Import(uri, QTypeRevision::fromVersion(importMajor, importMinor), false);
+}
+
+static QTypeRevision resolveModuleVersion(int moduleMajor)
+{
+ return moduleMajor == QQmlModuleImportModuleAny
+ ? QTypeRevision()
+ : QTypeRevision::fromMajorVersion(moduleMajor);
+}
+
+/*!
+ * \enum QQmlModuleImportSpecialVersions
+ *
+ * Defines some special values that can be passed to the version arguments of
+ * qmlRegisterModuleImport() and qmlUnregisterModuleImport().
+ *
+ * \value QQmlModuleImportModuleAny When passed as majorVersion of the base
+ * module, signifies that the import is to be
+ * applied to any version of the module.
+ * \value QQmlModuleImportLatest When passed as major or minor version of
+ * the imported module, signifies that the
+ * latest overall, or latest minor version
+ * of a specified major version shall be
+ * imported.
+ * \value QQmlModuleImportAuto When passed as major version of the imported
+ * module, signifies that the version of the
+ * base module shall be forwarded.
+ */
+
/*!
* Registers an implicit import for module \a uri of major version \a majorVersion
*
* This has the same effect as an \c import statement in a qmldir file: Whenever
- * \a uri version \a majorVersion is imported, \a import is automatically
- * imported, too, with the same version.
+ * \a uri of version \a moduleMajor is imported, \a import of version
+ * \a importMajor.\a importMinor is automatically imported, too. If
+ * \a importMajor is \l QmlModuleImportLatest the latest version
+ * available of that module is imported, and \a importMinor does not matter. If
+ * \a importMinor is \l QmlModuleImportLatest the latest minor version of a
+ * \a importMajor is chosen. If \a importMajor is \l QmlModuleImportAuto the
+ * version of \a import is version of \a uri being imported, and \a importMinor
+ * does not matter. If \a moduleMajor is \a QmlModuleImportModuleAny the module
+ * import is applied for any major version of \a uri. For example, you may
+ * specify that whenever any version of MyModule is imported, the latest version
+ * of MyOtherModule should be imported. Then, the following call would be
+ * appropriate:
+ *
+ * \code
+ * qmlRegisterModuleImport("MyModule", QmlModuleImportModuleAny,
+ * "MyOtherModule", QmlModuleImportLatest);
+ * \endcode
+ *
+ * Or, you may specify that whenever major version 5 of "MyModule" is imported,
+ * then version 3.14 of "MyOtherModule" should be imported:
+ *
+ * \code
+ * qmlRegisterModuleImport("MyModule", 5, "MyOtherModule", 3, 14);
+ * \endcode
+ *
+ * Finally, if you always want the same version of "MyOtherModule" to be
+ * imported whenever "MyModule" is imported, specify the following:
+ *
+ * \code
+ * qmlRegisterModuleImport("MyModule", QmlModuleImportModuleAny,
+ * "MyOtherModule", QmlModuleImportAuto);
+ * \endcode
*
* \sa qmlUnregisterModuleImport()
*/
-void qmlRegisterModuleImport(const char *uri, int majorVersion, const char *import)
+void qmlRegisterModuleImport(const char *uri, int moduleMajor,
+ const char *import, int importMajor, int importMinor)
{
QQmlMetaType::registerModuleImport(
- QString::fromUtf8(uri), QTypeRevision::fromMajorVersion(majorVersion),
- QString::fromUtf8(import));
+ QString::fromUtf8(uri), resolveModuleVersion(moduleMajor),
+ resolveImport(QString::fromUtf8(import), importMajor, importMinor));
}
+
/*!
* Removes a module import previously registered with qmlRegisterModuleImport()
*
- * Calling this function makes sure that \a import is not automatically imported
- * anymore when \a uri of version \a majorVersion is.
+ * Calling this function makes sure that \a import of version
+ * \a{importMajor}.\a{importMinor} is not automatically imported anymore when
+ * \a uri of version \a moduleMajor is. The version resolution works the same
+ * way as with \l qmlRegisterModuleImport().
*
* \sa qmlRegisterModuleImport()
*/
-void qmlUnregisterModuleImport(const char *uri, int majorVersion, const char *import)
+void qmlUnregisterModuleImport(const char *uri, int moduleMajor,
+ const char *import, int importMajor, int importMinor)
{
QQmlMetaType::unregisterModuleImport(
- QString::fromUtf8(uri), QTypeRevision::fromMajorVersion(majorVersion),
- QString::fromUtf8(import));
+ QString::fromUtf8(uri), resolveModuleVersion(moduleMajor),
+ resolveImport(QString::fromUtf8(import), importMajor, importMinor));
}
//From qqml.h
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index ee3afa768a..ae72d90875 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -675,8 +675,20 @@ QT_WARNING_POP
Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion);
Q_QML_EXPORT void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor);
-Q_QML_EXPORT void qmlRegisterModuleImport(const char *uri, int majorVersion, const char *import);
-Q_QML_EXPORT void qmlUnregisterModuleImport(const char *uri, int majorVersion, const char *import);
+enum QQmlModuleImportSpecialVersions: int {
+ QQmlModuleImportModuleAny = -1,
+ QQmlModuleImportLatest = -1,
+ QQmlModuleImportAuto = -2
+};
+
+Q_QML_EXPORT void qmlRegisterModuleImport(const char *uri, int moduleMajor,
+ const char *import,
+ int importMajor = QQmlModuleImportLatest,
+ int importMinor = QQmlModuleImportLatest);
+Q_QML_EXPORT void qmlUnregisterModuleImport(const char *uri, int moduleMajor,
+ const char *import,
+ int importMajor = QQmlModuleImportLatest,
+ int importMinor = QQmlModuleImportLatest);
template<typename T>
QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 78f1d984e5..77d3571a05 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -628,22 +628,53 @@ bool QQmlMetaType::protectModule(const QString &uri, QTypeRevision version, bool
return range.first != range.second;
}
-void QQmlMetaType::registerModuleImport(const QString &uri, QTypeRevision version, const QString &import)
+void QQmlMetaType::registerModuleImport(const QString &uri, QTypeRevision moduleVersion,
+ const QQmlDirParser::Import &import)
{
QQmlMetaTypeDataPtr data;
- QQmlTypeModule *module = getTypeModule(uri, version, data);
- Q_ASSERT(module);
- module->addImport(import);
+ data->moduleImports.insert(QQmlMetaTypeData::VersionedUri(uri, moduleVersion), import);
+}
+
+static bool operator==(const QQmlDirParser::Import &a, const QQmlDirParser::Import &b)
+{
+ return a.module == b.module && a.version == b.version && a.isAutoImport == b.isAutoImport;
}
-void QQmlMetaType::unregisterModuleImport(const QString &uri, QTypeRevision version, const QString &import)
+void QQmlMetaType::unregisterModuleImport(const QString &uri, QTypeRevision moduleVersion,
+ const QQmlDirParser::Import &import)
{
QQmlMetaTypeDataPtr data;
+ data->moduleImports.remove(QQmlMetaTypeData::VersionedUri(uri, moduleVersion), import);
+}
- QQmlTypeModule *module = getTypeModule(uri, version, data);
- Q_ASSERT(module);
- module->removeImport(import);
+QList<QQmlDirParser::Import> QQmlMetaType::moduleImports(
+ const QString &uri, QTypeRevision version)
+{
+ QQmlMetaTypeDataPtr data;
+
+ const auto unrevisioned = data->moduleImports.equal_range(
+ QQmlMetaTypeData::VersionedUri(uri, QTypeRevision()));
+
+ QList<QQmlDirParser::Import> result(unrevisioned.first, unrevisioned.second);
+ if (version.hasMajorVersion())
+ return result + data->moduleImports.values(QQmlMetaTypeData::VersionedUri(uri, version));
+
+ // Use latest module available with that URI.
+ const auto begin = data->moduleImports.begin();
+ auto it = unrevisioned.first;
+ if (it == begin)
+ return result;
+
+ const QQmlMetaTypeData::VersionedUri latestVersion = (--it).key();
+ if (latestVersion.uri != uri)
+ return result;
+
+ do {
+ result += *it;
+ } while (it != begin && (--it).key() == latestVersion);
+
+ return result;
}
void QQmlMetaType::registerModule(const char *uri, QTypeRevision version)
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 1c00d65b75..7b142dd07f 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -54,6 +54,7 @@
#include <private/qtqmlglobal_p.h>
#include <private/qqmltype_p.h>
#include <private/qqmlproxymetaobject_p.h>
+#include <private/qqmldirparser_p.h>
QT_BEGIN_NAMESPACE
@@ -98,8 +99,12 @@ public:
static void registerModule(const char *uri, QTypeRevision version);
static bool protectModule(const QString &uri, QTypeRevision version,
bool protectAllVersions = false);
- static void registerModuleImport(const QString &uri, QTypeRevision version, const QString &import);
- static void unregisterModuleImport(const QString &uri, QTypeRevision version, const QString &import);
+
+ static void registerModuleImport(const QString &uri, QTypeRevision version,
+ const QQmlDirParser::Import &import);
+ static void unregisterModuleImport(const QString &uri, QTypeRevision version,
+ const QQmlDirParser::Import &import);
+ static QList<QQmlDirParser::Import> moduleImports(const QString &uri, QTypeRevision version);
static int typeId(const char *uri, QTypeRevision version, const char *qmlName);
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index b2ecbf2cea..a5d919e471 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -116,6 +116,9 @@ struct QQmlMetaTypeData
QQmlTypeModule *findTypeModule(const QString &module, QTypeRevision version);
QQmlTypeModule *addTypeModule(std::unique_ptr<QQmlTypeModule> module);
+ using ModuleImports = QMultiMap<VersionedUri, QQmlDirParser::Import>;
+ ModuleImports moduleImports;
+
QHash<QString, void (*)()> moduleTypeRegistrationFunctions;
bool registerModuleTypes(const QString &uri);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index ff0633a475..8e90388258 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -714,15 +714,15 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob)
bool QQmlTypeLoader::Blob::loadImportDependencies(PendingImportPtr currentImport, const QString &qmldirUri, QList<QQmlError> *errors)
{
const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirUri);
- const QQmlTypeModule *module = QQmlMetaType::typeModule(currentImport->uri,
- currentImport->version);
- const QStringList implicitImports = module ? (module->imports() + qmldir.imports())
- : qmldir.imports();
- for (const QString &implicitImport : implicitImports) {
+ const QList<QQmlDirParser::Import> implicitImports
+ = QQmlMetaType::moduleImports(currentImport->uri, currentImport->version)
+ + qmldir.imports();
+ for (const auto &implicitImport : implicitImports) {
auto dependencyImport = std::make_shared<PendingImport>();
- dependencyImport->uri = implicitImport;
+ dependencyImport->uri = implicitImport.module;
dependencyImport->qualifier = currentImport->qualifier;
- dependencyImport->version = currentImport->version;
+ dependencyImport->version = implicitImport.isAutoImport ? currentImport->version
+ : implicitImport.version;
if (!addImport(dependencyImport, QQmlImports::ImportLowPrecedence, errors)) {
QQmlError error;
error.setDescription(
diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp
index 714ea79e67..2175c115e6 100644
--- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp
+++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp
@@ -105,7 +105,7 @@ QQmlDirPlugins QQmlTypeLoaderQmldirContent::plugins() const
return m_parser.plugins();
}
-QStringList QQmlTypeLoaderQmldirContent::imports() const
+QQmlDirImports QQmlTypeLoaderQmldirContent::imports() const
{
return m_parser.imports();
}
diff --git a/src/qml/qml/qqmltypeloaderqmldircontent_p.h b/src/qml/qml/qqmltypeloaderqmldircontent_p.h
index 698643c7ec..677d06891e 100644
--- a/src/qml/qml/qqmltypeloaderqmldircontent_p.h
+++ b/src/qml/qml/qqmltypeloaderqmldircontent_p.h
@@ -78,7 +78,7 @@ public:
QQmlDirComponents components() const;
QQmlDirScripts scripts() const;
QQmlDirPlugins plugins() const;
- QStringList imports() const;
+ QQmlDirImports imports() const;
QString pluginLocation() const;
diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp
index f700f4c01a..01de024deb 100644
--- a/src/qml/qml/qqmltypemodule.cpp
+++ b/src/qml/qml/qqmltypemodule.cpp
@@ -123,22 +123,4 @@ void QQmlTypeModule::walkCompositeSingletons(const std::function<void(const QQml
}
}
-QStringList QQmlTypeModule::imports() const
-{
- QMutexLocker lock(&m_mutex);
- return m_imports;
-}
-
-void QQmlTypeModule::addImport(const QString &import)
-{
- QMutexLocker lock(&m_mutex);
- m_imports.append(import);
-}
-
-void QQmlTypeModule::removeImport(const QString &import)
-{
- QMutexLocker lock(&m_mutex);
- m_imports.removeAll(import);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypemodule_p.h b/src/qml/qml/qqmltypemodule_p.h
index 28cf070a95..0ba6245cbb 100644
--- a/src/qml/qml/qqmltypemodule_p.h
+++ b/src/qml/qml/qqmltypemodule_p.h
@@ -104,16 +104,10 @@ public:
void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
- void addImport(const QString &import);
- void removeImport(const QString &import);
- QStringList imports() const;
-
private:
const QString m_module;
const quint8 m_majorVersion = 0;
- QStringList m_imports;
-
// Can only ever decrease
QAtomicInt m_minMinorVersion = std::numeric_limits<quint8>::max();
diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp
index e4d916a10f..c8589431b8 100644
--- a/src/qml/qmldirparser/qqmldirparser.cpp
+++ b/src/qml/qmldirparser/qqmldirparser.cpp
@@ -276,12 +276,28 @@ bool QQmlDirParser::parse(const QString &source)
reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
}
} else if (sections[0] == QLatin1String("import")) {
- if (sectionCount != 2) {
+ if (sectionCount == 2) {
+ _imports << Import(sections[1], QTypeRevision(), false);
+ } else if (sectionCount == 3) {
+ if (sections[2] == QLatin1String("auto")) {
+ _imports << Import(sections[1], QTypeRevision(), true);
+ } else {
+ const auto version = parseVersion(sections[2]);
+ if (version.isValid()) {
+ _imports << Import(sections[1], version, false);
+ } else {
+ reportError(lineNumber, 0,
+ QStringLiteral("invalid version %1, expected <major>.<minor>")
+ .arg(sections[2]));
+ continue;
+ }
+ }
+ } else {
reportError(lineNumber, 0,
- QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ QStringLiteral("import requires 1 or 2 arguments, but %1 were provided")
+ .arg(sectionCount - 1));
continue;
}
- _imports << sections[1];
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], QTypeRevision());
@@ -374,7 +390,7 @@ QHash<QString, QQmlDirParser::Component> QQmlDirParser::dependencies() const
return _dependencies;
}
-QStringList QQmlDirParser::imports() const
+QList<QQmlDirParser::Import> QQmlDirParser::imports() const
{
return _imports;
}
diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h
index a5a548daca..68a0d6d5e2 100644
--- a/src/qml/qmldirparser/qqmldirparser_p.h
+++ b/src/qml/qmldirparser/qqmldirparser_p.h
@@ -132,9 +132,20 @@ public:
QTypeRevision version = QTypeRevision::zero();
};
+ struct Import
+ {
+ Import() = default;
+ Import(QString module, QTypeRevision version, bool isAutoImport)
+ : module(module), version(version), isAutoImport(isAutoImport) {}
+
+ QString module;
+ QTypeRevision version; // default: lastest version
+ bool isAutoImport = false; // if set: forward the version of the importing module
+ };
+
QMultiHash<QString,Component> components() const;
QHash<QString,Component> dependencies() const;
- QStringList imports() const;
+ QList<Import> imports() const;
QList<Script> scripts() const;
QList<Plugin> plugins() const;
bool designerSupported() const;
@@ -161,7 +172,7 @@ private:
QString _typeNamespace;
QMultiHash<QString,Component> _components;
QHash<QString,Component> _dependencies;
- QStringList _imports;
+ QList<Import> _imports;
QList<Script> _scripts;
QList<Plugin> _plugins;
bool _designerSupported = false;
@@ -172,6 +183,7 @@ private:
using QQmlDirComponents = QMultiHash<QString,QQmlDirParser::Component>;
using QQmlDirScripts = QList<QQmlDirParser::Script>;
using QQmlDirPlugins = QList<QQmlDirParser::Plugin>;
+using QQmlDirImports = QList<QQmlDirParser::Import>;
QDebug &operator<< (QDebug &, const QQmlDirParser::Component &);
QDebug &operator<< (QDebug &, const QQmlDirParser::Script &);
diff --git a/tests/auto/qml/qqmltypeloader/data/implicitautoimporttest.qml b/tests/auto/qml/qqmltypeloader/data/implicitautoimporttest.qml
new file mode 100644
index 0000000000..e32bac3c89
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/implicitautoimporttest.qml
@@ -0,0 +1,8 @@
+import modulewithimplicitautoimport 2.11 as MyNS
+MyNS.Test {
+ MyNS.Item { // Implicitly imported from QtQuick
+ // containmentMask added in 2.11. Version is forwarded.
+ objectName: containmentMask.objectName
+ }
+ MyNS.ListModel {}
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/implicitversionedimporttest.qml b/tests/auto/qml/qqmltypeloader/data/implicitversionedimporttest.qml
new file mode 100644
index 0000000000..ae09eba4e0
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/implicitversionedimporttest.qml
@@ -0,0 +1,8 @@
+import modulewithimplicitversionedimport 2.0 as MyNS
+MyNS.Test {
+ MyNS.Item { // Implicitly imported from QtQuick
+ // containmentMask added in 2.11. Despite version 2.0 above, the module imports 2.15.
+ objectName: containmentMask.objectName
+ }
+ MyNS.ListModel {}
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/Test.qml b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/Test.qml
new file mode 100644
index 0000000000..2f78302506
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/Test.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+Item {
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/qmldir b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/qmldir
new file mode 100644
index 0000000000..468eb296f7
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitautoimport/qmldir
@@ -0,0 +1,3 @@
+import QtQuick auto
+Test 2.0 Test.qml
+Dummy 2.22 Test.qml
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/Test.qml b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/Test.qml
new file mode 100644
index 0000000000..2f78302506
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/Test.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+Item {
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/qmldir b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/qmldir
new file mode 100644
index 0000000000..71bbbb99d0
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/modulewithimplicitversionedimport/qmldir
@@ -0,0 +1,2 @@
+import QtQuick 2.15
+Test 2.0 Test.qml
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 3843d9a720..e1fdb0e221 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -579,10 +579,25 @@ void tst_QQMLTypeLoader::implicitImport()
{
QQmlEngine engine;
engine.addImportPath(testFile("imports"));
- QQmlComponent component(&engine, testFileUrl("implicitimporttest.qml"));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> obj(component.create());
- QVERIFY(!obj.isNull());
+ {
+ QQmlComponent component(&engine, testFileUrl("implicitimporttest.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("implicitautoimporttest.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("implicitversionedimporttest.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ }
+
}
void tst_QQMLTypeLoader::compositeSingletonCycle()
diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp
index cc8a323112..50123d8957 100644
--- a/tools/qmllint/findwarnings.cpp
+++ b/tools/qmllint/findwarnings.cpp
@@ -141,8 +141,8 @@ FindWarningVisitor::Import FindWarningVisitor::readQmldir(const QString &path)
Import result;
auto reader = createQmldirParserForFile(path + SlashQmldir);
const auto imports = reader.imports();
- for (const QString &import : imports)
- result.dependencies.append(import);
+ for (const auto &import : imports)
+ result.dependencies.append(import.module); // TODO: version
QHash<QString, ScopeTree::Ptr> qmlComponents;
const auto components = reader.components();