diff options
author | Christian Kamm <mail@ckamm.de> | 2020-05-10 16:06:57 +0200 |
---|---|---|
committer | Christian Kamm <mail@ckamm.de> | 2020-05-21 07:54:08 +0000 |
commit | 40dd6fc1859bf0b5345d368e9cb3d4eddadf7fc5 (patch) | |
tree | 25b3610fe94fc18b7173564761c5e6fee9156090 /src | |
parent | f64146741df05d7da7429f66af079b24c11cc3ca (diff) |
QmlJS: Add workaround for missing imports in Qt >=5.15.0
The QtQuick module plugins.qmltypes in Qt 5.15.0 do not contain
QML types like QtObject. Instead, they are found in the QtQml module.
Something similar applies to QtQml and QtQml.Models and
QtQml.WorkerScript.
As Qt 5.15 can't use the "import" command in the qmldir file, this code
instead detects the 5.15 QtQuick and QtQml modules and adds the
dependent imports manually, as a workaround.
Change-Id: I982e349298eb7200372390dfc384fb43a762b253
Task-number: QTCREATORBUG-23986
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/qmljs/qmljsplugindumper.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp index de26d7435a..8b7604809b 100644 --- a/src/libs/qmljs/qmljsplugindumper.cpp +++ b/src/libs/qmljs/qmljsplugindumper.cpp @@ -494,6 +494,78 @@ QFuture<PluginDumper::DependencyInfo> PluginDumper::loadDependencies(const QStri return iface->future(); } +// Fills \a highestVersion with the largest export version for \a package +// and sets \a hasExportName to true if a type called \a exportName is found. +static void getHighestExportVersion( + const QList<LanguageUtils::FakeMetaObject::ConstPtr> &objects, + const QString &package, + const QString &exportName, + bool *hasExportName, + ComponentVersion *highestVersion) +{ + *highestVersion = ComponentVersion(); + *hasExportName = false; + for (const auto &object : objects) { + for (const auto &e : object->exports()) { + if (e.package == package) { + if (e.version > *highestVersion) + *highestVersion = e.version; + if (e.type == exportName) + *hasExportName = true; + } + } + } + +} + +/*** Workaround for implicit dependencies in >= 5.15.0. + * + * When "QtQuick" is imported, "QtQml" is implicitly loaded as well. + * When "QtQml" is imported, "QtQml.Models" and "QtQml.WorkerScript" are implicitly loaded. + * Add these imports as if they were "import" commands in the qmldir file. + * + * Qt 6 is planned to have these included in the qmldir file. + */ +static void applyQt515MissingImportWorkaround(const QString &path, LibraryInfo &info) +{ + if (!info.imports().isEmpty()) + return; + + const bool isQtQuick = path.endsWith(QStringLiteral("/QtQuick")) + || path.endsWith(QStringLiteral("/QtQuick.2")); + const bool isQtQml = path.endsWith(QStringLiteral("/QtQml")) + || path.endsWith(QStringLiteral("/QtQml.2")); + if (!isQtQuick && !isQtQml) + return; + + ComponentVersion highestVersion; + const auto package = isQtQuick ? QStringLiteral("QtQuick") : QStringLiteral("QtQml"); + const auto missingTypeName = isQtQuick ? QStringLiteral("QtObject") : QStringLiteral("ListElement"); + bool hasMissingType = false; + getHighestExportVersion( + info.metaObjects(), + package, + missingTypeName, + &hasMissingType, + &highestVersion); + + // If the highest export version is < 2.15, we expect Qt <5.15 + if (highestVersion.majorVersion() != 2 || highestVersion.minorVersion() < 15) + return; + // As an extra sanity check: if the type from the dependent module already exists, + // don't proceeed either. + if (hasMissingType) + return; + + if (isQtQuick) { + info.setImports(QStringList(QStringLiteral("QtQml"))); + } else if (isQtQml) { + info.setImports(QStringList( + { QStringLiteral("QtQml.Models"), + QStringLiteral("QtQml.WorkerScript") })); + } +} + void PluginDumper::prepareLibraryInfo(LibraryInfo &libInfo, const QString &libraryPath, const QStringList &deps, @@ -519,6 +591,8 @@ void PluginDumper::prepareLibraryInfo(LibraryInfo &libInfo, if (!warnings.isEmpty()) printParseWarnings(libraryPath, warnings.join(QLatin1String("\n"))); + applyQt515MissingImportWorkaround(libraryPath, libInfo); + libInfo.updateFingerprint(); } |