aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.cpp23
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.h3
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.cpp33
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testabstractmetaclass.h1
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp13
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.h5
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp8
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst14
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp3
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp2
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())