diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-09-12 10:53:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-13 10:29:22 +0200 |
commit | 4b5a7b15fc6d3650c8e9b7bf619804a0a953eeba (patch) | |
tree | dc0e6952e2e6ee26118bcc14dc1f573fa9216593 /src/qml/qml | |
parent | 8c2201e2e51e9a6c09b4f91c4b4fc09b2c82f4af (diff) |
[new compiler] Implement proper type resolution
Collect all references to unknown types after parsing, re-use the existing code
in QQmlTypeLoader to resolve them and finally use the resolved references map
in the QQmlObjectCreator instead of the type name cache directly.
Change-Id: I8b83af4f8852e79c33985457081c024358bb9622
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlcompileddata.cpp | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 23 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 87 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 5 |
7 files changed, 121 insertions, 19 deletions
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp index a2e323a129..f9e36d59d2 100644 --- a/src/qml/qml/qqmlcompileddata.cpp +++ b/src/qml/qml/qqmlcompileddata.cpp @@ -116,6 +116,14 @@ QQmlCompiledData::~QQmlCompiledData() types.at(ii).typePropertyCache->release(); } + for (QHash<int, TypeReference>::Iterator resolvedType = resolvedTypes.begin(), end = resolvedTypes.end(); + resolvedType != end; ++resolvedType) { + if (resolvedType->component) + resolvedType->component->release(); + if (resolvedType->typePropertyCache) + resolvedType->typePropertyCache->release(); + } + for (int ii = 0; ii < propertyCaches.count(); ++ii) propertyCaches.at(ii)->release(); diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index ca825a923d..ac304278ab 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -110,7 +110,12 @@ public: QQmlPropertyCache *propertyCache() const; QQmlPropertyCache *createPropertyCache(QQmlEngine *); }; + // --- old compiler: QList<TypeReference> types; + // --- new compiler: + // map from name index + QHash<int, TypeReference> resolvedTypes; + // --- struct V8Program { V8Program(const QByteArray &p, QQmlCompiledData *c) diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index dfa8fc701d..1becbe8f68 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -900,7 +900,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context) if (cc->compilationUnit && !cc->compilationUnit->engine) cc->compilationUnit->linkToEngine(v4); - state.creator = new QmlObjectCreator(context, cc->qmlUnit, cc->compilationUnit, cc->importCache, + state.creator = new QmlObjectCreator(context, cc->qmlUnit, cc->compilationUnit, cc->resolvedTypes, cc->propertyCaches, cc->datas); rv = state.creator->create(); if (!rv) diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 89c3028269..cca4bb7dac 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -60,21 +60,22 @@ QT_USE_NAMESPACE static QAtomicInt classIndexCounter(0); -QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, QQmlTypeNameCache *typeNameCache, const QQmlImports *imports) +QQmlPropertyCacheCreator::QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, const QUrl &url, const QQmlImports *imports, + QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes) : enginePrivate(enginePrivate) , unit(unit) , url(url) - , typeNameCache(typeNameCache) , imports(imports) + , resolvedTypes(resolvedTypes) { } bool QQmlPropertyCacheCreator::create(const QV4::CompiledData::Object *obj, QQmlPropertyCache **resultCache, QByteArray *vmeMetaObjectData) { - QQmlTypeNameCache::Result res = typeNameCache->query(stringAt(obj->inheritedTypeNameIndex)); - Q_ASSERT(res.isValid()); // types resolved earlier in resolveTypes() + QQmlType *baseType = resolvedTypes->value(obj->inheritedTypeNameIndex).type; + Q_ASSERT(baseType); - QQmlPropertyCache *baseTypeCache = enginePrivate->cache(res.type->metaObject()); + QQmlPropertyCache *baseTypeCache = enginePrivate->cache(baseType->metaObject()); if (obj->nProperties == 0 && obj->nSignals == 0 && obj->nFunctions == 0) { *resultCache = baseTypeCache; vmeMetaObjectData->clear(); @@ -441,14 +442,15 @@ static void removeBindingOnProperty(QObject *o, int index) } QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit, - const QV4::CompiledData::CompilationUnit *jsUnit, QQmlTypeNameCache *typeNameCache, + const QV4::CompiledData::CompilationUnit *jsUnit, + const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache*> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData) : engine(contextData->engine) , unit(qmlUnit) , jsUnit(jsUnit) , context(contextData) - , typeNameCache(typeNameCache) + , resolvedTypes(resolvedTypes) , propertyCaches(propertyCaches) , vmeMetaObjectData(vmeMetaObjectData) , _qobject(0) @@ -546,11 +548,10 @@ QObject *QmlObjectCreator::create(int index, QObject *parent) { const QV4::CompiledData::Object *obj = unit->objectAt(index); - QQmlTypeNameCache::Result res = typeNameCache->query(stringAt(obj->inheritedTypeNameIndex)); - if (!res.isValid()) - return 0; + QQmlType *type = resolvedTypes.value(obj->inheritedTypeNameIndex).type; + Q_ASSERT(type); - QObject *result = res.type->create(); + QObject *result = type->create(); // ### use no-event variant if (parent) result->setParent(parent); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 31d9d0d176..673809dd9b 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -44,6 +44,7 @@ #include <private/qqmlimport_p.h> #include <private/qqmltypenamecache_p.h> #include <private/qv4compileddata_p.h> +#include <private/qqmlcompiler_p.h> QT_BEGIN_NAMESPACE @@ -54,7 +55,8 @@ class QQmlPropertyCacheCreator Q_DECLARE_TR_FUNCTIONS(QQmlPropertyCacheCreator) public: QQmlPropertyCacheCreator(QQmlEnginePrivate *enginePrivate, const QV4::CompiledData::QmlUnit *unit, - const QUrl &url, QQmlTypeNameCache *typeNameCache, const QQmlImports *imports); + const QUrl &url, const QQmlImports *imports, + QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes); QList<QQmlError> errors; @@ -67,8 +69,8 @@ protected: QQmlEnginePrivate *enginePrivate; const QV4::CompiledData::QmlUnit *unit; QUrl url; - QQmlTypeNameCache *typeNameCache; const QQmlImports *imports; + QHash<int, QQmlCompiledData::TypeReference> *resolvedTypes; }; class QmlObjectCreator @@ -76,7 +78,7 @@ class QmlObjectCreator Q_DECLARE_TR_FUNCTIONS(QmlObjectCreator) public: QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::CompilationUnit *jsUnit, - QQmlTypeNameCache *typeNameCache, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData); + const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData); QObject *create(QObject *parent = 0) { return create(unit->indexOfRootObject, parent); } @@ -102,7 +104,7 @@ private: const QV4::CompiledData::QmlUnit *unit; const QV4::CompiledData::CompilationUnit *jsUnit; QQmlContextData *context; - QQmlTypeNameCache *typeNameCache; + const QHash<int, QQmlCompiledData::TypeReference> resolvedTypes; const QList<QQmlPropertyCache *> propertyCaches; const QList<QByteArray> vmeMetaObjectData; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0f83da7b0a..e1f96442b1 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2167,6 +2167,13 @@ void QQmlTypeData::compile() m_imports.populateCache(m_compiledData->importCache); m_compiledData->importCache->addref(); + for (QHash<int, TypeReference>::ConstIterator resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); + resolvedType != end; ++resolvedType) { + QQmlCompiledData::TypeReference ref; + ref.type = resolvedType->type; + m_compiledData->resolvedTypes.insert(resolvedType.key(), ref); + } + JSCodeGen jsCodeGen; jsCodeGen.generateJSCodeForFunctionsAndBindings(finalUrlString(), parsedQML.data()); @@ -2196,8 +2203,8 @@ void QQmlTypeData::compile() m_compiledData->propertyCaches.reserve(qmlUnit->nObjects); QQmlPropertyCacheCreator propertyCacheBuilder(QQmlEnginePrivate::get(m_typeLoader->engine()), - qmlUnit, m_compiledData->url, m_compiledData->importCache, - &m_imports); + qmlUnit, m_compiledData->url, + &m_imports, &m_compiledData->resolvedTypes); for (quint32 i = 0; i < qmlUnit->nObjects; ++i) { const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i); @@ -2255,10 +2262,10 @@ void QQmlTypeData::resolveTypes() m_scripts << ref; } + // --- old compiler: foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) { TypeReference ref; - QString url; int majorVersion = -1; int minorVersion = -1; QQmlImportNamespace *typeNamespace = 0; @@ -2318,6 +2325,80 @@ void QQmlTypeData::resolveTypes() m_types << ref; } + + // --- new compiler: + QV4::CompiledData::TypeReferenceMap typeReferences; + QStringList names; + if (parsedQML) { + typeReferences = parsedQML->typeReferences; + names = parsedQML->jsGenerator.strings; + } else { + // ### collect from available QV4::CompiledData::QmlUnit + } + for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = typeReferences.constBegin(), end = typeReferences.constEnd(); + unresolvedRef != end; ++unresolvedRef) { + + TypeReference ref; // resolved reference + + int majorVersion = -1; + int minorVersion = -1; + QQmlImportNamespace *typeNamespace = 0; + QList<QQmlError> errors; + + const QString name = names.at(unresolvedRef.key()); + bool typeFound = m_imports.resolveType(name, &ref.type, + &majorVersion, &minorVersion, &typeNamespace, &errors); + if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { + // Lazy loading of implicit import + if (loadImplicitImport()) { + // Try again to find the type + errors.clear(); + typeFound = m_imports.resolveType(name, &ref.type, + &majorVersion, &minorVersion, &typeNamespace, &errors); + } else { + return; //loadImplicitImport() hit an error, and called setError already + } + } + + if (!typeFound || typeNamespace) { + // Known to not be a type: + // - known to be a namespace (Namespace {}) + // - type with unknown namespace (UnknownNamespace.SomeType {}) + QQmlError error; + if (typeNamespace) { + error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(name)); + } else { + if (errors.size()) { + error = errors.takeFirst(); + } else { + // this should not be possible! + // Description should come from error provided by addImport() function. + error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database")); + } + error.setUrl(m_imports.baseUrl()); + error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(name).arg(error.description())); + } + + error.setLine(unresolvedRef->line); + error.setColumn(unresolvedRef->column); + + errors.prepend(error); + setError(errors); + return; + } + + if (ref.type->isComposite()) { + ref.typeData = typeLoader()->getType(ref.type->sourceUrl()); + addDependency(ref.typeData); + } + ref.majorVersion = majorVersion; + ref.minorVersion = minorVersion; + + ref.location.line = unresolvedRef->line; + ref.location.column = unresolvedRef->column; + + m_resolvedTypes.insert(unresolvedRef.key(), ref); + } } void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &/*nameSpace*/) diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 3a3fa8f1d5..c77c5b1a8d 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -457,7 +457,12 @@ private: QSet<QString> m_namespaces; + // --- old compiler QList<TypeReference> m_types; + // --- new compiler + // map from name index to resolved type + QHash<int, TypeReference> m_resolvedTypes; + // --- bool m_typesResolved:1; bool m_useNewCompiler:1; |