diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-10-01 09:04:50 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-08 10:04:38 +0100 |
commit | 4a2f09f14a4b79006e661b6d98c03909c4ba9db1 (patch) | |
tree | c5397277abe70e03849f17f54d834e7983697ff0 /src/qml/qml | |
parent | 4a662c21e669e964f9c3b835a91a38c9decf4ad4 (diff) |
[new compiler] Initial support for custom parsers
Enough to support the Connections {} element. What's missing are pre-compiled
bindings signal handlers.
Change-Id: I3ad1413fa636434d899ae8fb380249aaf40363dc
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 23 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 49 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 3 |
6 files changed, 74 insertions, 9 deletions
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 516f6653ca..d410d396e3 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -157,6 +157,8 @@ public: // index in first hash is component index, hash inside maps from object index in that scope to integer id QHash<int, QHash<int, int> > objectIndexToIdPerComponent; QHash<int, int> objectIndexToIdForRoot; + // hash key is object index + QHash<int, QByteArray> customParserData; QVector<int> customParserBindings; // index is binding identifier, value is compiled function index. bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); } diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 19e49009ce..0cc62fb988 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -230,6 +230,13 @@ void QQmlCustomParser::clearErrors() exceptions.clear(); } +QByteArray QQmlCustomParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) +{ + Q_UNUSED(qmlUnit) + Q_UNUSED(bindings) + return QByteArray(); +} + /*! Reports an error with the given \a description. @@ -256,7 +263,6 @@ void QQmlCustomParser::error(const QString& description) void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString& description) { QQmlError error; - QString exceptionDescription; error.setLine(prop.location().line); error.setColumn(prop.location().column); error.setDescription(description); @@ -271,7 +277,6 @@ void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& description) { QQmlError error; - QString exceptionDescription; error.setLine(node.location().line); error.setColumn(node.location().column); error.setDescription(description); @@ -279,6 +284,20 @@ void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& de } /*! + Reports an error in parsing \a binding, with the given \a description. + + An error is generated referring to the position of \a node in the source file. +*/ +void QQmlCustomParser::error(const QV4::CompiledData::Binding *binding, const QString &description) +{ + QQmlError error; + error.setLine(binding->location.line); + error.setColumn(binding->location.column); + error.setDescription(description); + exceptions << error; +} + +/*! If \a script is a simple enumeration expression (eg. Text.AlignLeft), returns the integer equivalent (eg. 1), and sets \a ok to true. diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index 27f7e00b31..3004b0f50c 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -126,6 +126,7 @@ public: Flags flags() const { return m_flags; } virtual QByteArray compile(const QList<QQmlCustomParserProperty> &)=0; + virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings); // ### make pure virtual virtual void setCustomData(QObject *, const QByteArray &)=0; QList<QQmlError> errors() const { return exceptions; } @@ -134,6 +135,7 @@ protected: void error(const QString& description); void error(const QQmlCustomParserProperty&, const QString& description); void error(const QQmlCustomParserNode&, const QString& description); + void error(const QV4::CompiledData::Binding *binding, const QString& description); int evaluateEnum(const QByteArray&, bool *ok) const; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 822708a73e..abf978801d 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -55,6 +55,7 @@ #include <QQmlComponent> #include <private/qqmlcomponent_p.h> #include <private/qqmlcodegenerator_p.h> +#include <private/qqmlcustomparser_p.h> QT_USE_NAMESPACE @@ -1237,6 +1238,7 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) bool isComponent = false; QObject *instance = 0; + QQmlCustomParser *customParser = 0; if (compiledData->isComponent(index)) { isComponent = true; @@ -1254,6 +1256,7 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex))); return 0; } + const int parserStatusCast = type->parserStatusCast(); if (parserStatusCast != -1) { QQmlParserStatus *parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast); @@ -1261,6 +1264,8 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) _parserStatusCallbacks[index] = parserStatus; parserStatus->d = &_parserStatusCallbacks[index]; } + + customParser = type->customParser(); } else { Q_ASSERT(typeRef.component); if (typeRef.component->qmlUnit->isSingleton()) @@ -1305,6 +1310,11 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) if (idEntry != objectIndexToId.constEnd()) context->setIdProperty(idEntry.value(), instance); + if (customParser) { + QByteArray data = compiledData->customParserData.value(index); + customParser->setCustomData(instance, data); + } + if (!isComponent) { QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index); Q_ASSERT(!cache.isNull()); @@ -1727,11 +1737,13 @@ bool QQmlComponentAndAliasResolver::resolveAliases() QQmlPropertyValidator::QQmlPropertyValidator(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit, const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, - const QList<QQmlPropertyCache *> &propertyCaches, const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent) + const QList<QQmlPropertyCache *> &propertyCaches, const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent, + QHash<int, QByteArray> *customParserData) : QQmlCompilePass(url, qmlUnit) , resolvedTypes(resolvedTypes) , propertyCaches(propertyCaches) , objectIndexToIdPerComponent(objectIndexToIdPerComponent) + , customParserData(customParserData) { } @@ -1756,6 +1768,12 @@ bool QQmlPropertyValidator::validate() bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache) { + QQmlCustomParser *customParser = 0; + QQmlCompiledData::TypeReference objectType = resolvedTypes.value(obj->inheritedTypeNameIndex); + if (objectType.type) + customParser = objectType.type->customParser(); + QList<const QV4::CompiledData::Binding*> customBindings; + PropertyResolver propertyResolver(propertyCache); QQmlPropertyData *defaultProperty = propertyCache->defaultProperty(); @@ -1763,8 +1781,11 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, const QV4::CompiledData::Binding *binding = obj->bindingTable(); for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) { if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty - || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) + || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) { + if (customParser) + customBindings << binding; continue; + } const QString name = stringAt(binding->propertyNameIndex); @@ -1777,9 +1798,8 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, if (notInRevision) { QString typeName = stringAt(obj->inheritedTypeNameIndex); - QQmlCompiledData::TypeReference type = resolvedTypes.value(objectIndex); - if (type.type) { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion)); + if (objectType.type) { + COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType.type->module()).arg(objectType.majorVersion).arg(objectType.minorVersion)); } else { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); } @@ -1790,6 +1810,10 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, } if (!pd) { + if (customParser) { + customBindings << binding; + continue; + } if (bindingToDefaultProperty) { COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent default property")); } else { @@ -1798,5 +1822,20 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, } } + if (customParser && !customBindings.isEmpty()) { + customParser->clearErrors(); + QByteArray data = customParser->compile(qmlUnit, customBindings); + customParserData->insert(objectIndex, data); + const QList<QQmlError> parserErrors = customParser->errors(); + if (!parserErrors.isEmpty()) { + foreach (QQmlError error, parserErrors) { + error.setUrl(url); + errors << error; + } + return false; + } + } + return true; } + diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 229a7de198..e33e47edcc 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -122,7 +122,8 @@ public: QQmlPropertyValidator(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit, const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, - const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent); + const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent, + QHash<int, QByteArray> *customParserData); bool validate(); @@ -134,6 +135,7 @@ private: const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes; const QList<QQmlPropertyCache *> &propertyCaches; const QHash<int, QHash<int, int> > objectIndexToIdPerComponent; + QHash<int, QByteArray> *customParserData; }; class QmlObjectCreator : public QQmlCompilePass diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 60fa00a5c9..1a4c8f015d 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2466,7 +2466,8 @@ void QQmlTypeData::compile() // Sanity check property bindings if (errors.isEmpty()) { QQmlPropertyValidator validator(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes, - m_compiledData->propertyCaches, m_compiledData->objectIndexToIdPerComponent); + m_compiledData->propertyCaches, m_compiledData->objectIndexToIdPerComponent, + &m_compiledData->customParserData); if (!validator.validate()) errors << validator.errors; } |