diff options
Diffstat (limited to 'sources')
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 |