diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-03-13 09:56:38 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-03-18 11:43:07 +0100 |
commit | 02838733a868e8898cc8218a6a877ed52fe5a3e9 (patch) | |
tree | d6f38f134404268740f91b25d0a67c17aa974067 | |
parent | 9141f75965d3a7b03f831193ed1f4094aff28574 (diff) |
shiboken6: Register typedefs of container types
For signals like
QRemoteObjectRegistry.remoteObjectAdded(QRemoteObjectSourceLocation)
where
using QRemoteObjectSourceLocation =
std::pair<QString,QRemoteObjectSourceLocationInfo>
one needed to specify the fully qualified C++ name in @Slot()
for the metaobject system to work and the shiboken converter
to be found. Record the typedefs and register the container
converters under the typedef name, too.
Fixes: PYSIDE-2633
Change-Id: Ifc62f096277949a507957a0466adb47d082695c7
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
13 files changed, 94 insertions, 7 deletions
diff --git a/sources/pyside6/tests/pysidetest/testobject.cpp b/sources/pyside6/tests/pysidetest/testobject.cpp index 295945a86..fe4ec98f7 100644 --- a/sources/pyside6/tests/pysidetest/testobject.cpp +++ b/sources/pyside6/tests/pysidetest/testobject.cpp @@ -30,6 +30,11 @@ void TestObject::emitSignalWithTypedefValue(int value) emit signalWithTypedefValue(TypedefValue(value)); } +void TestObject::emitSignalWithContainerTypedefValue(const IntList &il) +{ + emit signalWithContainerTypedefValue(il); +} + void TestObject::emitFlagsSignal(Qt::Alignment alignment) { emit flagsSignal(alignment); diff --git a/sources/pyside6/tests/pysidetest/testobject.h b/sources/pyside6/tests/pysidetest/testobject.h index 0d6aa9d14..a095a382e 100644 --- a/sources/pyside6/tests/pysidetest/testobject.h +++ b/sources/pyside6/tests/pysidetest/testobject.h @@ -8,12 +8,15 @@ #include <QtWidgets/QApplication> +#include <QtCore/QList> #include <QtCore/QObject> #include <QtCore/QMetaType> #include <QtCore/QVariant> QT_FORWARD_DECLARE_CLASS(QDebug) +using IntList = QList<int>; + class IntValue { public: @@ -44,6 +47,7 @@ public: void emitSignalWithDefaultValue_bool(); void emitSignalWithTypedefValue(int value); + void emitSignalWithContainerTypedefValue(const IntList &il); void emitFlagsSignal(Qt::Alignment alignment); @@ -59,6 +63,7 @@ signals: void childrenChanged(const QList<QObject*>&); void signalWithDefaultValue(bool value = false); void signalWithTypedefValue(TypedefValue value); + void signalWithContainerTypedefValue(const IntList &il); void flagsSignal(Qt::Alignment alignment); private: diff --git a/sources/pyside6/tests/pysidetest/typedef_signal_test.py b/sources/pyside6/tests/pysidetest/typedef_signal_test.py index dfe5311e8..d0bdc880b 100644 --- a/sources/pyside6/tests/pysidetest/typedef_signal_test.py +++ b/sources/pyside6/tests/pysidetest/typedef_signal_test.py @@ -10,7 +10,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) from init_paths import init_test_paths init_test_paths(True) -from PySide6.QtCore import QObject +from PySide6.QtCore import QObject, Slot from testbinding import TestObject @@ -23,6 +23,10 @@ class Receiver(QObject): def slot(self, value): self.received = value + @Slot("IntList") + def containerSlot(self, value): + self.received = value + class TypedefSignal(unittest.TestCase): @@ -34,6 +38,15 @@ class TypedefSignal(unittest.TestCase): obj.emitSignalWithTypedefValue(2) self.assertEqual(receiver.received.value, 2) + def testContainerTypedef(self): + obj = TestObject(0) + receiver = Receiver() + + test_list = [1, 2] + obj.signalWithContainerTypedefValue.connect(receiver.containerSlot) + obj.emitSignalWithContainerTypedefValue(test_list) + self.assertEqual(receiver.received, test_list) + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 63e94cb51..58a8901cb 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -161,6 +161,11 @@ const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEn return d->m_enums; } +const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() const +{ + return d->m_typedefTargetToName; +} + void AbstractMetaBuilderPrivate::checkFunctionModifications() const { const auto &entries = TypeDatabase::instance()->entries(); @@ -963,9 +968,31 @@ std::optional<AbstractMetaEnum> return metaEnum; } -AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &, - const TypeDefModelItem &typeDef, - const AbstractMetaClassPtr ¤tClass) +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass) +{ + auto result = traverseTypeDefHelper(dom, typeDef, currentClass); + if (!result && typeDef->type().isPlain()) { + const auto &type = typeDef->type(); + QString fullName; + if (currentClass) + fullName += currentClass->qualifiedCppName() + "::"_L1; + fullName += typeDef->name(); + QString targetName = typeDef->type().toString(); + m_typedefTargetToName.insert(targetName, fullName); + const QByteArray normalized = QMetaObject::normalizedType(targetName.toUtf8().constData()); + if (targetName != QLatin1StringView(normalized)) + m_typedefTargetToName.insert(QString::fromUtf8(normalized), fullName); + } + return result; +} + +AbstractMetaClassPtr + AbstractMetaBuilderPrivate::traverseTypeDefHelper(const FileModelItem &, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass) { TypeDatabase *types = TypeDatabase::instance(); QString className = stripTemplateArgs(typeDef->name()); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h index b00a69363..cbd8c7034 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h @@ -54,6 +54,7 @@ public: const AbstractMetaFunctionCList &globalFunctions() const; const AbstractMetaEnumList &globalEnums() const; const QHash<TypeEntryCPtr, AbstractMetaEnum> &typeEntryToEnumsHash() const; + const QMultiHash<QString, QString> &typedefTargetToName() const; bool build(const QByteArrayList &arguments, ApiExtractorFlags apiExtractorFlags = {}, diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 39ade6438..d7aaba5b0 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -17,6 +17,7 @@ #include <QtCore/QFileInfo> #include <QtCore/QList> #include <QtCore/QMap> +#include <QtCore/QMultiHash> #include <QtCore/QSet> #include <optional> @@ -77,6 +78,9 @@ public: AbstractMetaClassPtr traverseTypeDef(const FileModelItem &dom, const TypeDefModelItem &typeDef, const AbstractMetaClassPtr ¤tClass); + AbstractMetaClassPtr traverseTypeDefHelper(const FileModelItem &dom, + const TypeDefModelItem &typeDef, + const AbstractMetaClassPtr ¤tClass); void traverseTypesystemTypedefs(); AbstractMetaClassPtr traverseClass(const FileModelItem &dom, const ClassModelItem &item, @@ -240,6 +244,7 @@ public: QFileInfoList m_globalHeaders; QStringList m_headerPaths; mutable QHash<QString, Include> m_resolveIncludeHash; + QMultiHash<QString, QString> m_typedefTargetToName; QList<TypeClassEntry> m_typeSystemTypeDefs; // look up metatype->class for type system typedefs ApiExtractorFlags m_apiExtractorFlags; bool m_skipDeprecated = false; diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp index 7778e97de..ea45f22ba 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp @@ -421,6 +421,7 @@ std::optional<ApiExtractorResult> ApiExtractor::run(ApiExtractorFlags flags) result.m_globalEnums = d->m_builder->globalEnums(); result.m_enums = d->m_builder->typeEntryToEnumsHash(); result.m_flags = flags; + result.m_typedefTargetToName = d->m_builder->typedefTargetToName(); qSwap(result.m_instantiatedContainers, collectContext.instantiatedContainers); qSwap(result.m_instantiatedSmartPointers, collectContext.instantiatedSmartPointers); return result; diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp index eb9ac2d4a..2a48a30d1 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.cpp @@ -50,6 +50,11 @@ const InstantiatedSmartPointers &ApiExtractorResult::instantiatedSmartPointers() return m_instantiatedSmartPointers; } +const QMultiHash<QString, QString> &ApiExtractorResult::typedefTargetToName() const +{ + return m_typedefTargetToName; +} + ApiExtractorFlags ApiExtractorResult::flags() const { return m_flags; diff --git a/sources/shiboken6/ApiExtractor/apiextractorresult.h b/sources/shiboken6/ApiExtractor/apiextractorresult.h index c1bb1a0a0..88a2093f1 100644 --- a/sources/shiboken6/ApiExtractor/apiextractorresult.h +++ b/sources/shiboken6/ApiExtractor/apiextractorresult.h @@ -10,6 +10,7 @@ #include "typesystem_typedefs.h" #include <QtCore/QHash> +#include <QtCore/QMultiHash> #include <optional> @@ -43,6 +44,8 @@ public: const AbstractMetaTypeList &instantiatedContainers() const; const InstantiatedSmartPointers &instantiatedSmartPointers() const; + const QMultiHash<QString, QString> &typedefTargetToName() const; + // Query functions for the generators std::optional<AbstractMetaEnum> findAbstractMetaEnum(TypeEntryCPtr typeEntry) const; @@ -66,6 +69,7 @@ private: AbstractMetaTypeList m_instantiatedContainers; InstantiatedSmartPointers m_instantiatedSmartPointers; QHash<TypeEntryCPtr, AbstractMetaEnum> m_enums; + QMultiHash<QString, QString> m_typedefTargetToName; ApiExtractorFlags m_flags; friend class ApiExtractor; diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp index 50d6a535c..f8c5c31d8 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp @@ -266,6 +266,12 @@ void TypeInfo::clearInstantiations() d->m_instantiations.clear(); } +bool TypeInfo::isPlain() const +{ + return d->m_constant == 0 && d->m_volatile == 0 && d->m_referenceType == NoReference + && d->m_indirections.isEmpty() && d->m_arrayElements.isEmpty(); +} + TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope) { CodeModel *__model = __scope->model(); diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h index d51e290c7..e4f363b67 100644 --- a/sources/shiboken6/ApiExtractor/parser/typeinfo.h +++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h @@ -80,6 +80,8 @@ public: void addInstantiation(const TypeInfo &i); void clearInstantiations(); + bool isPlain() const; // neither const,volatile, no indirections/references, array + bool isStdType() const; std::pair<qsizetype, qsizetype> diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 726365234..40c0e09da 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -4145,7 +4145,8 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const Abstrac } QString CppGenerator::writeContainerConverterInitialization(TextStream &s, - const AbstractMetaType &type) + const AbstractMetaType &type, + const ApiExtractorResult &api) { const auto cppSignature = QString::fromUtf8(QMetaObject::normalizedSignature(type.cppSignature().toUtf8())); @@ -4179,6 +4180,17 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s, QString isConv = convertibleToCppFunctionName(sourceTypeName, typeName); writeAddPythonToCppConversion(s, converter, toCpp, isConv); } + + auto typedefItPair = api.typedefTargetToName().equal_range(type.cppSignature()); + if (typedefItPair.first != typedefItPair.second) { + auto *typeDb = TypeDatabase::instance(); + s << "// Register converters for type aliases of " << cppSignature << "'.\n"; + for (auto it = typedefItPair.first; it != typedefItPair.second; ++it) { + if (!typeDb->findType(it.value())) + s << registerConverterName(it.value(), converter); + } + } + return converter; } @@ -6300,7 +6312,7 @@ bool CppGenerator::finishGeneration() if (!containers.isEmpty()) { s << '\n'; for (const AbstractMetaType &container : containers) { - const QString converterObj = writeContainerConverterInitialization(s, container); + const QString converterObj = writeContainerConverterInitialization(s, container, api()); const auto it = opaqueContainers.constFind(container); if (it != opaqueContainers.constEnd()) { writeSetPythonToCppPointerConversion(s, converterObj, diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index b7b1590ae..2c35b6f1d 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -460,7 +460,8 @@ private: const CustomConversionPtr &customConversion); static void writeEnumConverterInitialization(TextStream &s, const AbstractMetaEnum &metaEnum); static QString writeContainerConverterInitialization(TextStream &s, - const AbstractMetaType &type); + const AbstractMetaType &type, + const ApiExtractorResult &api); void writeSmartPointerConverterInitialization(TextStream &s, const AbstractMetaType &ype) const; static void writeExtendedConverterInitialization(TextStream &s, const TypeEntryCPtr &externalType, |