diff --git a/src/libs/languageutils/fakemetaobject.cpp b/src/libs/languageutils/fakemetaobject.cpp index 7fd6dd2d4ce58dabfc5a96fe72e24fc7abc0c5c0..e599a68774eb0e2fa96cddc3b4f42f2694add19b 100644 --- a/src/libs/languageutils/fakemetaobject.cpp +++ b/src/libs/languageutils/fakemetaobject.cpp @@ -121,7 +121,6 @@ bool FakeMetaProperty::isPointer() const FakeMetaObject::FakeMetaObject() - : m_super(0) { } @@ -143,17 +142,20 @@ void FakeMetaObject::addExport(const QString &name, const QString &package, Comp } QList<FakeMetaObject::Export> FakeMetaObject::exports() const { return m_exports; } +FakeMetaObject::Export FakeMetaObject::exportInPackage(const QString &package) const +{ + foreach (const Export &exp, m_exports) { + if (exp.package == package) + return exp; + } + return Export(); +} void FakeMetaObject::setSuperclassName(const QString &superclass) { m_superName = superclass; } QString FakeMetaObject::superclassName() const { return m_superName; } -void FakeMetaObject::setSuperclass(ConstPtr superClass) -{ m_super = superClass; } -FakeMetaObject::ConstPtr FakeMetaObject::superClass() const -{ return m_super; } - void FakeMetaObject::addEnum(const FakeMetaEnum &fakeEnum) { m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); } int FakeMetaObject::enumeratorCount() const diff --git a/src/libs/languageutils/fakemetaobject.h b/src/libs/languageutils/fakemetaobject.h index f7c324683e2a434ce59d4da854ff4d748a6b085e..6159900520c711825653e752457158a380b002e0 100644 --- a/src/libs/languageutils/fakemetaobject.h +++ b/src/libs/languageutils/fakemetaobject.h @@ -135,12 +135,13 @@ public: QString type; ComponentVersion version; QString packageNameVersion; + + bool isValid() const; }; private: QString m_className; QList<Export> m_exports; - ConstPtr m_super; QString m_superName; QList<FakeMetaEnum> m_enums; QHash<QString, int> m_enumNameToIndex; @@ -158,11 +159,10 @@ public: void addExport(const QString &name, const QString &package, ComponentVersion version); QList<Export> exports() const; + Export exportInPackage(const QString &package) const; void setSuperclassName(const QString &superclass); QString superclassName() const; - void setSuperclass(ConstPtr superClass); - ConstPtr superClass() const; void addEnum(const FakeMetaEnum &fakeEnum); int enumeratorCount() const; diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index e999ce1750c03192237fbac26a857923a438f2a8..8eee26d03d66801687b1a11c358511c9cc29b5b2 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -660,9 +660,9 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const // ### Verify type resolving. QmlObjectValue *objectValue = engine()->cppQmlTypes().typeByCppName(typeName); if (objectValue) { - QString fqn = objectValue->fullyQualifiedNameInPackage(packageName()); - if (!fqn.isEmpty()) - objectValue = engine()->cppQmlTypes().typeByQualifiedName(fqn); + FakeMetaObject::Export exp = objectValue->metaObject()->exportInPackage(packageName()); + if (exp.isValid()) + objectValue = engine()->cppQmlTypes().typeByQualifiedName(exp.packageNameVersion); return objectValue; } @@ -713,25 +713,20 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const return value; } -QString QmlObjectValue::packageName() const -{ return _packageName; } - -QString QmlObjectValue::nameInPackage(const QString &packageName) const +const QmlObjectValue *QmlObjectValue::prototype() const { - foreach (const FakeMetaObject::Export &exp, _metaObject->exports()) - if (exp.package == packageName) - return exp.type; - return QString(); + Q_ASSERT(!_prototype || dynamic_cast<const QmlObjectValue *>(_prototype)); + return static_cast<const QmlObjectValue *>(_prototype); } -QString QmlObjectValue::fullyQualifiedNameInPackage(const QString &packageName) const +FakeMetaObject::ConstPtr QmlObjectValue::metaObject() const { - foreach (const FakeMetaObject::Export &exp, _metaObject->exports()) - if (exp.package == packageName) - return exp.packageNameVersion; - return QString(); + return _metaObject; } +QString QmlObjectValue::packageName() const +{ return _packageName; } + ComponentVersion QmlObjectValue::version() const { return _componentVersion; } @@ -740,7 +735,8 @@ QString QmlObjectValue::defaultPropertyName() const QString QmlObjectValue::propertyType(const QString &propertyName) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { return iter->property(propIdx).typeName(); @@ -751,7 +747,8 @@ QString QmlObjectValue::propertyType(const QString &propertyName) const bool QmlObjectValue::isListProperty(const QString &propertyName) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { return iter->property(propIdx).isList(); @@ -767,7 +764,8 @@ bool QmlObjectValue::isEnum(const QString &typeName) const bool QmlObjectValue::isWritable(const QString &propertyName) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { return iter->property(propIdx).isWritable(); @@ -778,7 +776,8 @@ bool QmlObjectValue::isWritable(const QString &propertyName) const bool QmlObjectValue::isPointer(const QString &propertyName) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { return iter->property(propIdx).isPointer(); @@ -797,7 +796,8 @@ bool QmlObjectValue::hasLocalProperty(const QString &typeName) const bool QmlObjectValue::hasProperty(const QString &propertyName) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { return true; @@ -841,7 +841,8 @@ bool QmlObjectValue::hasChildInPackage() const // if it has only the default no-package export, it is not really exported if (other->exports().size() <= 1) continue; - for (FakeMetaObject::ConstPtr iter = other; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; if (iter == _metaObject) // this object is a parent of other return true; } @@ -851,7 +852,8 @@ bool QmlObjectValue::hasChildInPackage() const bool QmlObjectValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const { - for (FakeMetaObject::ConstPtr iter = _metaObject; iter; iter = iter->superClass()) { + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + FakeMetaObject::ConstPtr iter = it->_metaObject; if (iter == base) return true; } @@ -1956,7 +1958,7 @@ QHash<QString, FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects; QStringList CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles) { - QHash<QString, FakeMetaObject::Ptr> newObjects; + QHash<QString, FakeMetaObject::ConstPtr> newObjects; QStringList errorMsgs; foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) { @@ -1977,21 +1979,13 @@ QStringList CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles) } if (errorMsgs.isEmpty()) { - setSuperClasses(&newObjects); - - // we need to go from QHash<K, T::Ptr> to QHash<K, T::ConstPtr> - // and there seems to be no better way - QHashIterator<QString, FakeMetaObject::Ptr> it(newObjects); - while (it.hasNext()) { - it.next(); - builtinObjects.insert(it.key(), it.value()); - } + builtinObjects.unite(newObjects); } return errorMsgs; } -QString CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, QHash<QString, FakeMetaObject::Ptr> *newObjects) +QString CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, QHash<QString, FakeMetaObject::ConstPtr> *newObjects) { QmlJS::TypeDescriptionReader reader(QString::fromUtf8(xml)); if (!reader(newObjects)) { @@ -1999,30 +1993,9 @@ QString CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, QHash return QLatin1String("unknown error"); return reader.errorMessage(); } - setSuperClasses(newObjects); return QString(); } -void CppQmlTypesLoader::setSuperClasses(QHash<QString, FakeMetaObject::Ptr> *newObjects) -{ - QHashIterator<QString, FakeMetaObject::Ptr> it(*newObjects); - while (it.hasNext()) { - it.next(); - FakeMetaObject::Ptr obj = it.value(); - - const QString superName = obj->superclassName(); - if (! superName.isEmpty()) { - FakeMetaObject::ConstPtr superClass = newObjects->value(superName); - if (!superClass) - superClass = builtinObjects.value(superName); - if (superClass) - obj->setSuperclass(superClass); - else - qWarning() << "QmlJS::Interpreter::MetaTypeSystem: Can't find superclass" << superName << "for" << it.key(); - } - } -} - const QLatin1String CppQmlTypes::defaultPackage("<default>"); const QLatin1String CppQmlTypes::cppPackage("<cpp>"); @@ -2030,16 +2003,18 @@ template <typename T> void CppQmlTypes::load(Engine *engine, const T &objects) { // load - QList<FakeMetaObject::ConstPtr> newObjects; + QList<QmlObjectValue *> newObjects; foreach (FakeMetaObject::ConstPtr metaObject, objects) { - foreach (const FakeMetaObject::Export &exp, metaObject->exports()) - makeObject(engine, metaObject, exp, &newObjects); + foreach (const FakeMetaObject::Export &exp, metaObject->exports()) { + QmlObjectValue *newObject = makeObject(engine, metaObject, exp); + if (newObject) + newObjects += newObject; + } } // set prototypes - foreach (FakeMetaObject::ConstPtr metaObject, newObjects) { - foreach (const FakeMetaObject::Export &exp, metaObject->exports()) - setPrototypes(engine, metaObject, exp); + foreach (QmlObjectValue *object, newObjects) { + setPrototypes(object); } } // explicitly instantiate load for list and hash @@ -2098,71 +2073,72 @@ 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) +QmlObjectValue *CppQmlTypes::makeObject( + Engine *engine, + FakeMetaObject::ConstPtr metaObject, + const LanguageUtils::FakeMetaObject::Export &exp) { // make sure we're not loading duplicate objects if (_typesByFullyQualifiedName.contains(exp.packageNameVersion)) - return; + return 0; - newObjects->append(metaObject); QmlObjectValue *objectValue = new QmlObjectValue( metaObject, exp.type, exp.package, exp.version, engine); _typesByPackage[exp.package].append(objectValue); _typesByFullyQualifiedName[exp.packageNameVersion] = objectValue; + return objectValue; } -void CppQmlTypes::setPrototypes(Engine *engine, - FakeMetaObject::ConstPtr metaObject, - const LanguageUtils::FakeMetaObject::Export &exp) +void CppQmlTypes::setPrototypes(QmlObjectValue *object) { - QmlObjectValue *objectValue = _typesByFullyQualifiedName.value(exp.packageNameVersion); - if (!objectValue || !metaObject->superClass()) + if (!object || object->metaObject()->superclassName().isEmpty()) return; + const QString targetPackage = object->packageName(); + // set prototypes for whole chain, creating new QmlObjectValues if necessary // for instance, if an type isn't exported in the package of the super type // Example: QObject (Qt, QtQuick) -> Positioner (not exported) -> Column (Qt, QtQuick) // needs to create Positioner (Qt) and Positioner (QtQuick) - bool created = true; - QmlObjectValue *v = objectValue; - FakeMetaObject::ConstPtr fmo = metaObject; - while (created && fmo->superClass()) { - QmlObjectValue *superValue = getOrCreate(exp.package, fmo->superclassName(), - fmo->superClass(), engine, &created); + QmlObjectValue *v = object; + FakeMetaObject::ConstPtr fmo = v->metaObject(); + while (!v->prototype() && !fmo->superclassName().isEmpty()) { + QmlObjectValue *superValue = getOrCreate(targetPackage, fmo->superclassName()); + if (!superValue) + return; v->setPrototype(superValue); v = superValue; - fmo = fmo->superClass(); + fmo = v->metaObject(); } } -QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName, - FakeMetaObject::ConstPtr metaObject, Engine *engine, bool *created) +QmlObjectValue *CppQmlTypes::getOrCreate(const QString &package, const QString &cppName) { - QString typeName = cppName; - ComponentVersion version; - foreach (const FakeMetaObject::Export &exp, metaObject->exports()) { - if (exp.package == package) { - typeName = exp.type; - version = exp.version; - break; - } + // first get the cpp object value + QmlObjectValue *cppObject = typeByCppName(cppName); + if (!cppObject) { + qWarning() << "QML type system: could not find '" << cppName << "'"; + return 0; } - const QString qName = qualifiedName(package, typeName, version); - QmlObjectValue *value = typeByQualifiedName(qName); - if (!value) { - *created = true; - value = new QmlObjectValue( - metaObject, typeName, package, ComponentVersion(), engine); - _typesByFullyQualifiedName[qName] = value; + FakeMetaObject::ConstPtr metaObject = cppObject->metaObject(); + FakeMetaObject::Export exp = metaObject->exportInPackage(package); + QmlObjectValue *object = 0; + if (exp.isValid()) { + object = typeByQualifiedName(exp.packageNameVersion); + if (!object) + object = makeObject(cppObject->engine(), metaObject, exp); } else { - *created = false; + const QString qname = qualifiedName(package, cppName, ComponentVersion()); + object = typeByQualifiedName(qname); + if (!object) { + object = new QmlObjectValue( + metaObject, cppName, package, ComponentVersion(), cppObject->engine()); + _typesByFullyQualifiedName[qname] = object; + } } - return value; + return object; } ConvertToNumber::ConvertToNumber(Engine *engine) diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 3732b576998d34b2b5b378f9107a743a598ae68b..7c7a52a34464b72b1a365a95bbb93cd827147393 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -420,9 +420,11 @@ private: private: Engine *_engine; - const Value *_prototype; QHash<QString, const Value *> _members; QString _className; + +protected: + const Value *_prototype; }; class QMLJS_EXPORT PrototypeIterator @@ -443,6 +445,8 @@ private: const Context *m_context; }; +// A ObjectValue based on a FakeMetaObject. +// May only have other QmlObjectValues as ancestors. class QMLJS_EXPORT QmlObjectValue: public ObjectValue { public: @@ -454,10 +458,14 @@ public: virtual void processMembers(MemberProcessor *processor) const; const Value *propertyValue(const LanguageUtils::FakeMetaProperty &prop) const; + using ObjectValue::prototype; + const QmlObjectValue *prototype() const; + + LanguageUtils::FakeMetaObject::ConstPtr metaObject() const; + 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; bool isListProperty(const QString &name) const; @@ -591,9 +599,7 @@ public: // parses the xml string and fills the newObjects map static QString parseQmlTypeDescriptions(const QByteArray &xml, - QHash<QString, LanguageUtils::FakeMetaObject::Ptr> *newObjects); -private: - static void setSuperClasses(QHash<QString, LanguageUtils::FakeMetaObject::Ptr> *newObjects); + QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *newObjects); }; class QMLJS_EXPORT CppQmlTypes @@ -621,16 +627,11 @@ public: LanguageUtils::ComponentVersion version) const; private: - void makeObject(Engine *engine, - LanguageUtils::FakeMetaObject::ConstPtr metaObject, - const LanguageUtils::FakeMetaObject::Export &exp, - QList<LanguageUtils::FakeMetaObject::ConstPtr> *newObjects); - void setPrototypes(Engine *engine, - LanguageUtils::FakeMetaObject::ConstPtr metaObject, - const LanguageUtils::FakeMetaObject::Export &exp); - QmlObjectValue *getOrCreate(const QString &package, const QString &cppName, - LanguageUtils::FakeMetaObject::ConstPtr metaObject, - Engine *engine, bool *created); + QmlObjectValue *makeObject(Engine *engine, + LanguageUtils::FakeMetaObject::ConstPtr metaObject, + const LanguageUtils::FakeMetaObject::Export &exp); + void setPrototypes(QmlObjectValue *object); + QmlObjectValue *getOrCreate(const QString &package, const QString &cppName); QHash<QString, QList<QmlObjectValue *> > _typesByPackage; diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp index 40c10116791a3994d9e6f965322ff0f6ff98f945..9e8f6884cd4a6cc5f943805286de4bd85f8c0508 100644 --- a/src/libs/qmljs/qmljstypedescriptionreader.cpp +++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp @@ -27,7 +27,7 @@ TypeDescriptionReader::~TypeDescriptionReader() { } -bool TypeDescriptionReader::operator()(QHash<QString, FakeMetaObject::Ptr> *objects) +bool TypeDescriptionReader::operator()(QHash<QString, FakeMetaObject::ConstPtr> *objects) { QString fileName("typeDescription"); Engine engine; diff --git a/src/libs/qmljs/qmljstypedescriptionreader.h b/src/libs/qmljs/qmljstypedescriptionreader.h index 21e9c3c4d5211e73da78366446e113d248ee5d5d..34dfd919d16056878861f60dd47744c981103762 100644 --- a/src/libs/qmljs/qmljstypedescriptionreader.h +++ b/src/libs/qmljs/qmljstypedescriptionreader.h @@ -30,7 +30,7 @@ public: explicit TypeDescriptionReader(const QString &data); ~TypeDescriptionReader(); - bool operator()(QHash<QString, LanguageUtils::FakeMetaObject::Ptr> *objects); + bool operator()(QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects); QString errorMessage() const; private: @@ -50,7 +50,7 @@ private: QString _source; QString _errorMessage; - QHash<QString, LanguageUtils::FakeMetaObject::Ptr> *_objects; + QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects; }; } // namespace QmlJS diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 48a4733569169419a712ac631042f3769115e2ac..fc6c55896f1d8081a1bbccc8601ca6672501405d 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -1551,7 +1551,6 @@ static void populate(LanguageUtils::FakeMetaObject::Ptr fmo, Class *klass, baseFmo = FakeMetaObject::Ptr(new FakeMetaObject); populate(baseFmo, baseClass, classes, typeOf); } - fmo->setSuperclass(baseFmo); } } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 11bd11b68ee99aa957f1a7356a70600c59a80aa7..baebcabe2b7fd8261aace39420c042b885f2b985 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -52,6 +52,7 @@ #include <qmljs/qmljsinterpreter.h> #include <qmljs/qmljsbind.h> #include <qmljs/parser/qmljsast_p.h> +#include <languageutils/fakemetaobject.h> #include <private/qdeclarativemetatype_p.h> #include <private/qdeclarativestringconverters_p.h> @@ -658,7 +659,9 @@ bool NodeMetaInfoPrivate::cleverCheckType(const QString &otherType) const if (packageName() == package) return QString(package + "/" + typeName) == qualfiedTypeName(); - const QString convertedName = getQmlObjectValue()->nameInPackage(package); + const LanguageUtils::FakeMetaObject::Export exp = + getQmlObjectValue()->metaObject()->exportInPackage(package); + const QString convertedName = exp.type; return QString(package + "/" + typeName) == QString(package + "/" + convertedName); } diff --git a/src/plugins/qmljstools/qmljsplugindumper.cpp b/src/plugins/qmljstools/qmljsplugindumper.cpp index 7ab0d9bcb23c9fd72f3a93d6e89f0224172f328d..68d70a808691f6ab15e0fbe41986346ead85190a 100644 --- a/src/plugins/qmljstools/qmljsplugindumper.cpp +++ b/src/plugins/qmljstools/qmljsplugindumper.cpp @@ -139,16 +139,11 @@ static QString qmldumpFailedMessage(const QString &error) static QList<FakeMetaObject::ConstPtr> parseHelper(const QByteArray &qmlTypeDescriptions, QString *error) { QList<FakeMetaObject::ConstPtr> ret; - QHash<QString, FakeMetaObject::Ptr> newObjects; + QHash<QString, FakeMetaObject::ConstPtr> newObjects; *error = Interpreter::CppQmlTypesLoader::parseQmlTypeDescriptions(qmlTypeDescriptions, &newObjects); if (error->isEmpty()) { - // convert from QList<T *> to QList<const T *> - QHashIterator<QString, FakeMetaObject::Ptr> it(newObjects); - while (it.hasNext()) { - it.next(); - ret.append(it.value()); - } + ret = newObjects.values(); } return ret; }