Minor optimizations and cleanup
authorAaron Kennedy <aaron.kennedy@nokia.com>
Fri, 4 May 2012 12:14:43 +0000 (13:14 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 4 May 2012 16:15:03 +0000 (18:15 +0200)
Change-Id: Iecbd5c46af00f649b1f1d78cdf5f2b40a2844897
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
src/qml/qml/qqmlcompiler.cpp
src/qml/qml/qqmlcompiler_p.h
src/qml/qml/qqmlcustomparser.cpp
src/qml/qml/qqmlimport.cpp
src/qml/qml/qqmlimport_p.h
src/qml/qml/qqmlinstruction.cpp
src/qml/qml/qqmlscript.cpp
src/qml/qml/qqmlscript_p.h
src/qml/qml/qqmltypeloader.cpp
src/qml/qml/qqmlvme.cpp
tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp

index 5708a84..7d06ff3 100644 (file)
@@ -90,7 +90,6 @@ using namespace QQmlCompilerTypes;
 static QString id_string(QLatin1String("id"));
 static QString on_string(QLatin1String("on"));
 static QString Changed_string(QLatin1String("Changed"));
-static QString Component_string(QLatin1String("Component"));
 static QString Component_import_string(QLatin1String("QML/Component"));
 static QString qsTr_string(QLatin1String("qsTr"));
 static QString qsTrId_string(QLatin1String("qsTrId"));
@@ -793,22 +792,22 @@ bool QQmlCompiler::compile(QQmlEngine *engine,
                 QString err = ref.type->noCreationReason();
                 if (err.isEmpty())
                     err = tr( "Element is not creatable.");
-                COMPILE_EXCEPTION(parserRef->refObjects.first(), err);
+                COMPILE_EXCEPTION(parserRef->firstUse, err);
             }
             
             if (ref.type->containsRevisionedAttributes()) {
                 QQmlError cacheError;
-                ref.typePropertyCache = enginePrivate->cache(ref.type, resolvedTypes.at(ii).minorVersion, 
+                ref.typePropertyCache = enginePrivate->cache(ref.type,
+                                                             resolvedTypes.at(ii).minorVersion,
                                                              cacheError);
                 if (!ref.typePropertyCache) 
-                    COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description());
+                    COMPILE_EXCEPTION(parserRef->firstUse, cacheError.description());
                 ref.typePropertyCache->addref();
             }
 
         } else if (tref.typeData) {
             ref.component = tref.typeData->compiledData();
         }
-        ref.className = parserRef->name;
         out->types << ref;
     }
 
@@ -943,9 +942,6 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
     const QQmlCompiledData::TypeReference &tr = output->types.at(obj->type);
     obj->metatype = tr.metaObject();
 
-    if (tr.type) 
-        obj->typeName = tr.type->qmlTypeName();
-
     // This object is a "Component" element
     if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
         COMPILE_CHECK(buildComponent(obj, ctxt));
@@ -1614,7 +1610,6 @@ int QQmlCompiler::componentTypeRef()
             }
         }
         QQmlCompiledData::TypeReference ref;
-        ref.className = Component_string;
         ref.type = t;
         output->types << ref;
         cachedComponentTypeRef = output->types.count() - 1;
@@ -2399,7 +2394,6 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
             QQmlScript::Object *root = v->object;
             QQmlScript::Object *component = pool->New<Object>();
             component->type = componentTypeRef();
-            component->typeName = QStringLiteral("Qt/Component");
             component->metatype = &QQmlComponent::staticMetaObject;
             component->location = root->location;
             QQmlScript::Value *componentValue = pool->New<Value>();
@@ -2460,7 +2454,7 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
             buildDynamicMeta(baseObj, ForceCreation);
         v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
     } else {
-        COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(v->object->typeName).arg(prop->name().toString()));
+        COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(elementName(v->object)).arg(prop->name().toString()));
     }
 
     return true;
@@ -2540,14 +2534,6 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
     QQmlType *type = 0;
     unit->imports().resolveType(typeName, &type, 0, 0, 0, 0);
 
-    //handle enums on value types (where obj->typeName is empty)
-    QString objTypeName = obj->typeName;
-    if (objTypeName.isEmpty()) {
-        QQmlType *objType = toQmlType(obj);
-        if (objType)
-            objTypeName = objType->qmlTypeName();
-    }
-
     if (!type)
         return true;
 
