aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2017-10-18 15:50:32 +0200
committerUlf Hermann <ulf.hermann@qt.io>2017-10-19 16:26:14 +0000
commitffca73c79d7733f06416f211d5d544dd037c9532 (patch)
treeb9793da38a53c5bf46ed001a98e49d531232fe3c /src
parent3b6eeee177b64eebe240d51be0c7bb5f031471d8 (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.cpp53
-rw-r--r--src/qml/qml/qqmlimport_p.h15
-rw-r--r--src/qml/qml/qqmlmetatype_p.h3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp19
-rw-r--r--src/qml/qml/qqmltypeloader_p.h5
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;