From 4fc2032e10d156dd64a3a7e9a864f57d6e10ad69 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Tue, 8 Feb 2011 16:18:34 +0100
Subject: [PATCH] QmlJS: Put types with cpp names into a separate package.

In preparation of relocatable plugin types.
---
 src/libs/qmljs/qmljsinterpreter.cpp           | 87 +++++++++----------
 src/libs/qmljs/qmljsinterpreter.h             | 15 +++-
 src/libs/qmljs/qmljslink.cpp                  |  2 +-
 src/libs/qmljs/qmljstypedescriptionreader.cpp |  2 -
 4 files changed, 54 insertions(+), 52 deletions(-)

diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index ae7d8bad8e4..f74ca3eb95d 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -658,11 +658,11 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
     const QString typeName = prop.typeName();
 
     // ### Verify type resolving.
-    QmlObjectValue *objectValue = engine()->cppQmlTypes().typeForImport(typeName);
+    QmlObjectValue *objectValue = engine()->cppQmlTypes().typeByCppName(typeName);
     if (objectValue) {
-        QString packageClassName = objectValue->nameInPackage(packageName());
-        if (!packageClassName.isEmpty())
-            objectValue = engine()->cppQmlTypes().typeForImport(packageName() + '.' + packageClassName);
+        QString fqn = objectValue->fullyQualifiedNameInPackage(packageName());
+        if (!fqn.isEmpty())
+            objectValue = engine()->cppQmlTypes().typeByQualifiedName(fqn);
         return objectValue;
     }
 
@@ -724,6 +724,14 @@ QString QmlObjectValue::nameInPackage(const QString &packageName) const
     return QString();
 }
 
+QString QmlObjectValue::fullyQualifiedNameInPackage(const QString &packageName) const
+{
+    foreach (const FakeMetaObject::Export &exp, _metaObject->exports())
+        if (exp.package == packageName)
+            return exp.packageNameVersion;
+    return QString();
+}
+
 ComponentVersion QmlObjectValue::version() const
 { return _componentVersion; }
 
@@ -2015,24 +2023,23 @@ void CppQmlTypesLoader::setSuperClasses(QHash<QString, FakeMetaObject::Ptr> *new
     }
 }
 
+const QLatin1String CppQmlTypes::defaultPackage("<default>");
+const QLatin1String CppQmlTypes::cppPackage("<cpp>");
+
 template <typename T>
 void CppQmlTypes::load(Engine *engine, const T &objects)
 {
     // load
     QList<FakeMetaObject::ConstPtr> newObjects;
     foreach (FakeMetaObject::ConstPtr metaObject, objects) {
-        for (int i = 0; i < metaObject->exports().size(); ++i) {
-            const FakeMetaObject::Export &exp = metaObject->exports().at(i);
-            // make sure we're not loading duplicate objects
-            if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
-                continue;
+        foreach (const FakeMetaObject::Export &exp, metaObject->exports())
+            makeObject(engine, metaObject, exp, &newObjects);
 
-            newObjects.append(metaObject);
-            QmlObjectValue *objectValue = new QmlObjectValue(
-                        metaObject, exp.type, exp.package, exp.version, engine);
-            _typesByPackage[exp.package].append(objectValue);
-            _typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
-        }
+        FakeMetaObject::Export cppExport;
+        cppExport.package = cppPackage;
+        cppExport.type = metaObject->className();
+        cppExport.packageNameVersion = qualifiedName(cppPackage, cppExport.type, cppExport.version);
+        makeObject(engine, metaObject, cppExport, &newObjects);
     }
 
     // set prototypes
@@ -2087,37 +2094,9 @@ QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName,
     return objectValuesByName.values();
 }
 
-QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName,
-                                           ComponentVersion version) const
+QmlObjectValue *CppQmlTypes::typeByCppName(const QString &cppName) const
 {
-    QString name = qualifiedName;
-    QString packageName;
-    int dotIdx = name.indexOf(QLatin1Char('.'));
-    if (dotIdx != -1) {
-        packageName = name.left(dotIdx);
-        name = name.mid(dotIdx + 1);
-    }
-
-    QmlObjectValue *previousCandidate = 0;
-    foreach (QmlObjectValue *qmlObjectValue, _typesByPackage.value(packageName)) {
-        const QString typeName = qmlObjectValue->className();
-        if (typeName != name)
-            continue;
-        if (version.isValid() && version < qmlObjectValue->version())
-            continue;
-
-        if (previousCandidate) {
-            // check if our new candidate is newer than the one we found previously
-            if (previousCandidate->version() < qmlObjectValue->version()) {
-                // the new candidate has a higher version no. than the one we found previously, so replace it
-                previousCandidate = qmlObjectValue;
-            }
-        } else {
-            previousCandidate = qmlObjectValue;
-        }
-    }
-
-    return previousCandidate;
+    return typeByQualifiedName(cppPackage, cppName, ComponentVersion());
 }
 
 bool CppQmlTypes::hasPackage(const QString &package) const