@@ -2555,7 +2541,7 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
     int value;
     bool ok;
 
-    if (objTypeName == type->qmlTypeName()) {
+    if (toQmlType(obj) == type) {
         // When these two match, we can short cut the search
         if (mprop.isFlagType()) {
             value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
@@ -3736,7 +3722,7 @@ QString QQmlCompiler::elementName(QQmlScript::Object *o)
 {
     Q_ASSERT(o);
     if (o->type != -1) {
-        return output->types.at(o->type).className;
+        return unit->parser().referencedTypes().at(o->type)->name;
     } else {
         return QString();
     }
@@ -3744,6 +3730,9 @@ QString QQmlCompiler::elementName(QQmlScript::Object *o)
 
 QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
 {
+    if (from->type != -1 && output->types.at(from->type).type)
+        return output->types.at(from->type).type;
+
     // ### Optimize
     const QMetaObject *mo = from->metatype;
     QQmlType *type = 0;
index 5a52dcf..f2e2376 100644 (file)
@@ -94,7 +94,6 @@ public:
         TypeReference()
         : type(0), typePropertyCache(0), component(0) {}
 
-        QString className;
         QQmlType *type;
         QQmlPropertyCache *typePropertyCache;
         QQmlCompiledData *component;
@@ -403,7 +402,7 @@ private:
     int componentTypeRef();
     int translationContextIndex();
 
-    static QQmlType *toQmlType(QQmlScript::Object *from);
+    QQmlType *toQmlType(QQmlScript::Object *from);
     bool canCoerce(int to, QQmlScript::Object *from);
 
     QString elementName(QQmlScript::Object *);
index f888b61..67e580c 100644 (file)
@@ -97,7 +97,8 @@ QQmlCustomParserNode
 QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
 {
     QQmlCustomParserNode rootNode;
-    rootNode.d->name = root->typeName;
+    if (root->typeReference)
+        rootNode.d->name = root->typeReference->name;
     rootNode.d->location = root->location.start;
 
     for (Property *p = root->properties.first(); p; p = root->properties.next(p)) {
index 1417e3d..2f17137 100644 (file)
 #include <private/qqmlglobal_p.h>
 #include <private/qqmltypenamecache_p.h>
 #include <private/qqmlengine_p.h>
+#include <private/qfieldlist_p.h>
 
 QT_BEGIN_NAMESPACE
 
 DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE)
 DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
 
+static QString dotqml_string(QLatin1String(".qml"));
+
 QString resolveLocalUrl(const QString &url, const QString &relative)
 {
     if (relative.contains(QLatin1Char(':'))) {
@@ -111,6 +114,8 @@ Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores
 class QQmlImportNamespace
 {
 public:
+    QQmlImportNamespace() : nextNamespace(0) {}
+
     struct Import {
         QString uri;
         QString url;
@@ -131,6 +136,12 @@ public:
                      int *vmajor, int *vminor,
                      QQmlType** type_return, QString* url_return,
                      QString *base = 0, QList<QQmlError> *errors = 0);
+
+    // Prefix when used as a qualified import.  Otherwise empty.
+    QString prefix;
+
+    // Used by QQmlImportsPrivate::qualifiedSets
+    QQmlImportNamespace *nextNamespace;
 };
 
 class QQmlImportsPrivate
@@ -153,9 +164,11 @@ public:
     QString base;
     int ref;
 
-    QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
     QQmlImportNamespace unqualifiedset;
-    QHash<QString, QQmlImportNamespace *> set;
+
+    QQmlImportNamespace *findQualifiedNamespace(const QString &);
+    QFieldList<QQmlImportNamespace, &QQmlImportNamespace::nextNamespace> qualifiedSets;
+
     QQmlTypeLoader *typeLoader;
 
     static inline QString tr(const char *str) {
@@ -239,23 +252,22 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache, QQmlEngine *engine) co
             cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import.minversion));
     }
 
-    for (QHash<QString, QQmlImportNamespace* >::ConstIterator iter = d->set.begin();
-         iter != d->set.end(); 
-         ++iter) {
+    for (QQmlImportNamespace *ns = d->qualifiedSets.first(); ns; ns = d->qualifiedSets.next(ns)) {
+
+        const QQmlImportNamespace &set = *ns;
 
-        const QQmlImportNamespace &set = *iter.value();
         for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
             const QQmlImportNamespace::Import &import = set.imports.at(ii);
             QQmlTypeModule *module = QQmlMetaType::typeModule(import.uri, import.majversion);
             if (module) {
-                QQmlTypeNameCache::Import &typeimport = cache->m_namedImports[iter.key()];
+                QQmlTypeNameCache::Import &typeimport = cache->m_namedImports[set.prefix];
                 typeimport.modules.append(QQmlTypeModuleVersion(module, import.minversion));
             }
 
             QQmlMetaType::ModuleApi moduleApi = QQmlMetaType::moduleApi(import.uri, import.majversion,
                                                                         import.minversion);
             if (moduleApi.script || moduleApi.qobject) {
-                QQmlTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
+                QQmlTypeNameCache::Import &import = cache->m_namedImports[set.prefix];
                 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
                 import.moduleApi = ep->moduleApiInstance(moduleApi);
             }
@@ -280,10 +292,8 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
         }
     }
 
-    for (QHash<QString, QQmlImportNamespace* >::ConstIterator iter = d->set.constBegin();
-         iter != d->set.constEnd();
-         ++iter) {
-        const QQmlImportNamespace &set = *iter.value();
+    for (QQmlImportNamespace *ns = d->qualifiedSets.first(); ns; ns = d->qualifiedSets.next(ns)) {
+        const QQmlImportNamespace &set = *ns;
 
         for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
             const QQmlImportNamespace::Import &import = set.imports.at(ii);
@@ -291,7 +301,7 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
             foreach (const QQmlDirParser::Script &script, import.qmlDirScripts) {
                 ScriptReference ref;
                 ref.nameSpace = script.nameSpace;
-                ref.qualifier = iter.key();
+                ref.qualifier = set.prefix;
                 ref.location = QUrl(import.url).resolved(QUrl(script.fileName));
                 scripts.append(ref);
             }
@@ -319,7 +329,7 @@ bool QQmlImports::resolveType(const QString& type,
                               QQmlType** type_return, QString* url_return, int *vmaj, int *vmin,
                               QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const
 {
-    QQmlImportNamespace* ns = d->set.value(type);
+    QQmlImportNamespace* ns = d->findQualifiedNamespace(type);
     if (ns) {
         if (ns_return)
             *ns_return = ns;
@@ -383,13 +393,13 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
     bool typeWasDeclaredInQmldir = false;
     if (!qmlDirComponents.isEmpty()) {
         foreach (const QQmlDirParser::Component &c, qmlDirComponents) {
-            if (c.typeName == type) {
+            if (type == c.typeName) {
                 typeWasDeclaredInQmldir = true;
                 // importing version -1 means import ALL versions
                 if ((majversion == -1) || (c.majorVersion == majversion &&
                                            minversion >= c.minorVersion)) {
-                    QString candidate = resolveLocalUrl(QString(url + type + QLatin1String(".qml")),
-                                                        c.fileName);
+
+                    QString candidate = resolveLocalUrl(QString(url + type + dotqml_string), c.fileName);
                     if (c.internal && base) {
                         if (resolveLocalUrl(*base, c.fileName) != candidate)
                             continue; // failed attempt to access an internal type
@@ -408,7 +418,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
     }
 
     if (!typeWasDeclaredInQmldir && !isLibrary) {
-        QString qmlUrl(url + type + QLatin1String(".qml"));
+        QString qmlUrl = url + type + dotqml_string;
 
         bool exists = false;
 
@@ -439,10 +449,10 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin
                                      QList<QQmlError> *errors)
 {
     QQmlImportNamespace *s = 0;
-    int slash = type.indexOf(QLatin1Char('/'));
-    if (slash >= 0) {
-        QString namespaceName = type.left(slash);
-        s = set.value(namespaceName);
+    int dot = type.indexOf(QLatin1Char('.'));
+    if (dot >= 0) {
+        QString namespaceName = type.left(dot);
+        s = findQualifiedNamespace(namespaceName);
         if (!s) {
             if (errors) {
                 QQmlError error;
@@ -451,8 +461,8 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin
             }
             return false;
         }
-        int nslash = type.indexOf(QLatin1Char('/'),slash+1);
-        if (nslash > 0) {
+        int ndot = type.indexOf(QLatin1Char('.'),dot+1);
+        if (ndot > 0) {
             if (errors) {
                 QQmlError error;
                 error.setDescription(QQmlImportDatabase::tr("- nested namespaces not allowed"));
@@ -463,7 +473,7 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin
     } else {
         s = &unqualifiedset;
     }
-    QString unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
+    QString unqualifiedtype = dot < 0 ? type : type.mid(dot+1, -1);
     if (s) {
         if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors))
             return true;
@@ -477,8 +487,8 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin
     return false;
 }
 
-bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QString& type, int *vmajor,
-                                      int *vminor, QQmlType** type_return,
+bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QString& type,
+                                      int *vmajor, int *vminor, QQmlType** type_return,
                                       QString* url_return, QString *base, QList<QQmlError> *errors)
 {
     bool typeRecursionDetected = false;
@@ -496,10 +506,10 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QString&
                             QString u2 = imports.at(j).url;
                             if (base) {
                                 QString b = *base;
-                                int slash = b.lastIndexOf(QLatin1Char('/'));
-                                if (slash >= 0) {
-                                    b = b.left(slash+1);
-                                    QString l = b.left(slash);
+                                int dot = b.lastIndexOf(QLatin1Char('.'));
+                                if (dot >= 0) {
+                                    b = b.left(dot+1);
+                                    QString l = b.left(dot);
                                     if (u1.startsWith(b))
                                         u1 = u1.mid(b.count());
                                     else if (u1 == l)
@@ -546,8 +556,17 @@ QQmlImportsPrivate::QQmlImportsPrivate(QQmlTypeLoader *loader)
 
 QQmlImportsPrivate::~QQmlImportsPrivate()
 {
-    foreach (QQmlImportNamespace* s, set.values())
-        delete s;
+    while (QQmlImportNamespace *ns = qualifiedSets.takeFirst())
+        delete ns;
+}
+
+QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QString &prefix)
+{
+    for (QQmlImportNamespace *ns = qualifiedSets.first(); ns; ns = qualifiedSets.next(ns)) {
+        if (prefix == ns->prefix)
+            return ns;
+    }
+    return 0;
 }
 
 /*!
@@ -591,8 +610,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
         qDebug().nospace() << "QQmlImports(" << qPrintable(base) << "::importExtension: "
                            << "loaded " << qmldirFilePath;
 
-    if (!qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) {
-        qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(qmldirFilePath);
+    if (!database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) {
 
         QString qmldirPath = qmldirFilePath;
 
@@ -630,6 +648,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
                 return false;
             }
         }
+
+        database->qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(qmldirFilePath);
     }
 
     if (components)
@@ -789,10 +809,12 @@ bool QQmlImportsPrivate::addImport(const QQmlDirComponents &qmldircomponentsnetw
     if (prefix.isEmpty()) {
         importSet = &unqualifiedset;
     } else {
-        importSet = set.value(prefix);
+        importSet = findQualifiedNamespace(prefix);
+
         if (!importSet) {
             importSet = new QQmlImportNamespace;
-            set.insert(prefix, importSet);
+            importSet->prefix = prefix;
+            qualifiedSets.append(importSet);
         }
     }
 
index d673b64..ad0bbc6 100644 (file)
@@ -161,6 +161,7 @@ private:
     QStringList filePluginPath;
     QStringList fileImportPath;
 
+    QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded;
     QSet<QString> initializedPlugins;
     QQmlEngine *engine;
 };
index 82cf235..96136ff 100644 (file)
@@ -64,10 +64,10 @@ void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
         qWarning().nospace() << idx << "\t\t" << "DONE";
         break;
     case QQmlInstruction::CreateCppObject:
-        qWarning().nospace() << idx << "\t\t" << "CREATECPP\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+        qWarning().nospace() << idx << "\t\t" << "CREATECPP\t\t\t" << instr->create.type;
         break;
     case QQmlInstruction::CreateQMLObject:
-        qWarning().nospace() << idx << "\t\t" << "CREATEQML\t\t\t" << instr->createQml.type << "\t" << instr->createQml.bindingBits << "\t\t" << types.at(instr->createQml.type).className;
+        qWarning().nospace() << idx << "\t\t" << "CREATEQML\t\t\t" << instr->createQml.type << "\t" << instr->createQml.bindingBits;
         break;
     case QQmlInstruction::CompleteQMLObject:
         qWarning().nospace() << idx << "\t\t" << "COMPLETEQML";
index b1a50a4..704130d 100644 (file)
@@ -63,8 +63,8 @@ using namespace QQmlScript;
 // Parser IR classes
 //
 QQmlScript::Object::Object()
-: type(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1),
-  componentCompileState(0), nextAliasingObject(0), nextIdObject(0)
+: type(-1), typeReference(0), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0),
+  parserStatusCast(-1), componentCompileState(0), nextAliasingObject(0), nextIdObject(0)
 {
     // initialize the members in the meta object
     extObject.d.superdata = 0;
@@ -547,8 +547,6 @@ protected:
     QQmlScript::Object *currentObject() const;
     Property *currentProperty() const;
 
-    QString qualifiedNameId() const;
-
     QString textAt(const AST::SourceLocation &loc) const
     { return _contents->mid(loc.offset, loc.length); }
 
@@ -600,7 +598,6 @@ protected:
 private:
     QQmlScript::Parser *_parser;
     StateStack _stateStack;
-    QStringList _scope;
     const QString *_contents;
 };
 
@@ -642,11 +639,6 @@ Property *ProcessAST::currentProperty() const
     return state().property;
 }
 
-QString ProcessAST::qualifiedNameId() const
-{
-    return _scope.join(QLatin1String("/"));
-}
-
 void ProcessAST::extractVersion(QStringRef string, int *maj, int *min)
 {
     *maj = -1; *min = -1;
@@ -749,22 +741,10 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName,
     } else {
         // Class
 
-        QString resolvableObjectType = objectType;
-        if (lastTypeDot >= 0)
-            resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
-
        QQmlScript::Object *obj = _parser->_pool.New<QQmlScript::Object>();
 
-        QQmlScript::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
-        obj->type = typeRef->id;
-
-        typeRef->refObjects.append(obj);
-
-        // XXX this doesn't do anything (_scope never builds up)
-        _scope.append(resolvableObjectType);
-        obj->typeName = qualifiedNameId();
-        _scope.removeLast();
-
+        obj->type = _parser->findOrCreateTypeId(objectType, obj);
+        obj->typeReference = _parser->_refTypes.at(obj->type);
         obj->location = location;
 
         if (propertyCount) {
@@ -1059,9 +1039,8 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
         property->nameLocation.line = node->identifierToken.startLine;
         property->nameLocation.column = node->identifierToken.startColumn;
         if (type >= Object::DynamicProperty::Custom) {
-            QQmlScript::TypeReference *typeRef =
-                _parser->findOrCreateType(memberType.toString());
-            typeRef->refObjects.append(_stateStack.top().object);
+            // This forces the type to be added to the resolved types list
+            _parser->findOrCreateTypeId(memberType.toString(), _stateStack.top().object);
             property->customType = memberType;
         }
 
@@ -1301,7 +1280,7 @@ QByteArray QQmlScript::Parser::preparseData() const
     return QByteArray();
 }
 
-bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray &preparseData,
+bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* preparseData */,
                                const QUrl &url, const QString &urlString)
 {
     clear();
@@ -1672,7 +1651,6 @@ QQmlScript::Parser::JavaScriptMetaData QQmlScript::Parser::extractMetaData(QStri
 void QQmlScript::Parser::clear()
 {
     _imports.clear();
-    qDeleteAll(_refTypes);
     _refTypes.clear();
     _errors.clear();
 
@@ -1684,22 +1662,18 @@ void QQmlScript::Parser::clear()
     _pool.clear();
 }
 
-QQmlScript::TypeReference *QQmlScript::Parser::findOrCreateType(const QString &name)
+int QQmlScript::Parser::findOrCreateTypeId(const QString &name, Object *object)
 {
-    TypeReference *type = 0;
-    int i = 0;
-    for (; i < _refTypes.size(); ++i) {
-        if (_refTypes.at(i)->name == name) {
-            type = _refTypes.at(i);
-            break;
-        }
-    }
-    if (!type) {
-        type = new TypeReference(i, name);
-        _refTypes.append(type);
+    for (int ii = 0; ii < _refTypes.size(); ++ii) {
+        if (_refTypes.at(ii)->name == name)
+            return ii;
     }
 
-    return type;
+    TypeReference *type = _pool.New<TypeReference>();
+    type->name = name;
+    type->firstUse = object;
+    _refTypes.append(type);
+    return _refTypes.size() - 1;
 }
 
 void QQmlScript::Parser::setTree(QQmlScript::Object *tree)
index 1e46e6b..0a762d4 100644 (file)
@@ -124,16 +124,13 @@ public:
 };
 
 class Object;
-class TypeReference
+class TypeReference : public QQmlPool::Class
 {
 public:
-    TypeReference(int typeId, const QString &typeName) : id(typeId), name(typeName) {}
-
-    int id;
     // type as it has been referenced in Qml
     QString name;
-    // objects in parse tree referencing the type
-    QList<QQmlScript::Object*> refObjects;
+    // The first use of this type in the parse tree.  Useful for error locations.
+    QQmlScript::Object *firstUse;
 };
 
 class Object;
@@ -310,9 +307,10 @@ public:
     // QQmlCompiledData::types array, or -1 if the object is a property
     // group.
     int type;
+    // A back pointer to the QQmlScript::TypeReference for this type, if any.
+    // Set by the parser.
+    TypeReference *typeReference;
 
-    // The fully-qualified name of this type
-    QString typeName;
     // The id assigned to the object (if any).  Set by the QQmlCompiler
     QString id;
     // The id index assigned to the object (if any).  Set by the QQmlCompiler
@@ -503,7 +501,7 @@ public:
 
 
 // ### private:
-    TypeReference *findOrCreateType(const QString &name);
+    int findOrCreateTypeId(const QString &name, Object *);
     void setTree(QQmlScript::Object *tree);
 
     void setScriptFile(const QString &filename) {_scriptFile = filename; }
index 2e8f17e..4b5aa6c 100644 (file)
@@ -1851,10 +1851,8 @@ void QQmlTypeData::resolveTypes()
             //  - known to be a namespace (Namespace {})
             //  - type with unknown namespace (UnknownNamespace.SomeType {})
             QQmlError error;
-            QString userTypeName = parserRef->name;
-            userTypeName.replace(QLatin1Char('/'),QLatin1Char('.'));
             if (typeNamespace) {
-                error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName));
+                error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(parserRef->name));
             } else {
                 if (errors.size()) {
                     error = errors.takeFirst();
@@ -1864,14 +1862,12 @@ void QQmlTypeData::resolveTypes()
                     error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
                 }
                 error.setUrl(m_imports.baseUrl());
-                error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(userTypeName).arg(error.description()));
+                error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(parserRef->name).arg(error.description()));
             }
 
-            if (!parserRef->refObjects.isEmpty()) {
-                QQmlScript::Object *obj = parserRef->refObjects.first();
-                error.setLine(obj->location.start.line);
-                error.setColumn(obj->location.start.column);
-            }
+            Q_ASSERT(parserRef->firstUse);
+            error.setLine(parserRef->firstUse->location.start.line);
+            error.setColumn(parserRef->firstUse->location.start.column);
 
             errors.prepend(error);
             setError(errors);
@@ -1886,8 +1882,8 @@ void QQmlTypeData::resolveTypes()
             addDependency(ref.typeData);
         }
 
-        if (parserRef->refObjects.count())
-            ref.location = parserRef->refObjects.first()->location.start;
+        Q_ASSERT(parserRef->firstUse);
+        ref.location = parserRef->firstUse->location.start;
 
         m_types << ref;
     }
index 6047688..357200d 100644 (file)
@@ -559,7 +559,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
             }
 
             if (!o) 
-                VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.className), instr.line);
+                VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.type->elementName()),
+                              instr.line);
 
             if (instr.isRoot) {
                 if (ddata->context) {
index d0e818f..18b3653 100644 (file)
@@ -86,10 +86,6 @@ void tst_qqmlinstruction::dump()
     }
 
     {
-        QQmlCompiledData::TypeReference ref;
-        ref.className = "Test";
-        data->types << ref;
-
         QQmlCompiledData::Instruction::CreateCppObject i;
         i.type = 0;
         i.data = -1;
@@ -476,7 +472,7 @@ void tst_qqmlinstruction::dump()
         << "Index\tOperation\t\tData1\tData2\tData3\tComments"
         << "-------------------------------------------------------------------------------"
         << "0\t\tINIT\t\t\t0\t3\t-1\t-1"
-        << "1\t\tCREATECPP\t\t\t0\t\t\t\"Test\""
+        << "1\t\tCREATECPP\t\t\t0"
         << "2\t\tSETID\t\t\t0\t\t\t\"testId\""
         << "3\t\tSET_DEFAULT"
         << "4\t\tCREATE_COMPONENT\t3"