diff options
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 50 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 39 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser_p.h | 14 |
6 files changed, 89 insertions, 35 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 56351b0013..d6dde63d4b 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1120,6 +1120,11 @@ bool QQmlPropertyValidator::validate() return true; } +const QQmlImports &QQmlPropertyValidator::imports() const +{ + return *compiler->imports(); +} + bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache) { QQmlCustomParser *customParser = 0; @@ -1181,7 +1186,9 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, if (customParser && !customBindings.isEmpty()) { customParser->clearErrors(); + customParser->compiler = this; QByteArray data = customParser->compile(qmlUnit, customBindings); + customParser->compiler = 0; customParserData->insert(objectIndex, data); const QList<QQmlError> parserErrors = customParser->errors(); if (!parserErrors.isEmpty()) { diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index bd136ea9e6..248cd12796 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -172,7 +172,7 @@ protected: QHash<int, QHash<int, int> > *objectIndexToIdPerComponent; }; -class QQmlPropertyValidator : public QQmlCompilePass +class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend { Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator) public: @@ -180,6 +180,10 @@ public: bool validate(); + // Re-implemented for QQmlCustomParser + virtual const QQmlImports &imports() const; + + private: bool validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache); diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 6717c97d88..069345ecd3 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -2614,7 +2614,7 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, if (isIntProp) { // Allow enum assignment to ints. bool ok; - int enumval = evaluateEnum(typeName, enumValue.toUtf8(), &ok); + int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok); if (ok) { v->type = Value::Literal; v->value = QQmlScript::Variant((double)enumval); @@ -2665,46 +2665,38 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop, return true; } -// Similar logic to above, but not knowing target property. -int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const +int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt) { - Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer"); - *ok = false; + JSBindingReference *reference = pool->New<JSBindingReference>(); + reference->expression = value; + reference->property = pool->New<Property>(); + reference->property->setName(name); + reference->value = 0; + reference->bindingContext = ctxt; + reference->bindingContext.owner++; + // Unfortunately this is required for example for PropertyChanges where the bindings + // will be executed in the dynamic scope of the target, so we can't resolve any lookups + // at run-time. + reference->disableLookupAcceleration = true; - if (scope != QLatin1String("Qt")) { - QQmlType *type = 0; - unit->imports().resolveType(scope, &type, 0, 0, 0); - return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; - } + const int id = output->customParserBindings.count(); + output->customParserBindings.append(0); // Filled in later. + reference->customParserBindingsIndex = id; - const QMetaObject *mo = StaticQtMetaObject::get(); - int i = mo->enumeratorCount(); - while (i--) { - int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); - if (*ok) - return v; - } - return -1; -} + compileState->totalBindingsCount++; + compileState->bindings.prepend(reference); -const QMetaObject *QQmlCompiler::resolveType(const QString& name) const -{ - QQmlType *qmltype = 0; - if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0)) - return 0; - if (!qmltype) - return 0; - return qmltype->metaObject(); + return id; } -int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt) +QQmlBinding::Identifier QQmlCompiler::bindingIdentifier(const Variant &value, const QString &name, QQmlCustomParser *customParser) { JSBindingReference *reference = pool->New<JSBindingReference>(); reference->expression = value; reference->property = pool->New<Property>(); reference->property->setName(name); reference->value = 0; - reference->bindingContext = ctxt; + reference->bindingContext = QQmlCompilerTypes::BindingContext(customParser->object); reference->bindingContext.owner++; // Unfortunately this is required for example for PropertyChanges where the bindings // will be executed in the dynamic scope of the target, so we can't resolve any lookups diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index c94cee16cf..788def0288 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -65,6 +65,7 @@ #include <private/qqmlcodegenerator_p.h> #include "private/qv4identifier_p.h" #include <private/qqmljsastfwd_p.h> +#include "qqmlcustomparser_p.h" #include <QtCore/qbytearray.h> #include <QtCore/qset.h> @@ -332,7 +333,7 @@ namespace QQmlCompilerTypes { }; class QMetaObjectBuilder; -class Q_AUTOTEST_EXPORT QQmlCompiler +class Q_AUTOTEST_EXPORT QQmlCompiler : public QQmlCustomParserCompilerBackend { Q_DECLARE_TR_FUNCTIONS(QQmlCompiler) public: @@ -348,9 +349,10 @@ public: static bool isAttachedPropertyName(const QHashedStringRef &); static bool isSignalPropertyName(const QHashedStringRef &); - int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum - const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType int bindingIdentifier(const QString &name, const QQmlScript::Variant& value, const QQmlCompilerTypes::BindingContext &ctxt); // for QQmlCustomParser::bindingIndex + virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&value, const QString&name, QQmlCustomParser *customParser); + + virtual const QQmlImports &imports() const { return unit->imports(); } private: typedef QQmlCompiledData::Instruction Instruction; diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 3f8fc967f4..ca23451774 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -346,7 +346,44 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const */ QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Variant &value, const QString& name) { - return compiler->bindingIdentifier(name, value, QQmlCompilerTypes::BindingContext(object)); + return compiler->bindingIdentifier(value, name, this); +} + +struct StaticQtMetaObject : public QObject +{ + static const QMetaObject *get() + { return &staticQtMetaObject; } +}; + +int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const +{ + Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer"); + *ok = false; + + if (scope != QLatin1String("Qt")) { + QQmlType *type = 0; + imports().resolveType(scope, &type, 0, 0, 0); + return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; + } + + const QMetaObject *mo = StaticQtMetaObject::get(); + int i = mo->enumeratorCount(); + while (i--) { + int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok); + if (*ok) + return v; + } + return -1; +} + +const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const +{ + QQmlType *qmltype = 0; + if (!imports().resolveType(name, &qmltype, 0, 0, 0)) + return 0; + if (!qmltype) + return 0; + return qmltype->metaObject(); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index 39afa2a28e..2f1a9ddec8 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -108,6 +108,17 @@ private: QQmlCustomParserNodePrivate *d; }; +struct QQmlCustomParserCompilerBackend +{ + virtual ~QQmlCustomParserCompilerBackend() {} + virtual const QQmlImports &imports() const = 0; + + int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const; + const QMetaObject *resolveType(const QString& name) const; + + virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&, QQmlCustomParser *) { return QQmlBinding::Invalid; } +}; + class Q_QML_PRIVATE_EXPORT QQmlCustomParser { public: @@ -146,10 +157,11 @@ protected: private: QList<QQmlError> exceptions; - QQmlCompiler *compiler; + QQmlCustomParserCompilerBackend *compiler; QQmlScript::Object *object; Flags m_flags; friend class QQmlCompiler; + friend class QQmlPropertyValidator; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags) |