aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-12 14:43:56 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 14:26:01 +0200
commit6042327dee1f8dd912a86be16f4044d259c9b3e4 (patch)
tree48091ee06fc657dcbdd090a27b3ed0eec88bc55b /src/qml/compiler
parentbbb78a92a910d32b2886af62c218db87325eb6ce (diff)
[new compiler] Initial support for group properties
This implements support for "font.pixelSize: 24" for example. The representation in the compile data structure is so that font.pixelSize is short-hand for font { pixelSize: 24 } which means that inside the braces is a complete object initializer. For that initializer we create a dedicated CompiledData::Object, which however has its type name empty. When populating the outer instance then, the "font" property is read as QQmlValueType (a QObject) and instead of creating a new QObject we use that value type as instance to run the rest of the QML object initializer (everything in braces). Change-Id: Ic0a37ac77ab88f582546b9c09a3d06a07726420b Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp74
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h8
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
3 files changed, 78 insertions, 7 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 6ca7078e69..b875067620 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -152,21 +152,38 @@ bool QQmlCodeGenerator::visit(AST::UiProgram *)
bool QQmlCodeGenerator::visit(AST::UiObjectDefinition *node)
{
- int idx = defineQMLObject(node);
- appendBinding(AST::SourceLocation(), registerString(QString()), idx);
+ // The grammar can't distinguish between two different definitions here:
+ // Item { ... }
+ // versus
+ // font { ... }
+ // The former is a new binding with no property name and "Item" as type name,
+ // and the latter is a binding to the font property with no type name but
+ // only initializer.
+
+ AST::UiQualifiedId *lastId = node->qualifiedTypeNameId;
+ while (lastId->next)
+ lastId = lastId->next;
+ bool isType = lastId->name.unicode()->isUpper();
+ if (isType) {
+ int idx = defineQMLObject(node);
+ appendBinding(AST::SourceLocation(), registerString(QString()), idx);
+ } else {
+ int idx = defineQMLObject(/*qualfied type name id*/0, node->initializer);
+ appendBinding(node->qualifiedTypeNameId, idx);
+ }
return false;
}
bool QQmlCodeGenerator::visit(AST::UiObjectBinding *node)
{
int idx = defineQMLObject(node->qualifiedTypeNameId, node->initializer);
- appendBinding(node->qualifiedId->identifierToken, registerString(asString(node->qualifiedId)), idx);
+ appendBinding(node->qualifiedId, idx);
return false;
}
bool QQmlCodeGenerator::visit(AST::UiScriptBinding *node)
{
- appendBinding(node->qualifiedId->identifierToken, registerString(asString(node->qualifiedId)), node->statement);
+ appendBinding(node->qualifiedId, node->statement);
return false;
}
@@ -237,7 +254,9 @@ int QQmlCodeGenerator::defineQMLObject(AST::UiQualifiedId *qualifiedTypeNameId,
_object->inheritedTypeNameIndex = registerString(asString(qualifiedTypeNameId));
- AST::SourceLocation loc = qualifiedTypeNameId->firstSourceLocation();
+ AST::SourceLocation loc;
+ if (qualifiedTypeNameId)
+ loc = qualifiedTypeNameId->firstSourceLocation();
_object->location.line = loc.startLine;
_object->location.column = loc.startColumn;
@@ -664,6 +683,24 @@ void QQmlCodeGenerator::setBindingValue(QV4::CompiledData::Binding *binding, AST
}
}
+void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, AST::Statement *value)
+{
+ QmlObject *object = 0;
+ name = resolveQualifiedId(name, &object);
+ qSwap(_object, object);
+ appendBinding(name->identifierToken, registerString(name->name.toString()), value);
+ qSwap(_object, object);
+}
+
+void QQmlCodeGenerator::appendBinding(AST::UiQualifiedId *name, int objectIndex)
+{
+ QmlObject *object = 0;
+ name = resolveQualifiedId(name, &object);
+ qSwap(_object, object);
+ appendBinding(name->identifierToken, registerString(name->name.toString()), objectIndex);
+ qSwap(_object, object);
+}
+
void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value)
{
if (!sanityCheckPropertyName(nameLocation, propertyNameIndex))
@@ -685,9 +722,31 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
_object->bindings->append(binding);
}
+AST::UiQualifiedId *QQmlCodeGenerator::resolveQualifiedId(AST::UiQualifiedId *name, QmlObject **object)
+{
+ *object = _object;
+ while (name->next) {
+ Binding *binding = New<Binding>();
+ binding->propertyNameIndex = registerString(name->name.toString());
+ binding->value.type = QV4::CompiledData::Value::Type_Object;
+
+ int objIndex = defineQMLObject(0, 0);
+ binding->value.objectIndex = objIndex;
+
+ (*object)->bindings->append(binding);
+ *object = _objects[objIndex];
+
+ name = name->next;
+ }
+ return name;
+}
+
bool QQmlCodeGenerator::sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex)
{
- QString name = jsGenerator->strings.at(nameIndex);
+ const QString &name = jsGenerator->strings.at(nameIndex);
+ if (name.isEmpty())
+ return true;
+
if (_propertyNames.contains(name))
COMPILE_EXCEPTION(nameLocation, tr("Duplicate property name"));
@@ -720,7 +779,8 @@ void QQmlCodeGenerator::recordError(const AST::SourceLocation &location, const Q
void QQmlCodeGenerator::collectTypeReferences()
{
foreach (QmlObject *obj, _objects) {
- _typeReferences.add(obj->inheritedTypeNameIndex, obj->location);
+ if (!stringAt(obj->inheritedTypeNameIndex).isEmpty())
+ _typeReferences.add(obj->inheritedTypeNameIndex, obj->location);
for (QmlProperty *prop = obj->properties->first; prop; prop = prop->next) {
if (prop->type >= QV4::CompiledData::Property::Custom)
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index 97ba3ef075..5344dc1535 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -215,9 +215,15 @@ public:
void setBindingValue(QV4::CompiledData::Binding *binding, AST::Statement *statement);
+ void appendBinding(AST::UiQualifiedId *name, AST::Statement *value);
+ void appendBinding(AST::UiQualifiedId *name, int objectIndex);
void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, AST::Statement *value);
void appendBinding(const AST::SourceLocation &nameLocation, int propertyNameIndex, int objectIndex);
+ // 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);
+
bool sanityCheckPropertyName(const AST::SourceLocation &nameLocation, int nameIndex);
void recordError(const AST::SourceLocation &location, const QString &description);
@@ -229,6 +235,8 @@ public:
int registerString(const QString &str) const { return jsGenerator->registerString(str); }
template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
+ QString stringAt(int index) const { return jsGenerator->strings.at(index); }
+
QList<QQmlError> errors;
QList<QV4::CompiledData::Import*> _imports;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index c98d53a1fa..9f8bd80f4d 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -315,6 +315,9 @@ struct Property
struct Object
{
+ // An empty inherited type name suggests that this object doesn't require to be instantiated
+ // by itself but is merely used for grouped properties. It can therefore only have bindings,
+ // so nProperties, nFunctions and nSignals must be zero.
quint32 inheritedTypeNameIndex;
quint32 idIndex;
quint32 indexOfDefaultProperty;