[new compiler] Move component determination and alias resolving
authorSimon Hausmann <simon.hausmann@digia.com>
Thu, 12 Dec 2013 15:23:14 +0000 (16:23 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 9 Jan 2014 09:33:00 +0000 (10:33 +0100)
Move the code before the JS code generation, as we are going to need the
component boundaries for the correct scoping. This requires the component and
alias resolver to operate on the pre-compiled-data data structures.

Change-Id: I8d2e697d8a05e5a4914db93e785704f6b2434a2e
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qqmltypecompiler.cpp
src/qml/qml/qqmlobjectcreator.cpp
src/qml/qml/qqmlobjectcreator_p.h

index 7ff5570..96b69d0 100644 (file)
@@ -151,6 +151,18 @@ bool QQmlTypeCompiler::compile()
         compiledData->scripts << scriptData;
     }
 
+    // Resolve component boundaries and aliases
+
+    {
+        // Scan for components, determine their scopes and resolve aliases within the scope.
+        QQmlComponentAndAliasResolver resolver(compiledData->url, parsedQML->jsGenerator.strings, parsedQML->objects, parsedQML->indexOfRootObject, compiledData->resolvedTypes, compiledData->propertyCaches,
+                                               &compiledData->datas, &compiledData->objectIndexToIdForRoot, &compiledData->objectIndexToIdPerComponent);
+        if (!resolver.resolve()) {
+            errors << resolver.errors;
+            return false;
+        }
+    }
+
     // Compile JS binding expressions and signal handlers
 
     JSCodeGen jsCodeGen(typeData->finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, compiledData->importCache);
@@ -178,18 +190,6 @@ bool QQmlTypeCompiler::compile()
         compiledData->compilationUnit->ref();
     compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
 
-    // Resolve component boundaries and aliases
-
-    {
-        // Scan for components, determine their scopes and resolve aliases within the scope.
-        QQmlComponentAndAliasResolver resolver(compiledData->url, compiledData->qmlUnit, compiledData->resolvedTypes, compiledData->propertyCaches,
-                                               &compiledData->datas, &compiledData->objectIndexToIdForRoot, &compiledData->objectIndexToIdPerComponent);
-        if (!resolver.resolve()) {
-            errors << resolver.errors;
-            return false;
-        }
-    }
-
     // Add to type registry of composites
     if (compiledData->isCompositeType())
         engine->registerInternalCompositeType(compiledData);
index 69ccd4c..0c363b4 100644 (file)
@@ -73,13 +73,13 @@ struct ActiveOCRestorer
 
 QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QV4::CompiledData::QmlUnit *unit)
     : url(url)
-    , qmlUnit(unit)
+    , jsUnit(&unit->header)
 {
 }
 
 QQmlCompilePass::QQmlCompilePass(const QUrl &url, const QStringList &stringTable)
     : url(url)
-    , qmlUnit(0)
+    , jsUnit(0)
     , stringTable(stringTable)
 {
 
@@ -480,6 +480,7 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledD
     : QQmlCompilePass(compiledData->url, compiledData->qmlUnit)
     , componentAttached(0)
     , engine(parentContext->engine)
+    , qmlUnit(compiledData->qmlUnit)
     , jsUnit(compiledData->compilationUnit)
     , parentContext(parentContext)
     , context(0)
@@ -1468,12 +1469,14 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi
 }
 
 
-QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
+QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(const QUrl &url, const QStringList &stringTable, const QList<QmlObject *> &qmlObjects, int indexOfRootObject,
                                                                const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
                                                                const QList<QQmlPropertyCache *> &propertyCaches, QList<QByteArray> *vmeMetaObjectData,
                                                                QHash<int, int> *objectIndexToIdForRoot,
                                                                QHash<int, QHash<int, int> > *objectIndexToIdPerComponent)
-    : QQmlCompilePass(url, qmlUnit)
+    : QQmlCompilePass(url, stringTable)
+    , qmlObjects(qmlObjects)
+    , indexOfRootObject(indexOfRootObject)
     , _componentIndex(-1)
     , _objectIndexToIdInScope(0)
     , resolvedTypes(resolvedTypes)
