diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-09-12 16:53:32 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-20 14:26:05 +0200 |
commit | 3ec5aae38e77d370d1a23efe4b924ee4762a2238 (patch) | |
tree | bff7f62c5daa35a2e045d87a0ea882d211d05c4e | |
parent | 6042327dee1f8dd912a86be16f4044d259c9b3e4 (diff) |
[new compiler] Add support for id properties
Change-Id: Idb4a0ad06f6cbe5d040da075a8f43d067a27ebc4
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 45 | ||||
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 15 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 8 |
7 files changed, 80 insertions, 3 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index b875067620..2bd00f2a1f 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -705,6 +705,12 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i { if (!sanityCheckPropertyName(nameLocation, propertyNameIndex)) return; + + if (stringAt(propertyNameIndex) == QStringLiteral("id")) { + setId(value); + return; + } + Binding *binding = New<Binding>(); binding->propertyNameIndex = propertyNameIndex; setBindingValue(binding, value); @@ -722,6 +728,45 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i _object->bindings->append(binding); } +bool QQmlCodeGenerator::setId(AST::Statement *value) +{ + AST::SourceLocation loc = value->firstSourceLocation(); + QStringRef str; + + if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(value)) + if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(stmt->expression)) + str = lit->value; + + if (str.isEmpty()) + str = asStringRef(value); + + if (str.isEmpty()) + COMPILE_EXCEPTION(loc, tr( "Invalid empty ID")); + + QChar ch = str.at(0); + if (ch.isLetter() && !ch.isLower()) + COMPILE_EXCEPTION(loc, tr( "IDs cannot start with an uppercase letter")); + + QChar u(QLatin1Char('_')); + if (!ch.isLetter() && ch != u) + COMPILE_EXCEPTION(loc, tr( "IDs must start with a letter or underscore")); + + for (int ii = 1; ii < str.count(); ++ii) { + ch = str.at(ii); + if (!ch.isLetterOrNumber() && ch != u) + COMPILE_EXCEPTION(loc, tr( "IDs must contain only letters, numbers, and underscores")); + } + +#if 0 // ### + if (enginePrivate->v8engine()->illegalNames().contains(str)) + COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property")); +#endif + + _object->idIndex = registerString(str.toString()); + + return true; +} + AST::UiQualifiedId *QQmlCodeGenerator::resolveQualifiedId(AST::UiQualifiedId *name, QmlObject **object) { *object = _object; diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h index 5344dc1535..3e14a32bce 100644 --- a/src/qml/compiler/qqmlcodegenerator_p.h +++ b/src/qml/compiler/qqmlcodegenerator_p.h @@ -220,6 +220,8 @@ public: void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value); void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex); + bool setId(AST::Statement *value); + // resolves qualified name (font.pixelSize for example) and returns the last name along // with the object any right-hand-side of a binding should apply to. AST::UiQualifiedId *resolveQualifiedId(AST::UiQualifiedId *name, QmlObject **object); diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index ac304278ab..52d6fe210c 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -140,6 +140,8 @@ public: // --- new compiler QV4::CompiledData::CompilationUnit *compilationUnit; QV4::CompiledData::QmlUnit *qmlUnit; + // ### sub-context support + QHash<int, int> objectIndexToId; // --- struct Instruction { diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 955c940a9d..2063c5bb25 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -900,8 +900,21 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context) if (cc->compilationUnit && !cc->compilationUnit->engine) cc->compilationUnit->linkToEngine(v4); + // ### sub-contexts + QVector<QQmlContextData::ObjectIdMapping> mapping(cc->objectIndexToId.count()); + for (QHash<int, int>::ConstIterator it = cc->objectIndexToId.constBegin(), end = cc->objectIndexToId.constEnd(); + it != end; ++it) { + const QV4::CompiledData::Object *obj = cc->qmlUnit->objectAt(it.key()); + + QQmlContextData::ObjectIdMapping m; + m.id = it.value(); + m.name = cc->qmlUnit->header.stringAt(obj->idIndex); + mapping[m.id] = m; + } + context->setIdPropertyData(mapping); + state.creator = new QmlObjectCreator(context, cc->qmlUnit, cc->compilationUnit, cc->resolvedTypes, - cc->propertyCaches, cc->datas); + cc->propertyCaches, cc->datas, cc->objectIndexToId); rv = state.creator->create(); if (!rv) state.errors = state.creator->errors; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index a92bbeda9e..def5181f2d 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -446,7 +446,7 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::Comp const QV4::CompiledData::CompilationUnit *jsUnit, const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache*> &propertyCaches, - const QList<QByteArray> &vmeMetaObjectData) + const QList<QByteArray> &vmeMetaObjectData, const QHash<int, int> &objectIndexToId) : engine(contextData->engine) , unit(qmlUnit) , jsUnit(jsUnit) @@ -454,6 +454,7 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *contextData, const QV4::Comp , resolvedTypes(resolvedTypes) , propertyCaches(propertyCaches) , vmeMetaObjectData(vmeMetaObjectData) + , objectIndexToId(objectIndexToId) , _qobject(0) , _compiledObject(0) , _ddata(0) @@ -588,6 +589,10 @@ QObject *QmlObjectCreator::create(int index, QObject *parent) context->addObject(instance); + QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index); + if (idEntry != objectIndexToId.constEnd()) + context->setIdProperty(idEntry.value(), instance); + populateInstance(index, instance, cache); return instance; diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 509fda30e7..9891566a00 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -78,7 +78,8 @@ class QmlObjectCreator Q_DECLARE_TR_FUNCTIONS(QmlObjectCreator) public: QmlObjectCreator(QQmlContextData *contextData, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::CompilationUnit *jsUnit, - const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData); + const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes, const QList<QQmlPropertyCache *> &propertyCaches, const QList<QByteArray> &vmeMetaObjectData, + const QHash<int, int> &objectIndexToId); QObject *create(QObject *parent = 0) { return create(unit->indexOfRootObject, parent); } @@ -109,6 +110,7 @@ private: const QHash<int, QQmlCompiledData::TypeReference> resolvedTypes; const QList<QQmlPropertyCache *> propertyCaches; const QList<QByteArray> vmeMetaObjectData; + const QHash<int, int> &objectIndexToId; QObject *_qobject; const QV4::CompiledData::Object *_compiledObject; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 652018dd4b..db68631bbf 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2234,6 +2234,14 @@ void QQmlTypeData::compile() m_compiledData->propertyCaches << propertyCache; } + // ### support sub-contexts + for (quint32 i = 0; i < qmlUnit->nObjects; ++i) { + const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i); + const QString &id = qmlUnit->header.stringAt(obj->idIndex); + if (!id.isEmpty()) + m_compiledData->objectIndexToId.insert(i, m_compiledData->objectIndexToId.count()); + } + if (!errors.isEmpty()) { setError(errors); m_compiledData->release(); |