forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -234,13 +234,11 @@ void tst_ImportCheck::importTypes_data()
|
||||
<< QStringList({ "Item", "QtObject", "IsQtQuickSimple" });
|
||||
|
||||
// QtQuick/ and QtQml/ with an implicit dependency
|
||||
// This is the situation in Qt 5.15.0 and will be made to work in a
|
||||
// follow-up commit.
|
||||
/*
|
||||
// Seen in Qt 5.15.0.
|
||||
QTest::newRow("QtQuick-workaround-QtQml")
|
||||
<< QString(TESTSRCDIR "/importTypes/importQtQuick.qml")
|
||||
<< QString(TESTSRCDIR "/importTypes/imports-QtQuick-workaround-QtQml")
|
||||
<< QStringList({ "Item", "QtObject", "IsQtQuickWorkaround" });*/
|
||||
<< QStringList({ "Item", "QtObject", "IsQtQuickWorkaround" });
|
||||
|
||||
// QtQuick/ and QtQml/ with an "import" in the qmldir file
|
||||
// Seen in Qt 6.
|
||||
|
Reference in New Issue
Block a user