@@ -1494,8 +1497,8 @@ bool QQmlComponentAndAliasResolver::resolve()
     // when someProperty _is_ a QQmlComponent. In that case the Item {}
     // should be implicitly surrounded by Component {}
 
-    for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
-        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
+    for (int i = 0; i < qmlObjects.count(); ++i) {
+        const QtQml::QmlObject *obj = qmlObjects.at(i);
         if (stringAt(obj->inheritedTypeNameIndex).isEmpty())
             continue;
 
@@ -1507,18 +1510,18 @@ bool QQmlComponentAndAliasResolver::resolve()
 
         componentRoots.append(i);
 
-        if (obj->nFunctions > 0)
+        if (obj->functions->count > 0)
             COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
-        if (obj->nProperties > 0)
+        if (obj->properties->count > 0)
             COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
-        if (obj->nSignals > 0)
+        if (obj->qmlSignals->count > 0)
             COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
 
-        if (obj->nBindings == 0)
+        if (obj->bindings->count == 0)
             COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification"));
 
-        const QV4::CompiledData::Binding *rootBinding = obj->bindingTable();
-        if (obj->nBindings > 1 || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
+        const QtQml::Binding *rootBinding = obj->bindings->first;
+        if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
             COMPILE_EXCEPTION(rootBinding, tr("Component elements may not contain properties other than id"));
 
         componentBoundaries.append(rootBinding->value.objectIndex);
@@ -1527,8 +1530,8 @@ bool QQmlComponentAndAliasResolver::resolve()
     std::sort(componentBoundaries.begin(), componentBoundaries.end());
 
     for (int i = 0; i < componentRoots.count(); ++i) {
-        const QV4::CompiledData::Object *component = qmlUnit->objectAt(componentRoots.at(i));
-        const QV4::CompiledData::Binding *rootBinding = component->bindingTable();
+        const QtQml::QmlObject *component  = qmlObjects.at(componentRoots.at(i));
+        const QtQml::Binding *rootBinding = component->bindings->first;
 
         _componentIndex = i;
         _idToObjectIndex.clear();
@@ -1550,7 +1553,7 @@ bool QQmlComponentAndAliasResolver::resolve()
     _objectIndexToIdInScope = objectIndexToIdForRoot;
     _objectsWithAliases.clear();
 
-    collectIdsAndAliases(qmlUnit->indexOfRootObject);
+    collectIdsAndAliases(indexOfRootObject);
 
     resolveAliases();
 
@@ -1559,7 +1562,7 @@ bool QQmlComponentAndAliasResolver::resolve()
 
 bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
 {
-    const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
+    const QtQml::QmlObject *obj = qmlObjects.at(objectIndex);
 
     QString id = stringAt(obj->idIndex);
     if (!id.isEmpty()) {
@@ -1571,15 +1574,14 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
         _objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
     }
 
-    const QV4::CompiledData::Property *property = obj->propertyTable();
-    for (quint32 i = 0; i < obj->nProperties; ++i, ++property)
+    for (QtQml::QmlProperty *property = obj->properties->first; property; property = property->next) {
         if (property->type == QV4::CompiledData::Property::Alias) {
             _objectsWithAliases.append(objectIndex);
             break;
         }
+    }
 
-    const QV4::CompiledData::Binding *binding = obj->bindingTable();
-    for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
+    for (QtQml::Binding *binding = obj->bindings->first; binding; binding = binding->next) {
         if (binding->type != QV4::CompiledData::Binding::Type_Object
             && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
             && binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
@@ -1599,7 +1601,7 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
 bool QQmlComponentAndAliasResolver::resolveAliases()
 {
     foreach (int objectIndex, _objectsWithAliases) {
-        const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
+        const QtQml::QmlObject *obj = qmlObjects.at(objectIndex);
 
         QQmlPropertyCache *propertyCache = propertyCaches.value(objectIndex);
         Q_ASSERT(propertyCache);
@@ -1608,8 +1610,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
         int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
         int effectiveAliasIndex = 0;
 
-        const QV4::CompiledData::Property *p = obj->propertyTable();
-        for (quint32 propertyIndex = 0; propertyIndex < obj->nProperties; ++propertyIndex, ++p) {
+        const QtQml::QmlProperty *p = obj->properties->first;
+        for (int propertyIndex = 0; propertyIndex < obj->properties->count; ++propertyIndex, p = p->next) {
             if (p->type != QV4::CompiledData::Property::Alias)
                 continue;
 
@@ -1645,7 +1647,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
             quint32 propertyFlags = QQmlPropertyData::IsAlias;
 
             if (property.isEmpty()) {
-                const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(targetObjectIndex);
+                const QtQml::QmlObject *targetObject = qmlObjects.at(targetObjectIndex);
                 QQmlCompiledData::TypeReference typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex);
 
                 if (typeRef.type)
@@ -1748,6 +1750,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(const QUrl &url, const QV4::Compile
                                              const QList<QQmlPropertyCache *> &propertyCaches, const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent,
                                              QHash<int, QByteArray> *customParserData)
     : QQmlCompilePass(url, qmlUnit)
+    , qmlUnit(qmlUnit)
     , resolvedTypes(resolvedTypes)
     , propertyCaches(propertyCaches)
     , objectIndexToIdPerComponent(objectIndexToIdPerComponent)
index d395f02..796d92a 100644 (file)
@@ -57,12 +57,12 @@ struct QQmlCompilePass
     QQmlCompilePass(const QUrl &url, const QStringList &stringTable);
     QList<QQmlError> errors;
 
-    QString stringAt(int idx) const { return qmlUnit ? qmlUnit->header.stringAt(idx): stringTable.at(idx); }
+    QString stringAt(int idx) const { return jsUnit ? jsUnit->stringAt(idx): stringTable.at(idx); }
 protected:
     void recordError(const QV4::CompiledData::Location &location, const QString &description);
 
     const QUrl url;
-    const QV4::CompiledData::QmlUnit *qmlUnit;
+    const QV4::CompiledData::Unit *jsUnit;
     const QStringList stringTable;
 };
 
@@ -86,12 +86,14 @@ class QQmlComponentAndAliasResolver : public QQmlCompilePass
 {
     Q_DECLARE_TR_FUNCTIONS(QQmlAnonymousComponentResolver)
 public:
-    QQmlComponentAndAliasResolver(const QUrl &url, const QV4::CompiledData::QmlUnit *qmlUnit,
-                                   const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
-                                   const QList<QQmlPropertyCache *> &propertyCaches,
-                                   QList<QByteArray> *vmeMetaObjectData,
-                                   QHash<int, int> *objectIndexToIdForRoot,
-                                   QHash<int, QHash<int, int> > *objectIndexToIdPerComponent);
+    QQmlComponentAndAliasResolver(const QUrl &url, const QStringList &stringTable,
+                                  const QList<QtQml::QmlObject*> &qmlObjects,
+                                  int indexOfRootObject,
+                                  const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes,
+                                  const QList<QQmlPropertyCache *> &propertyCaches,
+                                  QList<QByteArray> *vmeMetaObjectData,
+                                  QHash<int, int> *objectIndexToIdForRoot,
+                                  QHash<int, QHash<int, int> > *objectIndexToIdPerComponent);
 
     bool resolve();
 
@@ -102,6 +104,9 @@ protected:
     bool isComponentType(int typeNameIndex) const
     { return resolvedTypes.value(typeNameIndex).type == 0; }
 
+    const QList<QtQml::QmlObject*> &qmlObjects;
+    const int indexOfRootObject;
+
     // indices of objects that are of type QQmlComponent
     QVector<int> componentBoundaries;
 
@@ -134,6 +139,7 @@ private:
 
     bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
 
+    const QV4::CompiledData::QmlUnit *qmlUnit;
     const QHash<int, QQmlCompiledData::TypeReference> &resolvedTypes;
     const QList<QQmlPropertyCache *> &propertyCaches;
     const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
@@ -164,6 +170,7 @@ private:
     void setupFunctions();
 
     QQmlEngine *engine;
+    const QV4::CompiledData::QmlUnit *qmlUnit;
     const QV4::CompiledData::CompilationUnit *jsUnit;
     QQmlContextData *parentContext;
     QQmlContextData *context;