aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp23
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h6
-rw-r--r--src/qml/compiler/qv4compileddata_p.h12
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp8
-rw-r--r--src/qml/qml/qqmlcompiler_p.h5
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp23
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h10
-rw-r--r--src/qml/qml/qqmltypeloader.cpp87
-rw-r--r--src/qml/qml/qqmltypeloader_p.h5
10 files changed, 162 insertions, 19 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 5d60c64639..6ca7078e69 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -109,6 +109,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
qSwap(_imports, output->imports);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
+ qSwap(_typeReferences, output->typeReferences);
this->pool = output->jsParserEngine.pool();
this->jsGenerator = &output->jsGenerator;
@@ -128,9 +129,13 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
AST::UiObjectDefinition *rootObject = AST::cast<AST::UiObjectDefinition*>(program->members->member);
Q_ASSERT(rootObject);
output->indexOfRootObject = defineQMLObject(rootObject);
+
+ collectTypeReferences();
+
qSwap(_imports, output->imports);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
+ qSwap(_typeReferences, output->typeReferences);
return true;
}
@@ -440,6 +445,8 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
}
param->nameIndex = registerString(p->name.toString());
+ param->location.line = p->identifierToken.startLine;
+ param->location.column = p->identifierToken.startColumn;
signal->parameters->append(param);
p = p->next;
}
@@ -710,6 +717,22 @@ void QQmlCodeGenerator::recordError(const AST::SourceLocation &location, const Q
errors << error;
}
+void QQmlCodeGenerator::collectTypeReferences()
+{
+ foreach (QmlObject *obj, _objects) {
+ _typeReferences.add(obj->inheritedTypeNameIndex, obj->location);
+
+ for (QmlProperty *prop = obj->properties->first; prop; prop = prop->next) {
+ if (prop->type >= QV4::CompiledData::Property::Custom)
+ _typeReferences.add(prop->customTypeNameIndex, prop->location);
+ }
+
+ for (Signal *sig = obj->qmlSignals->first; sig; sig = sig->next)
+ for (SignalParameter *param = sig->parameters->first; param; param = param->next)
+ _typeReferences.add(param->customTypeNameIndex, param->location);
+ }
+}
+
QQmlScript::LocationSpan QQmlCodeGenerator::location(AST::SourceLocation start, AST::SourceLocation end)
{
QQmlScript::LocationSpan rv;
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 100c1df1a4..97ba3ef075 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -163,6 +163,8 @@ struct ParsedQML
QList<AST::Node*> functions; // FunctionDeclaration, Statement or Expression
QV4::Compiler::JSUnitGenerator jsGenerator;
+ QV4::CompiledData::TypeReferenceMap typeReferences;
+
QString stringAt(int index) const { return jsGenerator.strings.value(index); }
};
@@ -220,6 +222,8 @@ public:
void recordError(const AST::SourceLocation &location, const QString &description);
+ void collectTypeReferences();
+
static QQmlScript::LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
int registerString(const QString &str) const { return jsGenerator->registerString(str); }
@@ -231,6 +235,8 @@ public:
QList<QmlObject*> _objects;
QList<AST::Node*> _functions;
+ QV4::CompiledData::TypeReferenceMap _typeReferences;
+
QmlObject *_object;
QSet<QString> _propertyNames;
QSet<QString> _signalNames;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 7833097325..c98d53a1fa 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -44,6 +44,7 @@
#include <QtCore/qstring.h>
#include <QVector>
#include <QStringList>
+#include <QHash>
#include <private/qv4value_def_p.h>
#include <private/qv4executableallocator_p.h>
@@ -73,6 +74,16 @@ struct Location
int column;
};
+// map from name index to location of first use
+struct TypeReferenceMap : QHash<int, Location>
+{
+ void add(int nameIndex, const Location &loc) {
+ if (contains(nameIndex))
+ return;
+ insert(nameIndex, loc);
+ }
+};
+
struct RegExp
{
enum Flags {
@@ -263,6 +274,7 @@ struct Parameter
quint32 type;
quint32 customTypeNameIndex;
quint32 reserved;
+ Location location;
};
struct Signal
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;