aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-05-29 22:08:26 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-06-09 17:05:15 +0200
commitc1d014d86ebde8f176fecf6e8cc920072cb809c3 (patch)
treeb1fd613489668f8dd513e1e84316d0a2f1de2ad2
parentf8a891f3d2b833747d575d92de99dfb27396a355 (diff)
shiboken6: Introduce a private attribute
Generate a separate, private module header containing classes marked as "private" in the typesystem. This can be used for classes that are not used in dependent modules and helps to prevent propagation of for example private headers required for them. Task-number: PYSIDE-802 Change-Id: If7f19c152d007c689bf719e13292107dceb802da Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp13
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.h3
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp4
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst19
-rw-r--r--sources/shiboken6/generator/generator.cpp8
-rw-r--r--sources/shiboken6/generator/generator.h2
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp2
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp64
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.h4
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp12
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h4
-rw-r--r--sources/shiboken6/tests/samplebinding/typesystem_sample.xml4
12 files changed, 127 insertions, 12 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index 55e5d3e8a..a220996a1 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -93,6 +93,7 @@ public:
int m_sbkIndex = 0;
TypeEntry::Type m_type;
bool m_stream = false;
+ bool m_private = false;
};
TypeEntryPrivate::TypeEntryPrivate(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr,
@@ -344,6 +345,16 @@ void TypeEntry::setStream(bool b)
m_d->m_stream = b;
}
+bool TypeEntry::isPrivate() const
+{
+ return m_d->m_private;
+}
+
+void TypeEntry::setPrivate(bool b)
+{
+ m_d->m_private = b;
+}
+
QString TypeEntry::name() const
{
return m_d->m_name;
@@ -2061,6 +2072,8 @@ void TypeEntry::formatDebug(QDebug &debug) const
debug << ", sbkIndex=" << m_d->m_sbkIndex;
if (m_d->m_include.isValid())
debug << ", include=" << m_d->m_include;
+ if (m_d->m_private)
+ debug << ", [private]";
formatList(debug, "extraIncludes", m_d->m_extraIncludes, ", ");
}
diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h
index 7d96c1bfb..abbbcd049 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.h
+++ b/sources/shiboken6/ApiExtractor/typesystem.h
@@ -147,6 +147,9 @@ public:
bool stream() const;
void setStream(bool b);
+ bool isPrivate() const;
+ void setPrivate(bool b);
+
// The type's name in C++, fully qualified
QString name() const;
// C++ excluding inline namespaces
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index 42a4015fc..baf979a8f 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -100,6 +100,7 @@ static inline QString staticAttribute() { return QStringLiteral("static"); }
static inline QString threadAttribute() { return QStringLiteral("thread"); }
static inline QString sourceAttribute() { return QStringLiteral("source"); }
static inline QString streamAttribute() { return QStringLiteral("stream"); }
+static inline QString privateAttribute() { return QStringLiteral("private"); }
static inline QString xPathAttribute() { return QStringLiteral("xpath"); }
static inline QString virtualSlotAttribute() { return QStringLiteral("virtual-slot"); }
static inline QString visibleAttribute() { return QStringLiteral("visible"); }
@@ -1551,6 +1552,9 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader
const auto name = attributes->at(i).qualifiedName();
if (name == streamAttribute()) {
ctype->setStream(convertBoolean(attributes->takeAt(i).value(), streamAttribute(), false));
+ } else if (name == privateAttribute()) {
+ ctype->setPrivate(convertBoolean(attributes->takeAt(i).value(),
+ privateAttribute(), false));
} else if (name == generateAttribute()) {
generate = convertBoolean(attributes->takeAt(i).value(), generateAttribute(), true);
} else if (name ==packageAttribute()) {
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index fadc78cd2..a8761d7f2 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -318,6 +318,7 @@ value-type
disable-wrapper="yes | no"
exception-handling="..."
hash-function="..."
+ private="yes | no"
stream="yes | no"
default-constructor="..."
revision="..."
@@ -344,6 +345,8 @@ value-type
For the *optional* **disable-wrapper** attribute, see :ref:`object-type`.
+ For the *optional* **private** attribute, see :ref:`private_types`.
+
The **revision** attribute can be used to specify a revision for each type, easing the
production of ABI compatible bindings.
@@ -378,6 +381,7 @@ object-type
exception-handling="..."
force-abstract="yes | no"
hash-function="..."
+ private="yes | no"
stream="yes | no"
revision="..."
snake-case="yes | no | both" />
@@ -402,6 +406,8 @@ object-type
references, or using a default value that cannot be generated for a
parameter, or similar).
+ For the *optional* **private** attribute, see :ref:`private_types`.
+
The *optional* attribute **stream** specifies whether this type will be able to
use externally defined operators, like QDataStream << and >>. If equals to **yes**,
these operators will be called as normal methods within the current class.
@@ -601,3 +607,16 @@ Conditional Processing
Other keywords can be specified using the
:ref:`--keywords <conditional_keywords>` command line option.
+
+.. _private_types:
+
+Private Types
+^^^^^^^^^^^^^
+
+Marking :ref:`object-type` or :ref:`value-type` entries as private causes a
+separate, private module header besides the public module header to be
+generated for them.
+
+This can be used for classes that are not referenced in dependent modules
+and helps to prevent the propagation of for example private C++ headers
+required for them.
diff --git a/sources/shiboken6/generator/generator.cpp b/sources/shiboken6/generator/generator.cpp
index 58998a380..1988c63f6 100644
--- a/sources/shiboken6/generator/generator.cpp
+++ b/sources/shiboken6/generator/generator.cpp
@@ -177,6 +177,7 @@ struct Generator::GeneratorPrivate
AbstractMetaTypeList instantiatedContainers;
AbstractMetaTypeList instantiatedSmartPointers;
AbstractMetaClassCList m_invisibleTopNamespaces;
+ bool m_hasPrivateClasses = false;
};
Generator::Generator() : m_d(new GeneratorPrivate)
@@ -464,6 +465,8 @@ bool Generator::generate()
for (auto cls : m_d->api.classes()) {
if (!generateFileForContext(contextForClass(cls)))
return false;
+ if (shouldGenerate(cls) && cls->typeEntry()->isPrivate())
+ m_d->m_hasPrivateClasses = true;
}
const auto smartPointers = m_d->api.smartPointers();
@@ -508,6 +511,11 @@ const ApiExtractorResult &Generator::api() const
return m_d->api;
}
+bool Generator::hasPrivateClasses() const
+{
+ return m_d->m_hasPrivateClasses;
+}
+
QString Generator::getFullTypeName(const TypeEntry *type)
{
QString result = type->qualifiedCppName();
diff --git a/sources/shiboken6/generator/generator.h b/sources/shiboken6/generator/generator.h
index 2930ff5ee..48ce9edca 100644
--- a/sources/shiboken6/generator/generator.h
+++ b/sources/shiboken6/generator/generator.h
@@ -237,6 +237,8 @@ public:
/// Returns the API as determined by ApiExtractor
const ApiExtractorResult &api() const;
+ bool hasPrivateClasses() const;
+
/**
* Retrieves the name of the currently processed module.
* While package name is a complete package idetification, e.g. 'PySide.QtCore',
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 2e9ea8d0b..c58842c95 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -413,6 +413,8 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
s << "#include <helper.h>\n#include <iostream>\n";
s << "\n// module include\n" << "#include \"" << getModuleHeaderFileName() << "\"\n";
+ if (hasPrivateClasses())
+ s << "#include \"" << getPrivateModuleHeaderFileName() << "\"\n";
QString headerfile = fileNameForContext(classContext);
headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h"));
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
index 8bf22d52c..d4dc38090 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -404,6 +404,7 @@ bool HeaderGenerator::finishGeneration()
// This header should be included by binding modules
// extendind on top of this one.
QSet<Include> includes;
+ QSet<Include> privateIncludes;
StringStream macrosStream(TextStream::Language::Cpp);
const auto snips = TypeDatabase::instance()->defaultTypeSystemType()->codeSnips();
@@ -494,6 +495,7 @@ bool HeaderGenerator::finishGeneration()
macrosStream << "// Macros for type check\n";
StringStream typeFunctions(TextStream::Language::Cpp);
+ StringStream privateTypeFunctions(TextStream::Language::Cpp);
if (usePySideExtensions()) {
typeFunctions << "QT_WARNING_PUSH\n";
typeFunctions << "QT_WARNING_DISABLE_DEPRECATED\n";
@@ -512,19 +514,22 @@ bool HeaderGenerator::finishGeneration()
//Includes
const TypeEntry *classType = metaClass->typeEntry();
- includes << classType->include();
+ const bool isPrivate = classType->isPrivate();
+ auto &includeList = isPrivate ? privateIncludes : includes;
+ includeList << classType->include();
+ auto &typeFunctionsStr = isPrivate ? privateTypeFunctions : typeFunctions;
for (const AbstractMetaEnum &cppEnum : metaClass->enums()) {
if (cppEnum.isAnonymous() || cppEnum.isPrivate())
continue;
EnumTypeEntry *enumType = cppEnum.typeEntry();
- includes << enumType->include();
+ includeList << enumType->include();
writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
- writeSbkTypeFunction(typeFunctions, cppEnum);
+ writeSbkTypeFunction(typeFunctionsStr, cppEnum);
}
if (!metaClass->isNamespace())
- writeSbkTypeFunction(typeFunctions, metaClass);
+ writeSbkTypeFunction(typeFunctionsStr, metaClass);
}
for (const AbstractMetaType &metaType : instantiatedSmartPtrs) {
@@ -535,9 +540,9 @@ bool HeaderGenerator::finishGeneration()
if (usePySideExtensions())
typeFunctions << "QT_WARNING_POP\n";
- QString moduleHeaderFileName(outputDirectory()
- + QDir::separator() + subDirectoryForPackage(packageName())
- + QDir::separator() + getModuleHeaderFileName());
+ const QString moduleHeaderDir = outputDirectory() + QLatin1Char('/')
+ + subDirectoryForPackage(packageName()) + QLatin1Char('/');
+ const QString moduleHeaderFileName(moduleHeaderDir + getModuleHeaderFileName());
QString includeShield(QLatin1String("SBK_") + moduleName().toUpper() + QLatin1String("_PYTHON_H"));
@@ -599,7 +604,50 @@ bool HeaderGenerator::finishGeneration()
<< "} // namespace Shiboken\n\n"
<< "#endif // " << includeShield << "\n\n";
- return file.done() != FileOut::Failure;
+ if (file.done() == FileOut::Failure)
+ return false;
+
+ return !hasPrivateClasses()
+ || writePrivateHeader(moduleHeaderDir, includeShield,
+ privateIncludes, privateTypeFunctions.toString());
+}
+
+bool HeaderGenerator::writePrivateHeader(const QString &moduleHeaderDir,
+ const QString &publicIncludeShield,
+ const QSet<Include> &privateIncludes,
+ const QString &privateTypeFunctions)
+{
+ // Write includes and type functions of private classes
+
+ FileOut privateFile(moduleHeaderDir + getPrivateModuleHeaderFileName());
+ TextStream &ps = privateFile.stream;
+ ps.setLanguage(TextStream::Language::Cpp);
+ QString privateIncludeShield =
+ publicIncludeShield.left(publicIncludeShield.size() - 2)
+ + QStringLiteral("_P_H");
+
+ ps << licenseComment()<< "\n\n";
+
+ ps << "#ifndef " << privateIncludeShield << '\n';
+ ps << "#define " << privateIncludeShield << "\n\n";
+
+ for (const Include &include : qAsConst(privateIncludes))
+ ps << include;
+ ps << '\n';
+
+ if (usePySideExtensions())
+ ps << "QT_WARNING_PUSH\nQT_WARNING_DISABLE_DEPRECATED\n";
+
+ ps << "namespace Shiboken\n{\n\n"
+ << "// PyType functions, to get the PyObjectType for a type T\n"
+ << privateTypeFunctions << '\n'
+ << "} // namespace Shiboken\n\n";
+
+ if (usePySideExtensions())
+ ps << "QT_WARNING_POP\n";
+
+ ps << "#endif\n";
+ return privateFile.done() != FileOut::Failure;
}
void HeaderGenerator::writeProtectedEnumSurrogate(TextStream &s, const AbstractMetaEnum &cppEnum) const
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.h b/sources/shiboken6/generator/shiboken/headergenerator.h
index 1fe0dd444..91a10eef8 100644
--- a/sources/shiboken6/generator/shiboken/headergenerator.h
+++ b/sources/shiboken6/generator/shiboken/headergenerator.h
@@ -65,6 +65,10 @@ private:
void writeMemberFunctionWrapper(TextStream &s,
const AbstractMetaFunctionCPtr &func,
const QString &postfix = {}) const;
+ bool writePrivateHeader(const QString &moduleHeaderDir,
+ const QString &publicIncludeShield,
+ const QSet<Include> &privateIncludes,
+ const QString &privateTypeFunctions);
QSet<AbstractMetaFunctionCPtr> m_inheritedOverloads;
};
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index 05a9e7571..4ecc69b15 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -2125,9 +2125,19 @@ const AbstractMetaClass *ShibokenGenerator::getMultipleInheritingClass(const Abs
return getMultipleInheritingClass(metaClass->baseClass());
}
+QString ShibokenGenerator::getModuleHeaderFileBaseName(const QString &moduleName)
+{
+ return moduleCppPrefix(moduleName).toLower() + QStringLiteral("_python");
+}
+
QString ShibokenGenerator::getModuleHeaderFileName(const QString &moduleName)
{
- return moduleCppPrefix(moduleName).toLower() + QLatin1String("_python.h");
+ return getModuleHeaderFileBaseName(moduleName) + QStringLiteral(".h");
+}
+
+QString ShibokenGenerator::getPrivateModuleHeaderFileName(const QString &moduleName)
+{
+ return getModuleHeaderFileBaseName(moduleName) + QStringLiteral("_p.h");
}
std::optional<AbstractMetaType>
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index bcba349cf..29b32c23a 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -313,7 +313,8 @@ protected:
static QString getFormatUnitString(const AbstractMetaFunctionCPtr &func, bool incRef = false);
/// Returns the file name for the module global header. If no module name is provided the current will be used.
- static QString getModuleHeaderFileName(const QString &moduleName = QString()) ;
+ static QString getModuleHeaderFileName(const QString &moduleName = QString());
+ static QString getPrivateModuleHeaderFileName(const QString &moduleName = QString());
OptionDescriptions options() const override;
bool handleOption(const QString &key, const QString &value) override;
@@ -398,6 +399,7 @@ protected:
static const QHash<QString, QString> &formatUnits();
private:
+ static QString getModuleHeaderFileBaseName(const QString &moduleName = QString());
static QString cpythonGetterFunctionName(const QString &name,
const AbstractMetaClass *enclosingClass);
static QString cpythonSetterFunctionName(const QString &name,
diff --git a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
index fe5e4343c..d86a637ff 100644
--- a/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken6/tests/samplebinding/typesystem_sample.xml
@@ -2302,7 +2302,7 @@
<object-type name="MDerived5"/>
<object-type name="SonOfMDerived1"/>
- <object-type name="Bucket">
+ <object-type name="Bucket" private="true">
<modify-function signature="lock()" allow-thread="yes" />
<modify-function signature="virtualBlockerMethod()" allow-thread="yes"/>
<modify-function signature="callVirtualBlockerMethodButYouDontKnowThis()" allow-thread="yes"/>
@@ -2330,7 +2330,7 @@
<property type="RenderHints" name="renderHints" get="getRenderHints" set="setRenderHints"/>
</value-type>
- <value-type name="CtorConvRule">
+ <value-type name="CtorConvRule" private="true">
<modify-function signature="CtorConvRule(long)">
<modify-argument index="1">
<!--<replace-type modified-type="long"/>-->