aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-01-15 17:29:04 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-20 15:10:00 +0100
commitae0a2ea25714af603babe5aa0de364d1ebae1170 (patch)
tree91a0845dd397af79b30341aae64f6c24f0f43197 /src/qml/compiler
parentf8176d72ac491469ccf0288cbb86c0ccc12fb47b (diff)
[new compiler] Add support for QML list models
List model definitions make heavy use of custom parsers, which requires AST access as well as a general port to the new QQmlCustomParser API. Additional fixes in the custom parser support were needed to pass all tests: * Fix support for AcceptsSignalHandlers and AcceptsAttachedProperties * Don't call setCustomData unless the compiler generated data earlier Change-Id: Ic42f8a890391267c94f63d35f055b60fdbf3c83d Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp3
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h3
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp66
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h9
4 files changed, 66 insertions, 15 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 46bb07f8bc..629671399d 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -1640,7 +1640,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (elementName.isEmpty())
continue;
QQmlCompiledData::TypeReference *tr = unit->resolvedTypes.value(obj->inheritedTypeNameIndex);
- if (tr && tr->type && tr->type->customParser())
+ QQmlCustomParser *customParser = (tr && tr->type) ? tr->type->customParser() : 0;
+ if (customParser && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers))
continue;
QQmlPropertyCache *cache = unit->propertyCaches.value(objectIndex);
Q_ASSERT(cache);
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index f1050f4476..0b70701515 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -173,7 +173,8 @@ struct Pragma
struct CompiledFunctionOrExpression
{
CompiledFunctionOrExpression()
- : disableAcceleratedLookups(false)
+ : node(0)
+ , disableAcceleratedLookups(false)
{}
CompiledFunctionOrExpression(AST::Node *n)
: node(n)
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index a684ebd959..00fc9c5925 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -201,7 +201,7 @@ bool QQmlTypeCompiler::compile()
}
// Sanity check property bindings
- QQmlPropertyValidator validator(this);
+ QQmlPropertyValidator validator(this, runtimeFunctionIndices);
if (!validator.validate())
return false;
@@ -295,6 +295,16 @@ MemoryPool *QQmlTypeCompiler::memoryPool()
return parsedQML->jsParserEngine.pool();
}
+const QList<CompiledFunctionOrExpression> &QQmlTypeCompiler::functions() const
+{
+ return parsedQML->functions;
+}
+
+void QQmlTypeCompiler::setCustomParserBindings(const QVector<int> &bindings)
+{
+ compiledData->customParserBindings = bindings;
+}
+
QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
: compiler(typeCompiler)
{
@@ -1113,19 +1123,23 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
}
-QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
+QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector<int> &runtimeFunctionIndices)
: QQmlCompilePass(typeCompiler)
, qmlUnit(typeCompiler->qmlUnit())
, resolvedTypes(*typeCompiler->resolvedTypes())
, propertyCaches(typeCompiler->propertyCaches())
, objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
, customParserData(typeCompiler->customParserData())
+ , runtimeFunctionIndices(runtimeFunctionIndices)
{
}
bool QQmlPropertyValidator::validate()
{
- return validateObject(qmlUnit->indexOfRootObject);
+ if (!validateObject(qmlUnit->indexOfRootObject))
+ return false;
+ compiler->setCustomParserBindings(customParserBindings);
+ return true;
}
const QQmlImports &QQmlPropertyValidator::imports() const
@@ -1133,6 +1147,22 @@ const QQmlImports &QQmlPropertyValidator::imports() const
return *compiler->imports();
}
+AST::Node *QQmlPropertyValidator::astForBinding(int scriptIndex) const
+{
+ // ####
+ int reverseIndex = runtimeFunctionIndices.indexOf(scriptIndex);
+ if (reverseIndex == -1)
+ return 0;
+ return compiler->functions().value(reverseIndex).node;
+}
+
+QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *)
+{
+ int id = customParserBindings.count();
+ customParserBindings.append(binding->value.compiledScriptIndex);
+ return id;
+}
+
bool QQmlPropertyValidator::validateObject(int objectIndex)
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
@@ -1158,16 +1188,30 @@ bool QQmlPropertyValidator::validateObject(int objectIndex)
const QV4::CompiledData::Binding *binding = obj->bindingTable();
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) {
- if (!validateObject(binding->value.objectIndex))
- return false;
- }
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty
- || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
- if (customParser)
+ if (customParser) {
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
+ customBindings << binding;
+ continue;
+ }
+ } else if ((binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && (!customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
customBindings << binding;
- continue;
+ continue;
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Object
+ || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ customBindings << binding;
+ continue;
+ }
+ }
+
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ if (!validateObject(binding->value.objectIndex))
+ return false;
+ // Nothing further to check for attached properties.
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty)
+ continue;
}
const QString name = stringAt(binding->propertyNameIndex);
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index e6a34fa376..4340279df8 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -92,6 +92,8 @@ struct QQmlTypeCompiler
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent();
QHash<int, QByteArray> *customParserData();
QQmlJS::MemoryPool *memoryPool();
+ const QList<CompiledFunctionOrExpression> &functions() const;
+ void setCustomParserBindings(const QVector<int> &bindings);
private:
QList<QQmlError> errors;
@@ -176,13 +178,14 @@ class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCom
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
- QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler);
+ QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector<int> &runtimeFunctionIndices);
bool validate();
// Re-implemented for QQmlCustomParser
virtual const QQmlImports &imports() const;
-
+ virtual QQmlJS::AST::Node *astForBinding(int scriptIndex) const;
+ virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser);
private:
bool validateObject(int objectIndex);
@@ -194,6 +197,8 @@ private:
const QVector<QQmlPropertyCache *> &propertyCaches;
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, QByteArray> *customParserData;
+ QVector<int> customParserBindings;
+ const QVector<int> &runtimeFunctionIndices;
};
QT_END_NAMESPACE