diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-11-09 10:40:29 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-11-10 14:14:59 +0100 |
commit | 3681ae61aaab836d26ad227911c3bfca92322f12 (patch) | |
tree | 0d368fe6dd1b434f4e3838224c4e9c732abada1f | |
parent | 2a71960d3ff3640b3dcb0c1b1eb004bbb3eaea4d (diff) |
shiboken6: Enable specifying namespaces for smart pointer instantiations
[ChangeLog][shiboken6] It is now possible to specify a namespace for a
smart pointer instantiation.
Task-number: PYSIDE-454
Change-Id: I9b61c3514211108fd7009e1776ae4fb8988c576b
Reviewed-by: Christian Tismer <tismer@stackless.com>
10 files changed, 68 insertions, 6 deletions
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp index 43c48882f..15b074d4d 100644 --- a/sources/shiboken6/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp @@ -12,6 +12,7 @@ #include "abstractmetalang.h" #include "codesnip.h" #include "exception.h" +#include "messages.h" #include "modifications.h" #include "reporthandler.h" #include "typedatabase.h" @@ -20,6 +21,7 @@ #include "primitivetypeentry.h" #include "smartpointertypeentry.h" #include "typedefentry.h" +#include "namespacetypeentry.h" #include "typesystemtypeentry.h" #include "qtcompat.h" @@ -508,14 +510,35 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex auto *ste = static_cast<const SmartPointerTypeEntry *>(smp.smartPointer->typeEntry()); QString name = ste->getTargetName(smp.type); auto *parentTypeEntry = ste->parent(); + InheritTemplateFlags flags; + + auto colonPos = name.lastIndexOf(u"::"); + const bool withinNameSpace = colonPos != -1; + if (withinNameSpace) { // user defined + const QString nameSpace = name.left(colonPos); + name.remove(0, colonPos + 2); + const auto nameSpaces = TypeDatabase::instance()->findNamespaceTypes(nameSpace); + if (nameSpaces.isEmpty()) + throw Exception(msgNamespaceNotFound(name)); + parentTypeEntry = nameSpaces.constFirst(); + } else { + flags.setFlag(InheritTemplateFlag::SetEnclosingClass); + } + auto *typedefEntry = new TypedefEntry(name, ste->name(), ste->version(), parentTypeEntry); typedefEntry->setTargetLangPackage(ste->targetLangPackage()); auto *instantiationEntry = TypeDatabase::initializeTypeDefEntry(typedefEntry, ste); smp.specialized = ApiExtractor::inheritTemplateClass(instantiationEntry, smp.smartPointer, - {instantiatedType}, - InheritTemplateFlag::SetEnclosingClass); + {instantiatedType}, flags); Q_ASSERT(smp.specialized); + if (withinNameSpace) { // move class to desired namespace + auto *enclClass = AbstractMetaClass::findClass(m_builder->classes(), parentTypeEntry); + Q_ASSERT(enclClass); + auto *specialized = const_cast<AbstractMetaClass *>(smp.specialized); + specialized->setEnclosingClass(enclClass); + enclClass->addInnerClass(specialized); + } if (instantiationEntry->isComplex()) { addOwnerModification(smp.specialized->queryFunctions(FunctionQueryOption::Constructors), @@ -550,8 +573,15 @@ ApiExtractorPrivate::collectInstantiatedContainersAndSmartPointers(Instantiation collectInstantiatedContainersAndSmartPointers(context, func); for (const AbstractMetaField &field : metaClass->fields()) addInstantiatedContainersAndSmartPointers(context, field.type(), field.name()); - for (auto *innerClass : metaClass->innerClasses()) - collectInstantiatedContainersAndSmartPointers(context, innerClass); + + // The list of inner classes might be extended when smart pointer + // instantiations are specified to be in namespaces. + auto &innerClasses = metaClass->innerClasses(); + for (auto i = innerClasses.size() - 1; i >= 0; --i) { + auto *innerClass = innerClasses.at(i); + if (!innerClass->typeEntry()->isSmartPointer()) + collectInstantiatedContainersAndSmartPointers(context, innerClass); + } } void diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index 5fbd6c8aa..f9dad4d50 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -255,6 +255,11 @@ QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, return result; } +QString msgNamespaceNotFound(const QString &name) +{ + return u"namespace '"_s + name + u"' not found."_s; +} + QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) { QString result = u"Ambiguous types of varying types found for \""_s + qualifiedName diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index 1d40dc76c..6b4ce2711 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -67,6 +67,8 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, const QString &fullName); +QString msgNamespaceNotFound(const QString &name); + QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst index b43c66732..f7409f3b3 100644 --- a/sources/shiboken6/doc/typesystem_specifying_types.rst +++ b/sources/shiboken6/doc/typesystem_specifying_types.rst @@ -665,6 +665,7 @@ smart-pointer-type found in the code will be generated. The type name might optionally be followed an equal sign and the Python type name, for example ``instantiations="int=IntPtr,double=DoublePtr"``. + It is also possible to specify a namespace delimited by ``::``. The *optional* attribute **type** specifies the type: diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index dea6550f7..d259ce82c 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -6635,9 +6635,13 @@ bool CppGenerator::finishGeneration() // Initialize smart pointer types. for (const auto &smp : api().instantiatedSmartPointers()) { GeneratorContext context = contextForSmartPointer(smp.specialized, smp.type); + auto *enclosingClass = context.metaClass()->enclosingClass(); + auto *enclosingTypeEntry = enclosingClass != nullptr + ? enclosingClass->typeEntry() + : smp.type.typeEntry()->targetLangEnclosingEntry(); writeInitFunc(s_classInitDecl, s_classPythonDefines, getInitFunctionName(context), - smp.type.typeEntry()->targetLangEnclosingEntry()); + enclosingTypeEntry); includes << smp.type.instantiations().constFirst().typeEntry()->include(); } diff --git a/sources/shiboken6/tests/libsmart/smart.h b/sources/shiboken6/tests/libsmart/smart.h index 9819ef43d..1f610b302 100644 --- a/sources/shiboken6/tests/libsmart/smart.h +++ b/sources/shiboken6/tests/libsmart/smart.h @@ -8,6 +8,7 @@ #include "smart_integer.h" #include "smart_obj.h" #include "smart_registry.h" +#include "smart_test.h" #include "stdsharedptrtestbench.h" #include "stdoptionaltestbench.h" #include "stduniqueptrtestbench.h" diff --git a/sources/shiboken6/tests/libsmart/smart_test.h b/sources/shiboken6/tests/libsmart/smart_test.h new file mode 100644 index 000000000..89d8cbc7c --- /dev/null +++ b/sources/shiboken6/tests/libsmart/smart_test.h @@ -0,0 +1,13 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef SMART_TEST_H +#define SMART_TEST_H + +namespace Test { + +enum DummyEnum { Dummy1, Dummy2 }; + +} + +#endif // SMART_TEST_H diff --git a/sources/shiboken6/tests/smartbinding/CMakeLists.txt b/sources/shiboken6/tests/smartbinding/CMakeLists.txt index 577c8936f..b15967781 100644 --- a/sources/shiboken6/tests/smartbinding/CMakeLists.txt +++ b/sources/shiboken6/tests/smartbinding/CMakeLists.txt @@ -26,6 +26,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/smart/std_unique_ptr_int_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/smart/stdoptionaltestbench_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/smart/stduniqueptrtestbench_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/smart/stduniqueptrvirtualmethodtester_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/test_wrapper.cpp ) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/smart-binding.txt.in" diff --git a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py index 5401d77d7..1bec3a286 100644 --- a/sources/shiboken6/tests/smartbinding/smart_pointer_test.py +++ b/sources/shiboken6/tests/smartbinding/smart_pointer_test.py @@ -233,6 +233,7 @@ class SmartPointerTests(unittest.TestCase): integer2 = o.createSharedPtrInteger2() # User defined name self.assertEqual(type(integer2).__name__, "SmartInteger2Ptr") + self.assertTrue("smart.Test.SmartInteger2Ptr" in repr(type(integer2))) self.assertEqual(integer2.value(), 456) # pass Smart<Integer2> to a function that accepts Smart<Integer> diff --git a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml index 74bfc28f1..261d5f15d 100644 --- a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml +++ b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml @@ -28,7 +28,7 @@ --> <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" null-check-method="isNull" - instantiations="Integer,Smart::Integer2=SmartInteger2Ptr,Obj"/> + instantiations="Integer,Smart::Integer2=Test::SmartInteger2Ptr,Obj"/> <object-type name="Obj" /> <value-type name="Integer" /> @@ -74,4 +74,8 @@ <object-type name="StdUniquePtrTestBench"/> <object-type name="StdUniquePtrVirtualMethodTester"/> + <namespace-type name="Test"> + <enum-type name="DummyEnum"/> + </namespace-type> + </typesystem> |