diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2017-10-18 15:50:32 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2017-10-19 16:26:14 +0000 |
commit | ffca73c79d7733f06416f211d5d544dd037c9532 (patch) | |
tree | b9793da38a53c5bf46ed001a98e49d531232fe3c /src | |
parent | 3b6eeee177b64eebe240d51be0c7bb5f031471d8 (diff) |
Tell QQmlImportInstance::resolveType what kind of type we want
In QQmlTypeData::resolveTypes() we know if we're looking at a reference
to a composite singleton type, or some other type reference. When we
call resolveType() we expect the correct type to be returned, not only
based on URL, but also based on its singleton property.
QQmlTypeData::resolveType() eventually invokes
QQmlImportInstance::resolveType() which will call
fetchOrCreateTypeForUrl(), passing a parameter on whether the result
should be a composite singleton. When operating on a qmldir component
the component itself encodes this. When fetching a type from a local
file without qmldir, we currently assume that it isn't a singleton, no
matter QQmlTypeData::resolveTypes() has determined. This means that
actual singletons loaded this way later get refused by the sanity check.
In order to fix this, pass the information about the expected singleton
property on to QQmlImportInstance. This is done using
QQmlType::RegistrationType, which gets another entry for "any type". If
the expected type is CompositeSingletonType QQmlTypeData::resolveType()
will not create a non-singleton type. If it is any specific other type,
it will not create a composite singleton. And if it is
AnyRegistrationType, it will behave as it previously did.
Change-Id: I6b7e082b63582e0aed946bb3d19077b94c7a45f7
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 53 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 15 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 5 |
5 files changed, 66 insertions, 29 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index ccd287e1b6..4e3b25070f 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -295,7 +295,8 @@ public: QList<QQmlError> *errors); bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, - QQmlType *type_return, QList<QQmlError> *errors); + QQmlType *type_return, QList<QQmlError> *errors, + QQmlType::RegistrationType registrationType); QUrl baseUrl; QString base; @@ -632,7 +633,8 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) */ bool QQmlImports::resolveType(const QHashedStringRef &type, QQmlType *type_return, int *vmaj, int *vmin, - QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const + QQmlImportNamespace** ns_return, QList<QQmlError> *errors, + QQmlType::RegistrationType registrationType) const { QQmlImportNamespace* ns = d->findQualifiedNamespace(type); if (ns) { @@ -641,7 +643,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return true; } if (type_return) { - if (d->resolveType(type, vmaj, vmin, type_return, errors)) { + if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ << ')' << "::resolveType: " << type.toString() << " => " @@ -719,14 +721,16 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml If the return pointer is 0, the corresponding search is not done. */ bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type, - QQmlType *type_return, int *vmaj, int *vmin) const + QQmlType *type_return, int *vmaj, int *vmin, + QQmlType::RegistrationType registrationType) const { - return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return); + return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return, 0, 0, registrationType); } -bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, - const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType* type_return, QString *base, bool *typeRecursionDetected) const +bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, + int *vmajor, int *vminor, QQmlType* type_return, QString *base, + bool *typeRecursionDetected, + QQmlType::RegistrationType registrationType) const { if (majversion >= 0 && minversion >= 0) { QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion); @@ -747,6 +751,18 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, QQmlDirComponents::ConstIterator candidate = end; for ( ; it != end && it.key() == typeStr; ++it) { const QQmlDirParser::Component &c = *it; + switch (registrationType) { + case QQmlType::AnyRegistrationType: + break; + case QQmlType::CompositeSingletonType: + if (!c.singleton) + continue; + break; + default: + if (c.singleton) + continue; + break; + } // importing version -1 means import ALL versions if ((majversion == -1) || @@ -780,8 +796,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName); int major = vmajor ? *vmajor : -1; int minor = vminor ? *vminor : -1; - QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0, - major, minor); + QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, + 0, major, minor); if (type_return) *type_return = returnType; return returnType.isValid(); @@ -808,7 +824,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, if (typeRecursionDetected) *typeRecursionDetected = true; } else { - QQmlType returnType = fetchOrCreateTypeForUrl(qmlUrl, type, false, 0); + QQmlType returnType = fetchOrCreateTypeForUrl( + qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, 0); if (type_return) *type_return = returnType; return returnType.isValid(); @@ -820,7 +837,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, } bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType *type_return, QList<QQmlError> *errors) + QQmlType *type_return, QList<QQmlError> *errors, + QQmlType::RegistrationType registrationType) { QQmlImportNamespace *s = 0; int dot = type.indexOf(Dot); @@ -849,7 +867,8 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, } QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1); if (s) { - if (s->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors)) + if (s->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors, + registrationType)) return true; if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) { // qualified, and only 1 url @@ -872,18 +891,20 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType *type_return, - QString *base, QList<QQmlError> *errors) + QString *base, QList<QQmlError> *errors, + QQmlType::RegistrationType registrationType) { bool typeRecursionDetected = false; for (int i=0; i<imports.count(); ++i) { const QQmlImportInstance *import = imports.at(i); if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, - base, &typeRecursionDetected)) { + base, &typeRecursionDetected, registrationType)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; j<imports.count(); ++j) { const QQmlImportInstance *import2 = imports.at(j); - if (import2->resolveType(typeLoader, type, vmajor, vminor, 0, base)) { + if (import2->resolveType(typeLoader, type, vmajor, vminor, nullptr, base, + nullptr, registrationType)) { if (errors) { QString u1 = import->url; QString u2 = import2->url; diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 8a0a4ea4f1..1bdd287690 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -87,7 +87,8 @@ struct QQmlImportInstance bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType* type_return, - QString *base = 0, bool *typeRecursionDetected = 0) const; + QString *base = 0, bool *typeRecursionDetected = 0, + QQmlType::RegistrationType = QQmlType::AnyRegistrationType) const; }; class QQmlImportNamespace @@ -102,7 +103,9 @@ public: bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, QQmlType* type_return, - QString *base = 0, QList<QQmlError> *errors = 0); + QString *base = 0, QList<QQmlError> *errors = 0, + QQmlType::RegistrationType registrationType + = QQmlType::AnyRegistrationType); // Prefix when used as a qualified import. Otherwise empty. QHashedString prefix; @@ -128,10 +131,14 @@ public: QQmlType *type_return, int *version_major, int *version_minor, QQmlImportNamespace **ns_return, - QList<QQmlError> *errors = 0) const; + QList<QQmlError> *errors = 0, + QQmlType::RegistrationType registrationType + = QQmlType::AnyRegistrationType) const; bool resolveType(QQmlImportNamespace *, const QHashedStringRef& type, - QQmlType *type_return, int *version_major, int *version_minor) const; + QQmlType *type_return, int *version_major, int *version_minor, + QQmlType::RegistrationType registrationType + = QQmlType::AnyRegistrationType) const; bool addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlError> *errors); diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 74b1cf0e06..4bfdf52de1 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -252,7 +252,8 @@ public: SingletonType = 1, InterfaceType = 2, CompositeType = 3, - CompositeSingletonType = 4 + CompositeSingletonType = 4, + AnyRegistrationType = 255 }; private: diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 342e6c0725..193acb04be 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2612,7 +2612,8 @@ void QQmlTypeData::resolveTypes() int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1; int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1; - if (!resolveType(typeName, majorVersion, minorVersion, ref)) + if (!resolveType(typeName, majorVersion, minorVersion, ref, -1, -1, true, + QQmlType::CompositeSingletonType)) return; if (ref.type.isCompositeSingleton()) { @@ -2640,7 +2641,9 @@ void QQmlTypeData::resolveTypes() const QString name = stringAt(unresolvedRef.key()); - if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors) && reportErrors) + if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, + unresolvedRef->location.column, reportErrors, + QQmlType::AnyRegistrationType) && reportErrors) return; if (ref.type.isComposite()) { @@ -2710,20 +2713,22 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( return noError; } -bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber, int columnNumber, bool reportErrors) +bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, + TypeReference &ref, int lineNumber, int columnNumber, + bool reportErrors, QQmlType::RegistrationType registrationType) { QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; - bool typeFound = m_importCache.resolveType(typeName, &ref.type, - &majorVersion, &minorVersion, &typeNamespace, &errors); + bool typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + &typeNamespace, &errors, registrationType); if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { // Lazy loading of implicit import if (loadImplicitImport()) { // Try again to find the type errors.clear(); - typeFound = m_importCache.resolveType(typeName, &ref.type, - &majorVersion, &minorVersion, &typeNamespace, &errors); + typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion, + &typeNamespace, &errors, registrationType); } else { return false; //loadImplicitImport() hit an error, and called setError already } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index abc0df9068..ef63e02b4f 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -474,7 +474,10 @@ private: const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher); void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); - bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true); + bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, + TypeReference &ref, int lineNumber = -1, int columnNumber = -1, + bool reportErrors = true, + QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType); void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override; |