aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
Diffstat (limited to 'sources')
-rw-r--r--sources/pyside6/cmake/Macros/PySideModules.cmake1
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp10
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h1
-rw-r--r--sources/shiboken6/doc/shibokengenerator.rst4
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp135
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp10
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h4
-rw-r--r--sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in1
-rw-r--r--sources/shiboken6/tests/otherbinding/other-binding.txt.in2
-rw-r--r--sources/shiboken6/tests/samplebinding/sample-binding.txt.in1
-rw-r--r--sources/shiboken6/tests/smartbinding/smart-binding.txt.in1
11 files changed, 155 insertions, 15 deletions
diff --git a/sources/pyside6/cmake/Macros/PySideModules.cmake b/sources/pyside6/cmake/Macros/PySideModules.cmake
index 60a863d0a..08b2127ed 100644
--- a/sources/pyside6/cmake/Macros/PySideModules.cmake
+++ b/sources/pyside6/cmake/Macros/PySideModules.cmake
@@ -131,6 +131,7 @@ macro(create_pyside_module)
"--typesystem-paths=${pyside_binary_dir}${PATH_SEP}${pyside6_SOURCE_DIR}${PATH_SEP}${${module_TYPESYSTEM_PATH}}"
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
--license-file=${CMAKE_CURRENT_SOURCE_DIR}/../licensecomment.txt
+ --lean-headers
--api-version=${SUPPORTED_QT_VERSION})
if(CMAKE_HOST_APPLE)
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
index 056003f5c..9cde7d992 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
@@ -529,6 +529,16 @@ bool AbstractMetaClass::isInvisibleNamespace() const
&& !NamespaceTypeEntry::isVisibleScope(d->m_typeEntry);
}
+bool AbstractMetaClass::isInlineNamespace() const
+{
+ bool result = false;
+ if (d->m_typeEntry->isNamespace()) {
+ auto *nte = static_cast<const NamespaceTypeEntry *>(d->m_typeEntry);
+ result = nte->isInlineNamespace();
+ }
+ return result;
+}
+
bool AbstractMetaClass::isQtNamespace() const
{
return isNamespace() && name() == u"Qt";
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h
index 53266778f..1c35c872e 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h
@@ -217,6 +217,7 @@ public:
bool isNamespace() const;
bool isInvisibleNamespace() const;
+ bool isInlineNamespace() const;
bool isQObject() const { return inheritsFrom(u"QObject"_qs); }
bool isQtNamespace() const;
diff --git a/sources/shiboken6/doc/shibokengenerator.rst b/sources/shiboken6/doc/shibokengenerator.rst
index 6fb0948db..01b4420ee 100644
--- a/sources/shiboken6/doc/shibokengenerator.rst
+++ b/sources/shiboken6/doc/shibokengenerator.rst
@@ -118,6 +118,10 @@ Options
If a class has an isNull() const method, it will be used to
compute the value of boolean casts (see :ref:`bool-cast`).
+``--lean-headers``
+ Forward declare classes in module headers instead of including their class
+ headers where possible.
+
.. _use-operator-bool-as-nb-nonzero:
``--use-operator-bool-as-nb_nonzero``
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
index 5c61b028c..c4a87c3f9 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -413,12 +413,111 @@ static void formatTypeDefEntries(TextStream &s)
s << '\n';
}
+// Helpers for forward-declaring classes in the module header for the
+// specialization of the SbkType template functions. This is possible if the
+// class does not have inner types or enums which need to be known.
+static bool canForwardDeclare(const AbstractMetaClass *c)
+{
+ if (c->isNamespace() || !c->enums().isEmpty()
+ || !c->innerClasses().isEmpty() || c->isTypeDef()) {
+ return false;
+ }
+ if (auto *encl = c->enclosingClass())
+ return encl->isNamespace();
+ return true;
+}
+
+static void writeForwardDeclaration(TextStream &s, const AbstractMetaClass *c)
+{
+ Q_ASSERT(!c->isNamespace());
+ const bool isStruct = c->attributes().testFlag(AbstractMetaClass::Struct);
+ s << (isStruct ? "struct " : "class ");
+ // Do not use name as this can be modified/renamed for target lang.
+ const QString qualifiedCppName = c->qualifiedCppName();
+ const auto lastQualifier = qualifiedCppName.lastIndexOf(u':');
+ if (lastQualifier != -1)
+ s << QStringView{qualifiedCppName}.mid(lastQualifier + 1);
+ else
+ s << qualifiedCppName;
+ s << ";\n";
+}
+
+// Helpers for writing out namespaces hierarchically when writing class
+// forward declarations to the module header. Ensure inline namespaces
+// are marked as such (else clang complains) and namespaces are ordered.
+struct NameSpace {
+ const AbstractMetaClass *nameSpace;
+ AbstractMetaClassCList classes;
+};
+
+static bool operator<(const NameSpace &n1, const NameSpace &n2)
+{
+ return n1.nameSpace->name() < n2.nameSpace->name();
+}
+
+using NameSpaces = QList<NameSpace>;
+
+static qsizetype indexOf(const NameSpaces &nsps, const AbstractMetaClass *needle)
+{
+ for (qsizetype i = 0, count = nsps.size(); i < count; ++i) {
+ if (nsps.at(i).nameSpace == needle)
+ return i;
+ }
+ return -1;
+}
+
+static void writeNamespaceForwardDeclarationRecursion(TextStream &s, qsizetype idx,
+ const NameSpaces &nameSpaces)
+{
+ auto &root = nameSpaces.at(idx);
+ s << '\n';
+ if (root.nameSpace->isInlineNamespace())
+ s << "inline ";
+ s << "namespace " << root.nameSpace->name() << " {\n" << indent;
+ for (auto *c : root.classes)
+ writeForwardDeclaration(s, c);
+
+ for (qsizetype i = 0, count = nameSpaces.size(); i < count; ++i) {
+ if (i != idx && nameSpaces.at(i).nameSpace->enclosingClass() == root.nameSpace)
+ writeNamespaceForwardDeclarationRecursion(s, i, nameSpaces);
+ }
+ s << outdent << "}\n";
+}
+
+static void writeForwardDeclarations(TextStream &s,
+ const AbstractMetaClassCList &classList)
+{
+ NameSpaces nameSpaces;
+
+ for (auto *c : classList) {
+ if (auto *encl = c->enclosingClass()) {
+ Q_ASSERT(encl->isNamespace());
+ auto idx = indexOf(nameSpaces, encl);
+ if (idx != -1)
+ nameSpaces[idx].classes.append(c);
+ else
+ nameSpaces.append(NameSpace{encl, {c}});
+ } else {
+ writeForwardDeclaration(s, c);
+ }
+ }
+
+ std::sort(nameSpaces.begin(), nameSpaces.end());
+
+ // Recursively write out namespaces starting at the root elements.
+ for (qsizetype i = 0, count = nameSpaces.size(); i < count; ++i) {
+ const auto &nsp = nameSpaces.at(i);
+ if (nsp.nameSpace->enclosingClass() == nullptr)
+ writeNamespaceForwardDeclarationRecursion(s, i, nameSpaces);
+ }
+}
bool HeaderGenerator::finishGeneration()
{
// Generate the main header for this module.
// This header should be included by binding modules
// extendind on top of this one.
+ AbstractMetaClassCList forwardDeclarations;
QSet<Include> includes;
QSet<Include> privateIncludes;
StringStream macrosStream(TextStream::Language::Cpp);
@@ -531,7 +630,11 @@ bool HeaderGenerator::finishGeneration()
//Includes
const bool isPrivate = classType->isPrivate();
auto &includeList = isPrivate ? privateIncludes : includes;
- includeList << classType->include();
+ if (leanHeaders() && canForwardDeclare(metaClass))
+ forwardDeclarations.append(metaClass);
+ else
+ includeList << classType->include();
+
auto &typeFunctionsStr = isPrivate ? privateTypeFunctions : typeFunctions;
for (const AbstractMetaEnum &cppEnum : metaClass->enums()) {
@@ -590,20 +693,24 @@ bool HeaderGenerator::finishGeneration()
for (const Include &include : std::as_const(includes))
s << include;
- if (!primitiveTypes().isEmpty()) {
- s << "// Conversion Includes - Primitive Types\n";
- const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
- for (const PrimitiveTypeEntry *ptype : primitiveTypeList)
- s << ptype->include();
- s<< '\n';
- }
+ if (leanHeaders()) {
+ writeForwardDeclarations(s, forwardDeclarations);
+ } else {
+ if (!primitiveTypes().isEmpty()) {
+ s << "// Conversion Includes - Primitive Types\n";
+ const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
+ for (const PrimitiveTypeEntry *ptype : primitiveTypeList)
+ s << ptype->include();
+ s<< '\n';
+ }
- if (!containerTypes().isEmpty()) {
- s << "// Conversion Includes - Container Types\n";
- const ContainerTypeEntryList &containerTypeList = containerTypes();
- for (const ContainerTypeEntry *ctype : containerTypeList)
- s << ctype->include();
- s<< '\n';
+ if (!containerTypes().isEmpty()) {
+ s << "// Conversion Includes - Container Types\n";
+ const ContainerTypeEntryList &containerTypeList = containerTypes();
+ for (const ContainerTypeEntry *ctype : containerTypeList)
+ s << ctype->include();
+ s<< '\n';
+ }
}
s << macrosStream.toString() << '\n';
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index e6cc4383f..24a782879 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -54,6 +54,7 @@ static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero";
static const char USE_OPERATOR_BOOL_AS_NB_NONZERO[] = "use-operator-bool-as-nb_nonzero";
static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics";
static const char NO_IMPLICIT_CONVERSIONS[] = "no-implicit-conversions";
+static const char LEAN_HEADERS[] = "lean-headers";
const QString CPP_ARG = u"cppArg"_s;
const QString CPP_ARG_REMOVED = u"removed_cppArg"_s;
@@ -2081,6 +2082,8 @@ Generator::OptionDescriptions ShibokenGenerator::options() const
{QLatin1StringView(USE_ISNULL_AS_NB_NONZERO),
u"If a class have an isNull() const method, it will be used to compute\n"
"the value of boolean casts"_s},
+ {QLatin1StringView(LEAN_HEADERS),
+ u"Forward declare classes in module headers"_s},
{QLatin1StringView(USE_OPERATOR_BOOL_AS_NB_NONZERO),
u"If a class has an operator bool, it will be used to compute\n"
"the value of boolean casts"_s},
@@ -2104,6 +2107,8 @@ bool ShibokenGenerator::handleOption(const QString &key, const QString &value)
return (m_verboseErrorMessagesDisabled = true);
if (key == QLatin1StringView(USE_ISNULL_AS_NB_NONZERO))
return (m_useIsNullAsNbNonZero = true);
+ if (key == QLatin1StringView(LEAN_HEADERS))
+ return (m_leanHeaders= true);
if (key == QLatin1StringView(USE_OPERATOR_BOOL_AS_NB_NONZERO))
return (m_useOperatorBoolAsNbNonZero = true);
if (key == QLatin1StringView(NO_IMPLICIT_CONVERSIONS)) {
@@ -2135,6 +2140,11 @@ bool ShibokenGenerator::useIsNullAsNbNonZero() const
return m_useIsNullAsNbNonZero;
}
+bool ShibokenGenerator::leanHeaders() const
+{
+ return m_leanHeaders;
+}
+
bool ShibokenGenerator::useOperatorBoolAsNbNonZero() const
{
return m_useOperatorBoolAsNbNonZero;
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index 4f486de57..af18d2f17 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -272,6 +272,8 @@ protected:
bool useReturnValueHeuristic() const;
/// Returns true if the generator should use the result of isNull()const to compute boolean casts.
bool useIsNullAsNbNonZero() const;
+ /// Whether to generate lean module headers
+ bool leanHeaders() const;
/// Returns true if the generator should use operator bool to compute boolean casts.
bool useOperatorBoolAsNbNonZero() const;
/// Generate implicit conversions of function arguments
@@ -434,6 +436,8 @@ private:
bool m_userReturnValueHeuristic = false;
bool m_verboseErrorMessagesDisabled = false;
bool m_useIsNullAsNbNonZero = false;
+ // FIXME PYSIDE 7 Flip m_leanHeaders default or remove?
+ bool m_leanHeaders = false;
bool m_useOperatorBoolAsNbNonZero = false;
// FIXME PYSIDE 7 Flip generateImplicitConversions default or remove?
bool m_generateImplicitConversions = true;
diff --git a/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
index 85b139676..101567070 100644
--- a/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
+++ b/sources/shiboken6/tests/minimalbinding/minimal-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers
diff --git a/sources/shiboken6/tests/otherbinding/other-binding.txt.in b/sources/shiboken6/tests/otherbinding/other-binding.txt.in
index dbe935a9f..d85f6030a 100644
--- a/sources/shiboken6/tests/otherbinding/other-binding.txt.in
+++ b/sources/shiboken6/tests/otherbinding/other-binding.txt.in
@@ -17,4 +17,4 @@ typesystem-path = @sample_SOURCE_DIR@
typesystem-path = @smart_SOURCE_DIR@
enable-parent-ctor-heuristic
-
+lean-headers
diff --git a/sources/shiboken6/tests/samplebinding/sample-binding.txt.in b/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
index 317f76f09..bcf9de90f 100644
--- a/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
+++ b/sources/shiboken6/tests/samplebinding/sample-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers
diff --git a/sources/shiboken6/tests/smartbinding/smart-binding.txt.in b/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
index 699f0bfe6..a2c73c6bf 100644
--- a/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
+++ b/sources/shiboken6/tests/smartbinding/smart-binding.txt.in
@@ -13,3 +13,4 @@ typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@
enable-parent-ctor-heuristic
use-isnull-as-nb_nonzero
+lean-headers