forked from qt-creator/qt-creator
		
	QmlJS: Rework FakeMetaObjects to no longer contain pointers.
Having a duplicate prototype chain - once in FakeMetaObjects and once in QmlObjectValues was unnecessary. Now FMOs don't contain references which may allow other simplifications.
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|  | ||||
| const QmlObjectValue *QmlObjectValue::prototype() const | ||||
| { | ||||
|     Q_ASSERT(!_prototype || dynamic_cast<const QmlObjectValue *>(_prototype)); | ||||
|     return static_cast<const QmlObjectValue *>(_prototype); | ||||
| } | ||||
|  | ||||
| FakeMetaObject::ConstPtr QmlObjectValue::metaObject() const | ||||
| { | ||||
|     return _metaObject; | ||||
| } | ||||
|  | ||||
| QString QmlObjectValue::packageName() const | ||||
| { return _packageName; } | ||||
|  | ||||
| QString QmlObjectValue::nameInPackage(const QString &packageName) const | ||||
| { | ||||
|     foreach (const FakeMetaObject::Export &exp, _metaObject->exports()) | ||||
|         if (exp.package == packageName) | ||||
|             return exp.type; | ||||
|     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; } | ||||
|  | ||||
| @@ -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; | ||||
|     } | ||||
|  | ||||
|     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 { | ||||
|         const QString qname = qualifiedName(package, cppName, ComponentVersion()); | ||||
|         object = typeByQualifiedName(qname); | ||||
|         if (!object) { | ||||
|             object = new QmlObjectValue( | ||||
|                         metaObject, cppName, package, ComponentVersion(), cppObject->engine()); | ||||
|             _typesByFullyQualifiedName[qname] = object; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     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; | ||||
|     } else { | ||||
|         *created = false; | ||||
|     } | ||||
|  | ||||
|     return value; | ||||
|     return object; | ||||
| } | ||||
|  | ||||
| ConvertToNumber::ConvertToNumber(Engine *engine) | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user