diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-10-30 11:47:02 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-05-22 09:55:21 +0200 |
commit | 91cb27a2a7180e9c05b806d870b266fa31bef041 (patch) | |
tree | d1b044350e40f4ca6809717e350d0675326b4015 /sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp | |
parent | ff3a9f61edc479e5610f6d57c5ab789704ca81cb (diff) |
shiboken: Make it possible to extend namespaces
Qt has some modules, where functions and classes are added to
namespaces of other modules. For example, QtGui adds the free
functions mightBeRichText() and convertFromPlainText() to the "Qt"
namespace and Qt3DQuick adds a namespace "Quick" to the namespace
"Qt3DCore" started in Qt3DCore. Shiboken was unable to handle this
since the name of the index constant was derived from the namespace
name and would thus clash. Also, all code model items from the base
module would be re-generated into the extended namespace.
To fix this:
- No longer join namespace code model items in clang builder.
- Search for pre-existing namespaces in traverseNamespace() before
creating a new one, continuing populating it.
- Add a "files" attribute taking a regular expression to match header
names to the namespace type entry, making it possible to restrict
code model items by files when extending namespaces (as otherwise,
all base items are again added).
- Add "extends" attribute specifying the package name of the namespace
to extend, which will be used as base type in CPython.
- Disambiguate the SBK indexes of namespaces and the init_ functions
by adding the module name.
Change-Id: Ib552e878911942fa4d52d2bb0c6695e5b2c4c341
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 7e998d315..67489b151 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -452,10 +452,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) const auto &namespaceTypeValues = dom->namespaces(); ReportHandler::startProgress("Generating namespace model (" + QByteArray::number(namespaceTypeValues.size()) + ")..."); - for (const NamespaceModelItem &item : namespaceTypeValues) { - if (AbstractMetaClass *metaClass = traverseNamespace(dom, item)) - addAbstractMetaClass(metaClass, item.data()); - } + for (const NamespaceModelItem &item : namespaceTypeValues) + traverseNamespace(dom, item); // Go through all typedefs to see if we have defined any // specific typedefs to be used as classes. @@ -742,23 +740,38 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel if (!namespaceName.isEmpty()) namespaceName.append(colonColon()); namespaceName.append(namespaceItem->name()); - NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName); if (TypeDatabase::instance()->isClassRejected(namespaceName)) { m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled); return 0; } + auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName()); if (!type) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName); return 0; } - AbstractMetaClass* metaClass = new AbstractMetaClass; - metaClass->setTypeEntry(type); - - *metaClass += AbstractMetaAttributes::Public; + // Continue populating namespace? + AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type); + if (!metaClass) { + metaClass = new AbstractMetaClass; + metaClass->setTypeEntry(type); + *metaClass += AbstractMetaAttributes::Public; + addAbstractMetaClass(metaClass, namespaceItem.data()); + if (auto extendsType = type->extends()) { + AbstractMetaClass *extended = AbstractMetaClass::findClass(m_metaClasses, extendsType); + if (!extended) { + qCWarning(lcShiboken, "%s", + qPrintable(msgNamespaceToBeExtendedNotFound(extendsType->name(), extendsType->targetLangPackage()))); + return nullptr; + } + metaClass->setExtendedNamespace(extended); + } + } else { + m_itemToClass.insert(namespaceItem.data(), metaClass); + } if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { qCDebug(lcShiboken) @@ -797,7 +810,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel if (mjc) { metaClass->addInnerClass(mjc); mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc, ni.data()); } } @@ -3075,6 +3087,30 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const return result; } +void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item) +{ + // For purposes of type lookup, join all namespaces of the same name + // within the parent item. + QVector<NamespaceModelItem> candidates; + const QString name = item->name(); + if (!m_scopes.isEmpty()) { + for (const auto &n : m_scopes.constLast()->namespaces()) { + if (n->name() == name) + candidates.append(n); + } + } + if (candidates.size() > 1) { + NamespaceModelItem joined(new _NamespaceModelItem(m_scopes.constLast()->model(), + name, _CodeModelItem::Kind_Namespace)); + joined->setScope(item->scope()); + for (const auto &n : candidates) + joined->appendNamespace(*n); + m_scopes << joined; + } else { + m_scopes << item; + } +} + AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClassList &classList, const Dependencies &additionalDependencies) const { |