aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qmljs/qmljslink.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/qmljs/qmljslink.cpp')
-rw-r--r--src/libs/qmljs/qmljslink.cpp78
1 files changed, 70 insertions, 8 deletions
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index e505a9e4c5..2d91324f64 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -93,7 +93,7 @@ public:
bool importLibrary(const Document::Ptr &doc,
const QString &libraryPath,
- Import *import,
+ Import *import, ObjectValue *targetObject,
const QString &importPath = QString());
void loadQmldirComponents(ObjectValue *import,
LanguageUtils::ComponentVersion version,
@@ -239,6 +239,32 @@ Context::ImportsPerDocument LinkPrivate::linkImports()
return importsPerDocument;
}
+/**
+ * A workaround for prototype issues with QEasingCurve in Qt 5.15.
+ *
+ * In this Qt version, QEasingCurve is declared in builtins.qmltypes, but its
+ * prototype, QQmlEasingValueType, is only contained in the QtQml module.
+ *
+ * This code attempts to resolve QEasingCurve's prototype if it hasn't been set
+ * already. It's intended to be called after all CppQmlTypes have been loaded.
+ */
+static void workaroundQEasingCurve(CppQmlTypes &cppTypes)
+{
+ const CppComponentValue *easingCurve = cppTypes.objectByCppName("QEasingCurve");
+ if (!easingCurve || easingCurve->prototype())
+ return;
+
+ const QString superclassName = easingCurve->metaObject()->superclassName();
+ if (superclassName.isEmpty())
+ return;
+
+ const CppComponentValue *prototype = cppTypes.objectByCppName(superclassName);
+ if (!prototype)
+ return;
+
+ const_cast<CppComponentValue *>(easingCurve)->setPrototype(prototype);
+}
+
void LinkPrivate::populateImportedTypes(Imports *imports, const Document::Ptr &doc)
{
importableModuleApis.clear();
@@ -287,6 +313,8 @@ void LinkPrivate::populateImportedTypes(Imports *imports, const Document::Ptr &d
if (import.object)
imports->append(import);
}
+
+ workaroundQEasingCurve(m_valueOwner->cppQmlTypes());
}
/*
@@ -312,7 +340,7 @@ Import LinkPrivate::importFileOrDirectory(const Document::Ptr &doc, const Import
|| importInfo.type() == ImportType::ImplicitDirectory) {
import.object = new ObjectValue(m_valueOwner);
- importLibrary(doc, path, &import);
+ importLibrary(doc, path, &import, import.object);
const QList<Document::Ptr> documentsInDirectory = m_snapshot.documentsInDirectory(path);
for (const Document::Ptr &importedDoc : documentsInDirectory) {
@@ -337,7 +365,7 @@ Import LinkPrivate::importFileOrDirectory(const Document::Ptr &doc, const Import
} else if (importInfo.type() == ImportType::QrcDirectory){
import.object = new ObjectValue(m_valueOwner);
- importLibrary(doc, path, &import);
+ importLibrary(doc, path, &import, import.object);
const QMap<QString, QStringList> paths
= ModelManagerInterface::instance()->filesInQrcPath(path);
@@ -382,7 +410,7 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
const ComponentVersion version = importInfo.version();
QString libraryPath = modulePath(packageName, version.toString(), m_importPaths);
- bool importFound = !libraryPath.isEmpty() && importLibrary(doc, libraryPath, &import);
+ bool importFound = !libraryPath.isEmpty() && importLibrary(doc, libraryPath, &import, import.object);
if (!importFound) {
for (const QString &dir : qAsConst(m_applicationDirectories)) {
@@ -390,7 +418,7 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
// This adds the types to the C++ types, to be found below if applicable.
if (it.hasNext())
- importLibrary(doc, dir, &import);
+ importLibrary(doc, dir, &import, import.object);
}
}
@@ -436,6 +464,7 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
bool LinkPrivate::importLibrary(const Document::Ptr &doc,
const QString &libraryPath,
Import *import,
+ ObjectValue *targetObject,
const QString &importPath)
{
const ImportInfo &importInfo = import->info;
@@ -451,6 +480,38 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
if (const UiImport *ast = importInfo.ast())
errorLoc = locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation());
+ // Load imports that are mentioned by the "import" command in a qmldir
+ // file into the same targetObject, using the same version and "as".
+ //
+ // Note: Since this works on the same targetObject, the ModuleApi setPrototype()
+ // logic will not work. But ModuleApi isn't used in Qt versions that use import
+ // commands in qmldir files, and is pending removal in Qt 6.
+ for (const auto &importName : libraryInfo.imports()) {
+ Import subImport;
+ subImport.valid = true;
+ subImport.info = ImportInfo::moduleImport(importName, version, importInfo.as(), importInfo.ast());
+ subImport.libraryPath = modulePath(importName, version.toString(), m_importPaths);
+ bool subImportFound = importLibrary(doc, subImport.libraryPath, &subImport, targetObject, importPath);
+
+ if (!subImportFound && errorLoc.isValid()) {
+ import->valid = false;
+ error(doc, errorLoc,
+ Link::tr(
+ "Implicit import '%1' of QML module '%2' not found.\n\n"
+ "Import paths:\n"
+ "%3\n\n"
+ "For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
+ "For Qbs projects, declare and set a qmlImportPaths property in your product "
+ "to add import paths.\n"
+ "For qmlproject projects, use the importPaths property to add import paths.\n"
+ "For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n")
+ .arg(importName, importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
+ } else if (!subImport.valid) {
+ import->valid = false;
+ }
+ }
+
+ // Load types from qmltypes or plugins
if (!libraryInfo.plugins().isEmpty() || !libraryInfo.typeInfos().isEmpty()) {
if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::NoTypeInfo) {
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
@@ -493,7 +554,7 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
const auto objects = m_valueOwner->cppQmlTypes().createObjectsForImport(packageName,
version);
for (const CppComponentValue *object : objects)
- import->object->setMember(object->className(), object);
+ targetObject->setMember(object->className(), object);
// all but no-uri module apis become available for import
QList<ModuleApiInfo> noUriModuleApis;
@@ -508,13 +569,14 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
// if a module api has no uri, it shares the same name
ModuleApiInfo sameUriModuleApi = findBestModuleApi(noUriModuleApis, version);
if (sameUriModuleApi.version.isValid()) {
- import->object->setPrototype(m_valueOwner->cppQmlTypes()
+ targetObject->setPrototype(m_valueOwner->cppQmlTypes()
.objectByCppName(sameUriModuleApi.cppName));
}
}
}
- loadQmldirComponents(import->object, version, libraryInfo, libraryPath);
+ // Load types that are mentioned explicitly in the qmldir
+ loadQmldirComponents(targetObject, version, libraryInfo, libraryPath);
return true;
}