diff options
10 files changed, 102 insertions, 3 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp index 280b08cc2..1f725967f 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp @@ -472,14 +472,35 @@ bool AbstractMetaFunction::generateBinding() const case ConversionOperator: case AssignmentOperatorFunction: case MoveAssignmentOperatorFunction: + case AbstractMetaFunction::MoveConstructorFunction: return false; default: + if (!isWhiteListed()) + return false; break; } if (isPrivate() && d->m_functionType != EmptyFunction) return false; return d->m_name != u"qt_metacall" && !usesRValueReferences() - && !isModifiedRemoved(); + && !isModifiedRemoved(); +} + +bool AbstractMetaFunction::isWhiteListed() const +{ + switch (d->m_functionType) { + case NormalFunction: + case SignalFunction: + case SlotFunction: + if (auto *dc = declaringClass()) { + const QSet<QString> &whiteList = dc->typeEntry()->generateFunctions(); + return whiteList.isEmpty() || whiteList.contains(d->m_name) + || whiteList.contains(minimalSignature()); + } + break; + default: + break; + } + return true; } QString AbstractMetaFunctionPrivate::signature() const diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h index c92ef6404..c48b57a4f 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h @@ -306,6 +306,9 @@ public: bool usesRValueReferences() const; bool generateBinding() const; + // Returns whether the function is contained in the positive list of the + // type entry if one is specified. + bool isWhiteListed() const; QString signature() const; /// Return a signature qualified by class name, for error reporting. diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp index 53db07c00..b83c38cb9 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp @@ -766,4 +766,37 @@ void TestAbstractMetaClass::testUsingTemplateMembers() QCOMPARE(valueList->queryFunctionsByName(u"append"_s).size(), 2); } +void TestAbstractMetaClass::testGenerateFunctions() +{ + const char cppCode[] = R"CPP( +class TestClass { +public: + TestClass(); + + void alpha(int); + void beta(int); + void beta(double); + void gamma(int); +}; +)CPP"; + + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <object-type name='TestClass' generate-functions='beta(double);gamma'/> +</typesystem> +)XML"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + auto *tc = AbstractMetaClass::findClass(classes, u"TestClass"); + // Verify that the constructor and 2 functions are generated. + const auto &functions = tc->functions(); + QCOMPARE(functions.size(), 5); + const auto generateCount = + std::count_if(functions.cbegin(), functions.cend(), + [](const auto &af) { return af->generateBinding(); }); + QCOMPARE(generateCount, 3); +} + QTEST_APPLESS_MAIN(TestAbstractMetaClass) diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.h b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.h index b0d9becfe..9887312cd 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.h +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.h @@ -57,6 +57,7 @@ private slots: void testUsingMembers(); void testUsingTemplateMembers_data(); void testUsingTemplateMembers(); + void testGenerateFunctions(); }; #endif // TESTABSTRACTMETACLASS_H diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp index 101be0c79..5e32b10e3 100644 --- a/sources/shiboken6/ApiExtractor/typesystem.cpp +++ b/sources/shiboken6/ApiExtractor/typesystem.cpp @@ -1231,6 +1231,7 @@ public: AddedFunctionList m_addedFunctions; FunctionModificationList m_functionMods; + QSet<QString> m_generateFunctions; FieldModificationList m_fieldMods; QList<TypeSystemProperty> m_properties; QString m_defaultConstructor; @@ -1356,6 +1357,18 @@ void ComplexTypeEntry::addNewFunction(const AddedFunctionPtr &addedFunction) d->m_addedFunctions << addedFunction; } +const QSet<QString> &ComplexTypeEntry::generateFunctions() const +{ + S_D(const ComplexTypeEntry); + return d->m_generateFunctions; +} + +void ComplexTypeEntry::setGenerateFunctions(const QSet<QString> &f) +{ + S_D(ComplexTypeEntry); + d->m_generateFunctions = f; +} + void ComplexTypeEntry::setFieldModifications(const FieldModificationList &mods) { S_D(ComplexTypeEntry); diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h index dd8b1524a..3d61a86dd 100644 --- a/sources/shiboken6/ApiExtractor/typesystem.h +++ b/sources/shiboken6/ApiExtractor/typesystem.h @@ -35,6 +35,7 @@ #include <QtCore/QStringList> #include <QtCore/QScopedPointer> +#include <QtCore/QSet> class AbstractMetaType; class CustomFunction; @@ -580,6 +581,10 @@ public: void setAddedFunctions(const AddedFunctionList &addedFunctions); void addNewFunction(const AddedFunctionPtr &addedFunction); + // Functions specified in the "generate-functions" attribute + const QSet<QString> &generateFunctions() const; + void setGenerateFunctions(const QSet<QString> &f); + void setFieldModifications(const FieldModificationList &mods); FieldModificationList fieldModifications() const; diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 2de95fcdc..1452eedf9 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -78,6 +78,7 @@ static inline QString forceAbstractAttribute() { return QStringLiteral("force-ab static inline QString forceIntegerAttribute() { return QStringLiteral("force-integer"); } static inline QString formatAttribute() { return QStringLiteral("format"); } static inline QString generateUsingAttribute() { return QStringLiteral("generate-using"); } +static inline QString generateFunctionsAttribute() { return QStringLiteral("generate-functions"); } static inline QString classAttribute() { return QStringLiteral("class"); } static inline QString generateAttribute() { return QStringLiteral("generate"); } static inline QString generateGetSetDefAttribute() { return QStringLiteral("generate-getsetdef"); } @@ -1770,6 +1771,13 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader } else if (name == deleteInMainThreadAttribute()) { if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false)) ctype->setDeleteInMainThread(true); + } else if (name == generateFunctionsAttribute()) { + const auto names = attributes->takeAt(i).value(); + const auto nameList = names.split(u';', Qt::SkipEmptyParts); + QSet<QString> nameSet; + for (const auto &name : nameList) + nameSet.insert(name.trimmed().toString()); + ctype->setGenerateFunctions(nameSet); } else if (name == u"target-type") { ctype->setTargetType(attributes->takeAt(i).value().toString()); } else if (name == snakeCaseAttribute()) { diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst index caacc5cb3..164fc002c 100644 --- a/sources/shiboken6/doc/typesystem_specifying_types.rst +++ b/sources/shiboken6/doc/typesystem_specifying_types.rst @@ -320,6 +320,7 @@ value-type allow-thread="..." disable-wrapper="yes | no" exception-handling="..." + generate-functions="..." isNull ="yes | no" operator-bool="yes | no" hash-function="..." @@ -349,7 +350,8 @@ value-type on its constructor signatures, thus **default-constructor** is used only in very odd cases. - For the *optional* **disable-wrapper** attribute, see :ref:`object-type`. + For the *optional* **disable-wrapper** and **generate-functions** + attributes, see :ref:`object-type`. For the *optional* **private** attribute, see :ref:`private_types`. @@ -397,6 +399,7 @@ object-type allow-thread="..." disable-wrapper="yes | no" exception-handling="..." + generate-functions="..." force-abstract="yes | no" hash-function="..." isNull ="yes | no" @@ -452,6 +455,15 @@ object-type specify the default handling for the corresponding function modification (see :ref:`modify-function`). + The *optional* **generate-functions** specifies a semicolon-separated + list of function names or minimal signatures to be generated. + This allows for restricting the functions for which bindings are generated. + This also applies to virtual functions; so, all abstract functions + need to be listed to prevent non-compiling code to be generated. + If nothing is specified, bindings for all suitable functions are + generated. Note that special functions (constructors, etc), + cannot be specified. + The *optional* **snake-case** attribute allows for overriding the value specified on the **typesystem** element. diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp index 9465bce8c..b559c5d93 100644 --- a/sources/shiboken6/generator/shiboken/headergenerator.cpp +++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp @@ -141,7 +141,8 @@ void HeaderGenerator::generateClass(TextStream &s, const GeneratorContext &class const auto &funcs = filterFunctions(metaClass); int maxOverrides = 0; for (const auto &func : funcs) { - if (!func->attributes().testFlag(AbstractMetaFunction::FinalCppMethod)) { + if (func->isWhiteListed() + && !func->attributes().testFlag(AbstractMetaFunction::FinalCppMethod)) { writeFunction(s, func); // PYSIDE-803: Build a boolean cache for unused overrides. if (shouldWriteVirtualMethodNative(func)) diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index bac9ed6b5..2d8bcd5d5 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -202,6 +202,8 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaCl bool ShibokenGenerator::shouldWriteVirtualMethodNative(const AbstractMetaFunctionCPtr &func) const { // PYSIDE-803: Extracted this because it is used multiple times. + if (!func->isWhiteListed()) + return false; const AbstractMetaClass *metaClass = func->ownerClass(); return (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) && ((func->isVirtual() || func->isAbstract()) |