@@ -2143,6 +2122,22 @@ QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const Q
     return typeByQualifiedName(qualifiedName(package, type, version));
 }
 
+void CppQmlTypes::makeObject(Engine *engine,
+                             FakeMetaObject::ConstPtr metaObject,
+                             const LanguageUtils::FakeMetaObject::Export &exp,
+                             QList<LanguageUtils::FakeMetaObject::ConstPtr> *newObjects)
+{
+    // make sure we're not loading duplicate objects
+    if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
+        return;
+
+    newObjects->append(metaObject);
+    QmlObjectValue *objectValue = new QmlObjectValue(
+                metaObject, exp.type, exp.package, exp.version, engine);
+    _typesByPackage[exp.package].append(objectValue);
+    _typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
+}
+
 QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName,
                                          FakeMetaObject::ConstPtr metaObject, Engine *engine, bool *created)
 {
@@ -2453,7 +2448,7 @@ Engine::Engine()
     // the 'Qt' object is dumped even though it is not exported
     // it contains useful information, in particular on enums - add the
     // object as a prototype to our custom Qt object to offer these for completion
-    _qtObject->setPrototype(_cppQmlTypes.typeForImport(QLatin1String("Qt")));
+    _qtObject->setPrototype(_cppQmlTypes.typeByCppName(QLatin1String("Qt")));
 }
 
 Engine::~Engine()
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index a97a19d5b04..ca1aa026ddd 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -456,6 +456,7 @@ public:
 
     QString packageName() const;
     QString nameInPackage(const QString &packageName) const;
+    QString fullyQualifiedNameInPackage(const QString &packageName) const;
     LanguageUtils::ComponentVersion version() const;
     QString defaultPropertyName() const;
     QString propertyType(const QString &propertyName) const;
@@ -598,12 +599,16 @@ private:
 class QMLJS_EXPORT CppQmlTypes
 {
 public:
+    // package name for objects that should be always available
+    static const QLatin1String defaultPackage;
+    // package name for objects with their raw cpp name
+    static const QLatin1String cppPackage;
+
     template <typename T>
     void load(Interpreter::Engine *interpreter, const T &objects);
 
     QList<Interpreter::QmlObjectValue *> typesForImport(const QString &prefix, LanguageUtils::ComponentVersion version) const;
-    Interpreter::QmlObjectValue *typeForImport(const QString &qualifiedName,
-                                               LanguageUtils::ComponentVersion version = LanguageUtils::ComponentVersion()) const;
+    Interpreter::QmlObjectValue *typeByCppName(const QString &cppName) const;
 
     bool hasPackage(const QString &package) const;
 
@@ -611,11 +616,15 @@ public:
     { return _typesByFullyQualifiedName; }
 
     static QString qualifiedName(const QString &package, const QString &type, LanguageUtils::ComponentVersion version);
-    QmlObjectValue *typeByQualifiedName(const QString &name) const;
+    QmlObjectValue *typeByQualifiedName(const QString &fullyQualifiedName) const;
     QmlObjectValue *typeByQualifiedName(const QString &package, const QString &type,
                                         LanguageUtils::ComponentVersion version) const;
 
 private:
+    void makeObject(Engine *engine,
+                    LanguageUtils::FakeMetaObject::ConstPtr metaObject,
+                    const LanguageUtils::FakeMetaObject::Export &exp,
+                    QList<LanguageUtils::FakeMetaObject::ConstPtr> *newObjects);
     QmlObjectValue *getOrCreate(const QString &package, const QString &cppName,
                                 LanguageUtils::FakeMetaObject::ConstPtr metaObject,
                                 Engine *engine, bool *created);
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index c5a2ca34522..2e6c91530ac 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -174,7 +174,7 @@ void Link::populateImportedTypes(TypeEnvironment *typeEnv, Document::Ptr doc)
         return;
 
     // implicit imports: the <default> package is always available
-    const QLatin1String defaultPackage("<default>");
+    const QString defaultPackage = CppQmlTypes::defaultPackage;
     if (engine()->cppQmlTypes().hasPackage(defaultPackage)) {
         ImportInfo info(ImportInfo::LibraryImport, defaultPackage);
         ObjectValue *import = d->importCache.value(ImportCacheKey(info));
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp
index a71cd28ccd7..35bce0a826b 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.cpp
+++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp
@@ -172,8 +172,6 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
         return;
     }
 
-    // ### for backwards compatibility until fixed: export by cpp name
-    fmo->addExport(fmo->className(), "", ComponentVersion());
     _objects->insert(fmo->className(), fmo);
 }
 
-- 
GitLab