diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 7bf7b3ed220..0898bb77acf 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -170,13 +170,29 @@ public: } }; } // namespace Internal + +FakeMetaObjectWithOrigin::FakeMetaObjectWithOrigin(FakeMetaObject::ConstPtr fakeMetaObject, const QString &originId) + : fakeMetaObject(fakeMetaObject) + , originId(originId) +{ } + +bool FakeMetaObjectWithOrigin::operator ==(const FakeMetaObjectWithOrigin &o) const +{ + return fakeMetaObject == o.fakeMetaObject; +} + +uint qHash(const FakeMetaObjectWithOrigin &fmoo, int seed) +{ + return qHash(fmoo.fakeMetaObject, seed); +} + } // namespace QmlJS CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className, - const QString &packageName, const ComponentVersion &componentVersion, - const ComponentVersion &importVersion, int metaObjectRevision, - ValueOwner *valueOwner) - : ObjectValue(valueOwner), + const QString &packageName, const ComponentVersion &componentVersion, + const ComponentVersion &importVersion, int metaObjectRevision, + ValueOwner *valueOwner, const QString &originId) + : ObjectValue(valueOwner, originId), m_metaObject(metaObject), m_moduleName(packageName), m_componentVersion(componentVersion), @@ -960,8 +976,8 @@ bool MemberProcessor::processGeneratedSlot(const QString &, const Value *) return true; } -ObjectValue::ObjectValue(ValueOwner *valueOwner) - : m_valueOwner(valueOwner), +ObjectValue::ObjectValue(ValueOwner *valueOwner, const QString &originId) + : m_valueOwner(valueOwner), m_originId(originId), _prototype(0) { valueOwner->registerValue(this); @@ -1374,7 +1390,7 @@ const QLatin1String CppQmlTypes::defaultPackage(""); const QLatin1String CppQmlTypes::cppPackage(""); template -void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) +void CppQmlTypes::load(const QString &originId, const T &fakeMetaObjects, const QString &overridePackage) { QList newCppTypes; foreach (const FakeMetaObject::ConstPtr &fmo, fakeMetaObjects) { @@ -1382,7 +1398,7 @@ void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) QString package = exp.package; if (package.isEmpty()) package = overridePackage; - m_fakeMetaObjectsByPackage[package].insert(fmo); + m_fakeMetaObjectsByPackage[package].insert(FakeMetaObjectWithOrigin(fmo, originId)); // make versionless cpp types directly // needed for access to property types that are not exported, like QDeclarativeAnchors @@ -1391,7 +1407,7 @@ void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) QTC_ASSERT(exp.type == fmo->className(), continue); CppComponentValue *cppValue = new CppComponentValue( fmo, fmo->className(), cppPackage, ComponentVersion(), ComponentVersion(), - ComponentVersion::MaxVersion, m_valueOwner); + ComponentVersion::MaxVersion, m_valueOwner, originId); m_objectsByQualifiedName[qualifiedName(cppPackage, fmo->className(), ComponentVersion())] = cppValue; newCppTypes += cppValue; } @@ -1407,8 +1423,8 @@ void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) } } // explicitly instantiate load for list and hash -template void CppQmlTypes::load< QList >(const QList &, const QString &); -template void CppQmlTypes::load< QHash >(const QHash &, const QString &); +template void CppQmlTypes::load< QList >(const QString &, const QList &, const QString &); +template void CppQmlTypes::load< QHash >(const QString &, const QHash &, const QString &); QList CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version) { @@ -1417,7 +1433,8 @@ QList CppQmlTypes::createObjectsForImport(const QStri QList newObjects; // make new exported objects - foreach (const FakeMetaObject::ConstPtr &fmo, m_fakeMetaObjectsByPackage.value(package)) { + foreach (const FakeMetaObjectWithOrigin &fmoo, m_fakeMetaObjectsByPackage.value(package)) { + const FakeMetaObject::ConstPtr &fmo = fmoo.fakeMetaObject; // find the highest-version export for each alias QHash bestExports; foreach (const FakeMetaObject::Export &exp, fmo->exports()) { @@ -1449,7 +1466,8 @@ QList CppQmlTypes::createObjectsForImport(const QStri CppComponentValue *newComponent = new CppComponentValue( fmo, name, package, bestExport.version, version, - bestExport.metaObjectRevision, m_valueOwner); + bestExport.metaObjectRevision, m_valueOwner, + fmoo.originId); // use package.cppname importversion as key m_objectsByQualifiedName.insert(key, newComponent); @@ -1463,6 +1481,8 @@ QList CppQmlTypes::createObjectsForImport(const QStri } // set their prototypes, creating them if necessary + // this ensures that the prototypes of C++ objects are resolved correctly and with the correct + // revision, and cannot be hidden by other objects. foreach (const CppComponentValue *cobject, newObjects) { CppComponentValue *object = const_cast(cobject); while (!object->prototype()) { @@ -1485,8 +1505,10 @@ QList CppQmlTypes::createObjectsForImport(const QStri // make a new object CppComponentValue *proto = new CppComponentValue( - protoFmo, protoCppName, object->moduleName(), ComponentVersion(), - object->importVersion(), ComponentVersion::MaxVersion, m_valueOwner); + protoFmo, protoCppName, object->moduleName(), + ComponentVersion(), + object->importVersion(), ComponentVersion::MaxVersion, m_valueOwner, + cppProto->originId()); m_objectsByQualifiedName.insert(key, proto); object->setPrototype(proto); @@ -1786,7 +1808,8 @@ ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName, UiObjectInitializer *initializer, const Document *doc, ValueOwner *valueOwner) - : ObjectValue(valueOwner), m_typeName(typeName), m_initializer(initializer), m_doc(doc), m_defaultPropertyRef(0) + : ObjectValue(valueOwner, doc->importId()), + m_typeName(typeName), m_initializer(initializer), m_doc(doc), m_defaultPropertyRef(0) { if (m_initializer) { for (UiObjectMemberList *it = m_initializer->members; it; it = it->next) { diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 6bb48b8a6f5..64e89fee151 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -443,7 +443,7 @@ public: class QMLJS_EXPORT ObjectValue: public Value { public: - ObjectValue(ValueOwner *valueOwner); + ObjectValue(ValueOwner *valueOwner, const QString &originId = QString()); ~ObjectValue(); ValueOwner *valueOwner() const; @@ -475,6 +475,9 @@ public: // Value interface const ObjectValue *asObjectValue() const QTC_OVERRIDE; void accept(ValueVisitor *visitor) const QTC_OVERRIDE; + QString originId() const + { return m_originId; } + private: bool checkPrototype(const ObjectValue *prototype, QSet *processed) const; @@ -483,6 +486,7 @@ private: ValueOwner *m_valueOwner; QHash m_members; QString m_className; + QString m_originId; protected: const Value *_prototype; @@ -542,7 +546,7 @@ public: CppComponentValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className, const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion, const LanguageUtils::ComponentVersion &importVersion, int metaObjectRevision, - ValueOwner *valueOwner); + ValueOwner *valueOwner, const QString &originId); ~CppComponentValue(); const CppComponentValue *asCppComponentValue() const QTC_OVERRIDE; @@ -673,6 +677,18 @@ public: QList *newModuleApis, QString *errorMessage, QString *warningMessage, const QString &fileName); }; +class QMLJS_EXPORT FakeMetaObjectWithOrigin +{ +public: + LanguageUtils::FakeMetaObject::ConstPtr fakeMetaObject; + QString originId; + FakeMetaObjectWithOrigin(LanguageUtils::FakeMetaObject::ConstPtr fakeMetaObject, + const QString &originId); + bool operator ==(const FakeMetaObjectWithOrigin &o) const; +}; + +QMLJS_EXPORT uint qHash(const FakeMetaObjectWithOrigin &fmoo, int seed = 0); + class QMLJS_EXPORT CppQmlTypes { public: @@ -684,7 +700,7 @@ public: static const QLatin1String cppPackage; template - void load(const T &fakeMetaObjects, const QString &overridePackage = QString()); + void load(const QString &originId, const T &fakeMetaObjects, const QString &overridePackage = QString()); QList createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version); bool hasModule(const QString &module) const; @@ -703,7 +719,7 @@ public: private: // "Package.CppName ImportVersion" -> CppComponentValue QHash m_objectsByQualifiedName; - QHash > m_fakeMetaObjectsByPackage; + QHash > m_fakeMetaObjectsByPackage; const ObjectValue *m_cppContextProperties; ValueOwner *m_valueOwner; }; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 969bc8c939d..e0006e4b837 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -147,10 +147,14 @@ Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const Librar ModelManagerInterface *modelManager = ModelManagerInterface::instance(); if (modelManager) { ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData(); - - // populate engine with types from C++ - foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { - d->valueOwner->cppQmlTypes().load(cppData.exportedTypes); + { + // populate engine with types from C++ + ModelManagerInterface::CppDataHashIterator cppDataHashIterator(cppDataHash); + while (cppDataHashIterator.hasNext()) { + cppDataHashIterator.next(); + d->valueOwner->cppQmlTypes().load(cppDataHashIterator.key(), + cppDataHashIterator.value().exportedTypes); + } } // build an object with the context properties from C++ @@ -197,13 +201,13 @@ Context::ImportsPerDocument LinkPrivate::linkImports() // load builtin objects if (builtins.pluginTypeInfoStatus() == LibraryInfo::DumpDone || builtins.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) { - valueOwner->cppQmlTypes().load(builtins.metaObjects()); + valueOwner->cppQmlTypes().load(QLatin1String(""), builtins.metaObjects()); } else { - valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultQtObjects); + valueOwner->cppQmlTypes().load(QLatin1String(""), CppQmlTypesLoader::defaultQtObjects); } // load library objects shipped with Creator - valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultLibraryObjects); + valueOwner->cppQmlTypes().load(QLatin1String(""), CppQmlTypesLoader::defaultLibraryObjects); if (document) { // do it on document first, to make sure import errors are shown @@ -483,7 +487,7 @@ bool LinkPrivate::importLibrary(Document::Ptr doc, } } else { const QString packageName = importInfo.name(); - valueOwner->cppQmlTypes().load(libraryInfo.metaObjects(), packageName); + valueOwner->cppQmlTypes().load(libraryPath, libraryInfo.metaObjects(), packageName); foreach (const CppComponentValue *object, valueOwner->cppQmlTypes().createObjectsForImport(packageName, version)) { import->object->setMember(object->className(), object); } @@ -578,7 +582,7 @@ void LinkPrivate::loadImplicitDefaultImports(Imports *imports) if (!import.object) { import.valid = true; import.info = info; - import.object = new ObjectValue(valueOwner); + import.object = new ObjectValue(valueOwner, QLatin1String("")); foreach (const CppComponentValue *object, valueOwner->cppQmlTypes().createObjectsForImport( defaultPackage, maxVersion)) { diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 089b70e68e6..ad2a14b81b4 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -142,6 +142,7 @@ public: }; typedef QHash CppDataHash; + typedef QHashIterator CppDataHashIterator; public: ModelManagerInterface(QObject *parent = 0);