qmljs: track origin of ObjectValues

allows unique identification of types

Change-Id: Id4e6a9c1fa23409b1e2d5eb32708a0bacd04a5da
Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@digia.com>
This commit is contained in:
Fawzi Mohamed
2014-07-16 16:21:40 +02:00
parent dae0d5afcd
commit 176096d112
4 changed files with 73 additions and 29 deletions

View File

@@ -170,13 +170,29 @@ public:
} }
}; };
} // namespace Internal } // 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 } // namespace QmlJS
CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className, CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className,
const QString &packageName, const ComponentVersion &componentVersion, const QString &packageName, const ComponentVersion &componentVersion,
const ComponentVersion &importVersion, int metaObjectRevision, const ComponentVersion &importVersion, int metaObjectRevision,
ValueOwner *valueOwner) ValueOwner *valueOwner, const QString &originId)
: ObjectValue(valueOwner), : ObjectValue(valueOwner, originId),
m_metaObject(metaObject), m_metaObject(metaObject),
m_moduleName(packageName), m_moduleName(packageName),
m_componentVersion(componentVersion), m_componentVersion(componentVersion),
@@ -960,8 +976,8 @@ bool MemberProcessor::processGeneratedSlot(const QString &, const Value *)
return true; return true;
} }
ObjectValue::ObjectValue(ValueOwner *valueOwner) ObjectValue::ObjectValue(ValueOwner *valueOwner, const QString &originId)
: m_valueOwner(valueOwner), : m_valueOwner(valueOwner), m_originId(originId),
_prototype(0) _prototype(0)
{ {
valueOwner->registerValue(this); valueOwner->registerValue(this);
@@ -1374,7 +1390,7 @@ const QLatin1String CppQmlTypes::defaultPackage("<default>");
const QLatin1String CppQmlTypes::cppPackage("<cpp>"); const QLatin1String CppQmlTypes::cppPackage("<cpp>");
template <typename T> template <typename T>
void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) void CppQmlTypes::load(const QString &originId, const T &fakeMetaObjects, const QString &overridePackage)
{ {
QList<CppComponentValue *> newCppTypes; QList<CppComponentValue *> newCppTypes;
foreach (const FakeMetaObject::ConstPtr &fmo, fakeMetaObjects) { foreach (const FakeMetaObject::ConstPtr &fmo, fakeMetaObjects) {
@@ -1382,7 +1398,7 @@ void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage)
QString package = exp.package; QString package = exp.package;
if (package.isEmpty()) if (package.isEmpty())
package = overridePackage; package = overridePackage;
m_fakeMetaObjectsByPackage[package].insert(fmo); m_fakeMetaObjectsByPackage[package].insert(FakeMetaObjectWithOrigin(fmo, originId));
// make versionless cpp types directly // make versionless cpp types directly
// needed for access to property types that are not exported, like QDeclarativeAnchors // 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); QTC_ASSERT(exp.type == fmo->className(), continue);
CppComponentValue *cppValue = new CppComponentValue( CppComponentValue *cppValue = new CppComponentValue(
fmo, fmo->className(), cppPackage, ComponentVersion(), ComponentVersion(), fmo, fmo->className(), cppPackage, ComponentVersion(), ComponentVersion(),
ComponentVersion::MaxVersion, m_valueOwner); ComponentVersion::MaxVersion, m_valueOwner, originId);
m_objectsByQualifiedName[qualifiedName(cppPackage, fmo->className(), ComponentVersion())] = cppValue; m_objectsByQualifiedName[qualifiedName(cppPackage, fmo->className(), ComponentVersion())] = cppValue;
newCppTypes += cppValue; newCppTypes += cppValue;
} }
@@ -1407,8 +1423,8 @@ void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage)
} }
} }
// explicitly instantiate load for list and hash // explicitly instantiate load for list and hash
template void CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(const QList<FakeMetaObject::ConstPtr> &, const QString &); template void CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(const QString &, const QList<FakeMetaObject::ConstPtr> &, const QString &);
template void CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &); template void CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(const QString &, const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &);
QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version) QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version)
{ {
@@ -1417,7 +1433,8 @@ QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QStri
QList<const CppComponentValue *> newObjects; QList<const CppComponentValue *> newObjects;
// make new exported objects // 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 // find the highest-version export for each alias
QHash<QString, FakeMetaObject::Export> bestExports; QHash<QString, FakeMetaObject::Export> bestExports;
foreach (const FakeMetaObject::Export &exp, fmo->exports()) { foreach (const FakeMetaObject::Export &exp, fmo->exports()) {
@@ -1449,7 +1466,8 @@ QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QStri
CppComponentValue *newComponent = new CppComponentValue( CppComponentValue *newComponent = new CppComponentValue(
fmo, name, package, bestExport.version, version, fmo, name, package, bestExport.version, version,
bestExport.metaObjectRevision, m_valueOwner); bestExport.metaObjectRevision, m_valueOwner,
fmoo.originId);
// use package.cppname importversion as key // use package.cppname importversion as key
m_objectsByQualifiedName.insert(key, newComponent); m_objectsByQualifiedName.insert(key, newComponent);
@@ -1463,6 +1481,8 @@ QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QStri
} }
// set their prototypes, creating them if necessary // 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) { foreach (const CppComponentValue *cobject, newObjects) {
CppComponentValue *object = const_cast<CppComponentValue *>(cobject); CppComponentValue *object = const_cast<CppComponentValue *>(cobject);
while (!object->prototype()) { while (!object->prototype()) {
@@ -1485,8 +1505,10 @@ QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QStri
// make a new object // make a new object
CppComponentValue *proto = new CppComponentValue( CppComponentValue *proto = new CppComponentValue(
protoFmo, protoCppName, object->moduleName(), ComponentVersion(), protoFmo, protoCppName, object->moduleName(),
object->importVersion(), ComponentVersion::MaxVersion, m_valueOwner); ComponentVersion(),
object->importVersion(), ComponentVersion::MaxVersion, m_valueOwner,
cppProto->originId());
m_objectsByQualifiedName.insert(key, proto); m_objectsByQualifiedName.insert(key, proto);
object->setPrototype(proto); object->setPrototype(proto);
@@ -1786,7 +1808,8 @@ ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
UiObjectInitializer *initializer, UiObjectInitializer *initializer,
const Document *doc, const Document *doc,
ValueOwner *valueOwner) 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) { if (m_initializer) {
for (UiObjectMemberList *it = m_initializer->members; it; it = it->next) { for (UiObjectMemberList *it = m_initializer->members; it; it = it->next) {

View File

@@ -443,7 +443,7 @@ public:
class QMLJS_EXPORT ObjectValue: public Value class QMLJS_EXPORT ObjectValue: public Value
{ {
public: public:
ObjectValue(ValueOwner *valueOwner); ObjectValue(ValueOwner *valueOwner, const QString &originId = QString());
~ObjectValue(); ~ObjectValue();
ValueOwner *valueOwner() const; ValueOwner *valueOwner() const;
@@ -475,6 +475,9 @@ public:
// Value interface // Value interface
const ObjectValue *asObjectValue() const QTC_OVERRIDE; const ObjectValue *asObjectValue() const QTC_OVERRIDE;
void accept(ValueVisitor *visitor) const QTC_OVERRIDE; void accept(ValueVisitor *visitor) const QTC_OVERRIDE;
QString originId() const
{ return m_originId; }
private: private:
bool checkPrototype(const ObjectValue *prototype, QSet<const ObjectValue *> *processed) const; bool checkPrototype(const ObjectValue *prototype, QSet<const ObjectValue *> *processed) const;
@@ -483,6 +486,7 @@ private:
ValueOwner *m_valueOwner; ValueOwner *m_valueOwner;
QHash<QString, const Value *> m_members; QHash<QString, const Value *> m_members;
QString m_className; QString m_className;
QString m_originId;
protected: protected:
const Value *_prototype; const Value *_prototype;
@@ -542,7 +546,7 @@ public:
CppComponentValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className, CppComponentValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className,
const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion, const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion,
const LanguageUtils::ComponentVersion &importVersion, int metaObjectRevision, const LanguageUtils::ComponentVersion &importVersion, int metaObjectRevision,
ValueOwner *valueOwner); ValueOwner *valueOwner, const QString &originId);
~CppComponentValue(); ~CppComponentValue();
const CppComponentValue *asCppComponentValue() const QTC_OVERRIDE; const CppComponentValue *asCppComponentValue() const QTC_OVERRIDE;
@@ -673,6 +677,18 @@ public:
QList<ModuleApiInfo> *newModuleApis, QString *errorMessage, QString *warningMessage, const QString &fileName); QList<ModuleApiInfo> *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 class QMLJS_EXPORT CppQmlTypes
{ {
public: public:
@@ -684,7 +700,7 @@ public:
static const QLatin1String cppPackage; static const QLatin1String cppPackage;
template <typename T> template <typename T>
void load(const T &fakeMetaObjects, const QString &overridePackage = QString()); void load(const QString &originId, const T &fakeMetaObjects, const QString &overridePackage = QString());
QList<const CppComponentValue *> createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version); QList<const CppComponentValue *> createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version);
bool hasModule(const QString &module) const; bool hasModule(const QString &module) const;
@@ -703,7 +719,7 @@ public:
private: private:
// "Package.CppName ImportVersion" -> CppComponentValue // "Package.CppName ImportVersion" -> CppComponentValue
QHash<QString, const CppComponentValue *> m_objectsByQualifiedName; QHash<QString, const CppComponentValue *> m_objectsByQualifiedName;
QHash<QString, QSet<LanguageUtils::FakeMetaObject::ConstPtr> > m_fakeMetaObjectsByPackage; QHash<QString, QSet<FakeMetaObjectWithOrigin> > m_fakeMetaObjectsByPackage;
const ObjectValue *m_cppContextProperties; const ObjectValue *m_cppContextProperties;
ValueOwner *m_valueOwner; ValueOwner *m_valueOwner;
}; };

View File

@@ -147,10 +147,14 @@ Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const Librar
ModelManagerInterface *modelManager = ModelManagerInterface::instance(); ModelManagerInterface *modelManager = ModelManagerInterface::instance();
if (modelManager) { if (modelManager) {
ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData(); ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData();
{
// populate engine with types from C++ // populate engine with types from C++
foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { ModelManagerInterface::CppDataHashIterator cppDataHashIterator(cppDataHash);
d->valueOwner->cppQmlTypes().load(cppData.exportedTypes); while (cppDataHashIterator.hasNext()) {
cppDataHashIterator.next();
d->valueOwner->cppQmlTypes().load(cppDataHashIterator.key(),
cppDataHashIterator.value().exportedTypes);
}
} }
// build an object with the context properties from C++ // build an object with the context properties from C++
@@ -197,13 +201,13 @@ Context::ImportsPerDocument LinkPrivate::linkImports()
// load builtin objects // load builtin objects
if (builtins.pluginTypeInfoStatus() == LibraryInfo::DumpDone if (builtins.pluginTypeInfoStatus() == LibraryInfo::DumpDone
|| builtins.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) { || builtins.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) {
valueOwner->cppQmlTypes().load(builtins.metaObjects()); valueOwner->cppQmlTypes().load(QLatin1String("<builtins>"), builtins.metaObjects());
} else { } else {
valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultQtObjects); valueOwner->cppQmlTypes().load(QLatin1String("<defaults>"), CppQmlTypesLoader::defaultQtObjects);
} }
// load library objects shipped with Creator // load library objects shipped with Creator
valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultLibraryObjects); valueOwner->cppQmlTypes().load(QLatin1String("<defaultQt4>"), CppQmlTypesLoader::defaultLibraryObjects);
if (document) { if (document) {
// do it on document first, to make sure import errors are shown // do it on document first, to make sure import errors are shown
@@ -483,7 +487,7 @@ bool LinkPrivate::importLibrary(Document::Ptr doc,
} }
} else { } else {
const QString packageName = importInfo.name(); 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)) { foreach (const CppComponentValue *object, valueOwner->cppQmlTypes().createObjectsForImport(packageName, version)) {
import->object->setMember(object->className(), object); import->object->setMember(object->className(), object);
} }
@@ -578,7 +582,7 @@ void LinkPrivate::loadImplicitDefaultImports(Imports *imports)
if (!import.object) { if (!import.object) {
import.valid = true; import.valid = true;
import.info = info; import.info = info;
import.object = new ObjectValue(valueOwner); import.object = new ObjectValue(valueOwner, QLatin1String("<defaults>"));
foreach (const CppComponentValue *object, foreach (const CppComponentValue *object,
valueOwner->cppQmlTypes().createObjectsForImport( valueOwner->cppQmlTypes().createObjectsForImport(
defaultPackage, maxVersion)) { defaultPackage, maxVersion)) {

View File

@@ -142,6 +142,7 @@ public:
}; };
typedef QHash<QString, CppData> CppDataHash; typedef QHash<QString, CppData> CppDataHash;
typedef QHashIterator<QString, CppData> CppDataHashIterator;
public: public:
ModelManagerInterface(QObject *parent = 0); ModelManagerInterface(QObject *parent = 0);