aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/headergenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/generator/shiboken/headergenerator.cpp')
-rw-r--r--sources/shiboken6/generator/shiboken/headergenerator.cpp661
1 files changed, 661 insertions, 0 deletions
diff --git a/sources/shiboken6/generator/shiboken/headergenerator.cpp b/sources/shiboken6/generator/shiboken/headergenerator.cpp
new file mode 100644
index 000000000..d607ed643
--- /dev/null
+++ b/sources/shiboken6/generator/shiboken/headergenerator.cpp
@@ -0,0 +1,661 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "headergenerator.h"
+#include <abstractmetalang.h>
+#include <typedatabase.h>
+#include <reporthandler.h>
+#include <fileout.h>
+#include "parser/codemodel.h"
+
+#include <algorithm>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+#include <QtCore/QDebug>
+
+QString HeaderGenerator::fileNameSuffix() const
+{
+ return QLatin1String("_wrapper.h");
+}
+
+QString HeaderGenerator::fileNameForContext(const GeneratorContext &context) const
+{
+ const AbstractMetaClass *metaClass = context.metaClass();
+ if (!context.forSmartPointer()) {
+ QString fileNameBase = metaClass->qualifiedCppName().toLower();
+ fileNameBase.replace(QLatin1String("::"), QLatin1String("_"));
+ return fileNameBase + fileNameSuffix();
+ }
+ QString fileNameBase = getFileNameBaseForSmartPointer(context.preciseType(), metaClass);
+ return fileNameBase + fileNameSuffix();
+}
+
+void HeaderGenerator::writeCopyCtor(QTextStream &s, const AbstractMetaClass *metaClass) const
+{
+ s << INDENT << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName() << "& self)";
+ s << " : " << metaClass->qualifiedCppName() << "(self)\n";
+ s << INDENT << "{\n";
+ s << INDENT << "}\n\n";
+}
+
+void HeaderGenerator::writeProtectedFieldAccessors(QTextStream &s, const AbstractMetaField *field) const
+{
+ const AbstractMetaType &metaType = field->type();
+ QString fieldType = metaType.cppSignature();
+ QString fieldName = field->enclosingClass()->qualifiedCppName() + QLatin1String("::") + field->name();
+
+ // Force use of pointer to return internal variable memory
+ bool useReference = (!metaType.isConstant() &&
+ !metaType.isEnum() &&
+ !metaType.isPrimitive() &&
+ metaType.indirections() == 0);
+
+
+ // Get function
+ s << INDENT << "inline " << fieldType
+ << (useReference ? " *" : " ")
+ << ' ' << protectedFieldGetterName(field) << "()"
+ << " { return "
+ << (useReference ? " &" : " ") << "this->" << fieldName << "; }\n";
+
+ // Set function
+ s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)"
+ << " { " << fieldName << " = value; }\n";
+}
+
+void HeaderGenerator::generateClass(QTextStream &s, const GeneratorContext &classContextIn)
+{
+ GeneratorContext classContext = classContextIn;
+ const AbstractMetaClass *metaClass = classContext.metaClass();
+ m_inheritedOverloads.clear();
+ Indentation indent(INDENT);
+
+ // write license comment
+ s << licenseComment();
+
+ QString wrapperName;
+ if (!classContext.forSmartPointer()) {
+ wrapperName = classContext.useWrapper()
+ ? classContext.wrapperName() : metaClass->qualifiedCppName();
+ } else {
+ wrapperName = classContext.smartPointerWrapperName();
+ }
+ QString outerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper();
+ QString innerHeaderGuard;
+
+ // Header
+ s << "#ifndef SBK_" << outerHeaderGuard << "_H\n";
+ s << "#define SBK_" << outerHeaderGuard << "_H\n\n";
+
+ if (!avoidProtectedHack())
+ s << "#define protected public\n\n";
+
+ //Includes
+ auto typeEntry = metaClass->typeEntry();
+ s << typeEntry->include() << '\n';
+ if (classContext.useWrapper() && !typeEntry->extraIncludes().isEmpty()) {
+ s << "\n// Extra includes\n";
+ for (const Include &inc : typeEntry->extraIncludes())
+ s << inc.toString() << '\n';
+ }
+
+ if (classContext.useWrapper() && usePySideExtensions() && metaClass->isQObject())
+ s << "namespace PySide { class DynamicQMetaObject; }\n\n";
+
+ while (classContext.useWrapper()) {
+ if (!innerHeaderGuard.isEmpty()) {
+ s << "# ifndef SBK_" << innerHeaderGuard << "_H\n";
+ s << "# define SBK_" << innerHeaderGuard << "_H\n\n";
+ s << "// Inherited base class:\n";
+ }
+
+ // Class
+ s << "class " << wrapperName;
+ s << " : public " << metaClass->qualifiedCppName();
+
+ s << "\n{\npublic:\n";
+
+ const AbstractMetaFunctionList &funcs = filterFunctions(metaClass);
+ int maxOverrides = 0;
+ for (AbstractMetaFunction *func : funcs) {
+ if ((func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0) {
+ writeFunction(s, func);
+ // PYSIDE-803: Build a boolean cache for unused overrides.
+ if (shouldWriteVirtualMethodNative(func))
+ maxOverrides++;
+ }
+ }
+ if (!maxOverrides)
+ maxOverrides = 1;
+
+ if (avoidProtectedHack() && metaClass->hasProtectedFields()) {
+ const AbstractMetaFieldList &fields = metaClass->fields();
+ for (AbstractMetaField *field : fields) {
+ if (!field->isProtected())
+ continue;
+ writeProtectedFieldAccessors(s, field);
+ }
+ }
+
+ //destructor
+ // PYSIDE-504: When C++ 11 is used, then the destructor must always be written.
+ // See generator.h for further reference.
+ if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor() || alwaysGenerateDestructor) {
+ s << INDENT;
+ if (avoidProtectedHack() && metaClass->hasPrivateDestructor())
+ s << "// C++11: need to declare (unimplemented) destructor because "
+ "the base class destructor is private.\n";
+ s << '~' << wrapperName << "();\n";
+ }
+
+ writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(),
+ TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode,
+ classContext);
+
+ if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
+ && usePySideExtensions() && metaClass->isQObject()) {
+ s << "public:\n";
+ s << INDENT << "int qt_metacall(QMetaObject::Call call, int id, void **args) override;\n";
+ s << INDENT << "void *qt_metacast(const char *_clname) override;\n";
+ }
+
+ if (!m_inheritedOverloads.isEmpty()) {
+ s << INDENT << "// Inherited overloads, because the using keyword sux\n";
+ writeInheritedOverloads(s);
+ m_inheritedOverloads.clear();
+ }
+
+ if (usePySideExtensions())
+ s << INDENT << "static void pysideInitQtMetaTypes();\n";
+
+ s << INDENT << "void resetPyMethodCache();\n";
+ s << "private:\n";
+ s << INDENT << "mutable bool m_PyMethodCache[" << maxOverrides << "];\n";
+
+ s << "};\n\n";
+ if (!innerHeaderGuard.isEmpty())
+ s << "# endif // SBK_" << innerHeaderGuard << "_H\n\n";
+
+ // PYSIDE-500: Use also includes for inherited wrapper classes, because
+ // without the protected hack, we sometimes need to cast inherited wrappers.
+ // But we don't use multiple include files. Instead, they are inserted as recursive
+ // headers. This keeps the file structure as simple as before the enhanced inheritance.
+ metaClass = metaClass->baseClass();
+ if (!metaClass || !avoidProtectedHack())
+ break;
+ classContext = contextForClass(metaClass);
+ if (!classContext.forSmartPointer()) {
+ wrapperName = classContext.useWrapper()
+ ? classContext.wrapperName() : metaClass->qualifiedCppName();
+ } else {
+ wrapperName = classContext.smartPointerWrapperName();
+ }
+ innerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper();
+ }
+
+ s << "#endif // SBK_" << outerHeaderGuard << "_H\n\n";
+}
+
+void HeaderGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction *func)
+{
+
+ // do not write copy ctors here.
+ if (!func->isPrivate() && func->functionType() == AbstractMetaFunction::CopyConstructorFunction) {
+ writeCopyCtor(s, func->ownerClass());
+ return;
+ }
+ if (func->isUserAdded())
+ return;
+
+ if (avoidProtectedHack() && func->isProtected() && !func->isConstructor() && !func->isOperatorOverload()) {
+ s << INDENT << "inline " << (func->isStatic() ? "static " : "");
+ s << functionSignature(func, QString(), QLatin1String("_protected"), Generator::EnumAsInts|Generator::OriginalTypeDescription)
+ << " { ";
+ if (!func->isVoid())
+ s << "return ";
+ if (!func->isAbstract())
+ s << func->ownerClass()->qualifiedCppName() << "::";
+ s << func->originalName() << '(';
+ QStringList args;
+ const AbstractMetaArgumentList &arguments = func->arguments();
+ for (const AbstractMetaArgument &arg : arguments) {
+ QString argName = arg.name();
+ const TypeEntry *enumTypeEntry = nullptr;
+ if (arg.type().isFlags())
+ enumTypeEntry = static_cast<const FlagsTypeEntry *>(arg.type().typeEntry())->originator();
+ else if (arg.type().isEnum())
+ enumTypeEntry = arg.type().typeEntry();
+ if (enumTypeEntry)
+ argName = QString::fromLatin1("%1(%2)").arg(arg.type().cppSignature(), argName);
+ args << argName;
+ }
+ s << args.join(QLatin1String(", ")) << ')';
+ s << "; }\n";
+ }
+
+ // pure virtual functions need a default implementation
+ const bool notAbstract = !func->isAbstract();
+ if ((func->isPrivate() && notAbstract && !visibilityModifiedToPrivate(func))
+ || (func->isModifiedRemoved() && notAbstract))
+ return;
+
+ if (avoidProtectedHack() && func->ownerClass()->hasPrivateDestructor()
+ && (func->isAbstract() || func->isVirtual()))
+ return;
+
+ if (func->isConstructor() || func->isAbstract() || func->isVirtual()) {
+ s << INDENT;
+ Options virtualOption = Generator::OriginalTypeDescription;
+
+ const bool virtualFunc = func->isVirtual() || func->isAbstract();
+ if (!virtualFunc && !func->hasSignatureModifications())
+ virtualOption = Generator::NoOption;
+
+ s << functionSignature(func, QString(), QString(), virtualOption);
+
+ if (virtualFunc)
+ s << " override";
+ s << ";\n";
+ // Check if this method hide other methods in base classes
+ const AbstractMetaFunctionList &ownerFuncs = func->ownerClass()->functions();
+ for (const AbstractMetaFunction *f : ownerFuncs) {
+ if (f != func
+ && !f->isConstructor()
+ && !f->isPrivate()
+ && !f->isVirtual()
+ && !f->isAbstract()
+ && !f->isStatic()
+ && f->name() == func->name()) {
+ m_inheritedOverloads << f;
+ }
+ }
+
+ // TODO: when modified an abstract method ceases to be virtual but stays abstract
+ //if (func->isModifiedRemoved() && func->isAbstract()) {
+ //}
+ }
+}
+
+static void _writeTypeIndexValue(QTextStream &s, const QString &variableName,
+ int typeIndex)
+{
+ s << " ";
+ s.setFieldWidth(56);
+ s << variableName;
+ s.setFieldWidth(0);
+ s << " = " << typeIndex;
+}
+
+static inline void _writeTypeIndexValueLine(QTextStream &s,
+ const QString &variableName,
+ int typeIndex)
+{
+ _writeTypeIndexValue(s, variableName, typeIndex);
+ s << ",\n";
+}
+
+void HeaderGenerator::writeTypeIndexValueLine(QTextStream &s, const TypeEntry *typeEntry)
+{
+ if (!typeEntry || !typeEntry->generateCode())
+ return;
+ s.setFieldAlignment(QTextStream::AlignLeft);
+ const int typeIndex = typeEntry->sbkIndex();
+ _writeTypeIndexValueLine(s, getTypeIndexVariableName(typeEntry), typeIndex);
+ if (typeEntry->isComplex()) {
+ const auto *cType = static_cast<const ComplexTypeEntry *>(typeEntry);
+ if (cType->baseContainerType()) {
+ const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), cType);
+ if (metaClass->templateBaseClass())
+ _writeTypeIndexValueLine(s, getTypeIndexVariableName(metaClass, true), typeIndex);
+ }
+ }
+ if (typeEntry->isEnum()) {
+ auto ete = static_cast<const EnumTypeEntry *>(typeEntry);
+ if (ete->flags())
+ writeTypeIndexValueLine(s, ete->flags());
+ }
+}
+
+void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMetaClass *metaClass)
+{
+ auto typeEntry = metaClass->typeEntry();
+ if (!typeEntry->generateCode())
+ return;
+ // enum indices are required for invisible namespaces as well.
+ for (const AbstractMetaEnum *metaEnum : metaClass->enums()) {
+ if (!metaEnum->isPrivate())
+ writeTypeIndexValueLine(s, metaEnum->typeEntry());
+ }
+ if (NamespaceTypeEntry::isVisibleScope(typeEntry))
+ writeTypeIndexValueLine(s, metaClass->typeEntry());
+}
+
+// Format the typedefs for the typedef entries to be generated
+static void formatTypeDefEntries(QTextStream &s)
+{
+ QVector<const TypedefEntry *> entries;
+ const auto typeDbEntries = TypeDatabase::instance()->typedefEntries();
+ for (auto it = typeDbEntries.cbegin(), end = typeDbEntries.cend(); it != end; ++it) {
+ if (it.value()->generateCode() != 0)
+ entries.append(it.value());
+ }
+ if (entries.isEmpty())
+ return;
+ s << "\n// typedef entries\n";
+ for (const auto e : entries) {
+ const QString name = e->qualifiedCppName();
+ // Fixme: simplify by using nested namespaces in C++ 17.
+ const auto components = QStringView{name}.split(u"::");
+ const int nameSpaceCount = components.size() - 1;
+ for (int n = 0; n < nameSpaceCount; ++n)
+ s << "namespace " << components.at(n) << " {\n";
+ s << "using " << components.constLast() << " = " << e->sourceType() << ";\n";
+ for (int n = 0; n < nameSpaceCount; ++n)
+ s << "}\n";
+ }
+ s << '\n';
+}
+
+
+bool HeaderGenerator::finishGeneration()
+{
+ // Generate the main header for this module.
+ // This header should be included by binding modules
+ // extendind on top of this one.
+ QSet<Include> includes;
+ QString macros;
+ QTextStream macrosStream(&macros);
+ QString sbkTypeFunctions;
+ QTextStream typeFunctions(&sbkTypeFunctions);
+ QString protectedEnumSurrogates;
+ QTextStream protEnumsSurrogates(&protectedEnumSurrogates);
+
+ const auto snips = TypeDatabase::instance()->defaultTypeSystemType()->codeSnips();
+ if (!snips.isEmpty()) {
+ writeCodeSnips(macrosStream, snips, TypeSystem::CodeSnipPositionDeclaration,
+ TypeSystem::TargetLangCode);
+ }
+
+ Indentation indent(INDENT);
+
+ macrosStream << "// Type indices\nenum : int {\n";
+ AbstractMetaClassList classList = classes();
+
+ std::sort(classList.begin(), classList.end(), [](AbstractMetaClass *a, AbstractMetaClass *b) {
+ return a->typeEntry()->sbkIndex() < b->typeEntry()->sbkIndex();
+ });
+
+ for (const AbstractMetaClass *metaClass : classList)
+ writeTypeIndexValueLines(macrosStream, metaClass);
+
+ for (const AbstractMetaEnum *metaEnum : globalEnums())
+ writeTypeIndexValueLine(macrosStream, metaEnum->typeEntry());
+
+ // Write the smart pointer define indexes.
+ int smartPointerCountIndex = getMaxTypeIndex();
+ int smartPointerCount = 0;
+ const QVector<AbstractMetaType> &instantiatedSmartPtrs = instantiatedSmartPointers();
+ for (const AbstractMetaType &metaType : instantiatedSmartPtrs) {
+ QString indexName = getTypeIndexVariableName(metaType);
+ _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex);
+ macrosStream << ", // " << metaType.cppSignature() << Qt::endl;
+ // Add a the same value for const pointees (shared_ptr<const Foo>).
+ const auto ptrName = metaType.typeEntry()->entryName();
+ int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive);
+ if (pos >= 0) {
+ indexName.insert(pos + ptrName.size() + 1, QLatin1String("CONST"));
+ _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex);
+ macrosStream << ", // (const)\n";
+ }
+ ++smartPointerCountIndex;
+ ++smartPointerCount;
+ }
+
+ _writeTypeIndexValue(macrosStream,
+ QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT"),
+ getMaxTypeIndex() + smartPointerCount);
+ macrosStream << "\n};\n";
+
+ macrosStream << "// This variable stores all Python types exported by this module.\n";
+ macrosStream << "extern PyTypeObject **" << cppApiVariableName() << ";\n\n";
+ macrosStream << "// This variable stores the Python module object exported by this module.\n";
+ macrosStream << "extern PyObject *" << pythonModuleObjectName() << ";\n\n";
+ macrosStream << "// This variable stores all type converters exported by this module.\n";
+ macrosStream << "extern SbkConverter **" << convertersVariableName() << ";\n\n";
+
+ // TODO-CONVERTER ------------------------------------------------------------------------------
+ // Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex().
+ macrosStream << "// Converter indices\nenum : int {\n";
+ const PrimitiveTypeEntryList &primitives = primitiveTypes();
+ int pCount = 0;
+ for (const PrimitiveTypeEntry *ptype : primitives) {
+ /* Note: do not generate indices for typedef'd primitive types
+ * as they'll use the primitive type converters instead, so we
+ * don't need to create any other.
+ */
+ if (!ptype->generateCode() || !ptype->customConversion())
+ continue;
+
+ _writeTypeIndexValueLine(macrosStream, getTypeIndexVariableName(ptype), pCount++);
+ }
+
+ const QVector<AbstractMetaType> &containers = instantiatedContainers();
+ for (const AbstractMetaType &container : containers) {
+ _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount);
+ macrosStream << ", // " << container.cppSignature() << Qt::endl;
+ pCount++;
+ }
+
+ // Because on win32 the compiler will not accept a zero length array.
+ if (pCount == 0)
+ pCount++;
+ _writeTypeIndexValue(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT")
+ .arg(moduleName()), pCount);
+ macrosStream << "\n};\n";
+
+ formatTypeDefEntries(macrosStream);
+
+ // TODO-CONVERTER ------------------------------------------------------------------------------
+
+ macrosStream << "// Macros for type check\n";
+
+ if (usePySideExtensions()) {
+ typeFunctions << "QT_WARNING_PUSH\n";
+ typeFunctions << "QT_WARNING_DISABLE_DEPRECATED\n";
+ }
+ for (const AbstractMetaEnum *cppEnum : globalEnums()) {
+ if (!cppEnum->isAnonymous()) {
+ includes << cppEnum->typeEntry()->include();
+ writeSbkTypeFunction(typeFunctions, cppEnum);
+ }
+ }
+
+ for (AbstractMetaClass *metaClass : classList) {
+ if (!shouldGenerate(metaClass))
+ continue;
+
+ //Includes
+ const TypeEntry *classType = metaClass->typeEntry();
+ includes << classType->include();
+
+ for (const AbstractMetaEnum *cppEnum : metaClass->enums()) {
+ if (cppEnum->isAnonymous() || cppEnum->isPrivate())
+ continue;
+ EnumTypeEntry *enumType = cppEnum->typeEntry();
+ includes << enumType->include();
+ writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
+ writeSbkTypeFunction(typeFunctions, cppEnum);
+ }
+
+ if (!metaClass->isNamespace())
+ writeSbkTypeFunction(typeFunctions, metaClass);
+ }
+
+ for (const AbstractMetaType &metaType : instantiatedSmartPtrs) {
+ const TypeEntry *classType = metaType.typeEntry();
+ includes << classType->include();
+ writeSbkTypeFunction(typeFunctions, metaType);
+ }
+ if (usePySideExtensions())
+ typeFunctions << "QT_WARNING_POP\n";
+
+ QString moduleHeaderFileName(outputDirectory()
+ + QDir::separator() + subDirectoryForPackage(packageName())
+ + QDir::separator() + getModuleHeaderFileName());
+
+ QString includeShield(QLatin1String("SBK_") + moduleName().toUpper() + QLatin1String("_PYTHON_H"));
+
+ FileOut file(moduleHeaderFileName);
+ QTextStream &s = file.stream;
+ // write license comment
+ s << licenseComment() << Qt::endl << Qt::endl;
+
+ s << "#ifndef " << includeShield << Qt::endl;
+ s << "#define " << includeShield << Qt::endl << Qt::endl;
+ if (!avoidProtectedHack()) {
+ s << "//workaround to access protected functions\n";
+ s << "#define protected public\n\n";
+ }
+
+ s << "#include <sbkpython.h>\n";
+ s << "#include <sbkconverter.h>\n";
+
+ QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports();
+ if (!requiredTargetImports.isEmpty()) {
+ s << "// Module Includes\n";
+ for (const QString &requiredModule : qAsConst(requiredTargetImports))
+ s << "#include <" << getModuleHeaderFileName(requiredModule) << ">\n";
+ s << Qt::endl;
+ }
+
+ s << "// Bound library includes\n";
+ for (const Include &include : qAsConst(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 << Qt::endl;
+ }
+
+ if (!containerTypes().isEmpty()) {
+ s << "// Conversion Includes - Container Types\n";
+ const ContainerTypeEntryList &containerTypeList = containerTypes();
+ for (const ContainerTypeEntry *ctype : containerTypeList)
+ s << ctype->include();
+ s << Qt::endl;
+ }
+
+ s << macros << Qt::endl;
+
+ if (!protectedEnumSurrogates.isEmpty()) {
+ s << "// Protected enum surrogates\n";
+ s << protectedEnumSurrogates << Qt::endl;
+ }
+
+ s << "namespace Shiboken\n{\n\n";
+
+ s << "// PyType functions, to get the PyObjectType for a type T\n";
+ s << sbkTypeFunctions << Qt::endl;
+
+ s << "} // namespace Shiboken\n\n";
+
+ s << "#endif // " << includeShield << Qt::endl << Qt::endl;
+
+ return file.done() != FileOut::Failure;
+}
+
+void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream &s, const AbstractMetaEnum *cppEnum)
+{
+ if (avoidProtectedHack() && cppEnum->isProtected())
+ s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};\n";
+}
+
+void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaEnum *cppEnum)
+{
+ QString enumName;
+ if (avoidProtectedHack() && cppEnum->isProtected()) {
+ enumName = protectedEnumSurrogateName(cppEnum);
+ } else {
+ enumName = cppEnum->name();
+ if (cppEnum->enclosingClass())
+ enumName = cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::") + enumName;
+ }
+
+ s << "template<> inline PyTypeObject *SbkType< ::" << enumName << " >() ";
+ s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n";
+
+ FlagsTypeEntry *flag = cppEnum->typeEntry()->flags();
+ if (flag) {
+ s << "template<> inline PyTypeObject *SbkType< ::" << flag->name() << " >() "
+ << "{ return " << cpythonTypeNameExt(flag) << "; }\n";
+ }
+}
+
+void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaClass *cppClass)
+{
+ s << "template<> inline PyTypeObject *SbkType< ::" << cppClass->qualifiedCppName() << " >() "
+ << "{ return reinterpret_cast<PyTypeObject *>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n";
+}
+
+void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaType &metaType)
+{
+ s << "template<> inline PyTypeObject *SbkType< ::" << metaType.cppSignature() << " >() "
+ << "{ return reinterpret_cast<PyTypeObject *>(" << cpythonTypeNameExt(metaType) << "); }\n";
+}
+
+void HeaderGenerator::writeInheritedOverloads(QTextStream &s)
+{
+ for (const AbstractMetaFunction *func : qAsConst(m_inheritedOverloads)) {
+ s << INDENT << "inline ";
+ s << functionSignature(func, QString(), QString(), Generator::EnumAsInts|Generator::OriginalTypeDescription)
+ << " { ";
+ if (!func->isVoid())
+ s << "return ";
+ s << func->ownerClass()->qualifiedCppName() << "::" << func->originalName() << '(';
+ QStringList args;
+ const AbstractMetaArgumentList &arguments = func->arguments();
+ for (const AbstractMetaArgument &arg : arguments) {
+ QString argName = arg.name();
+ const TypeEntry *enumTypeEntry = nullptr;
+ if (arg.type().isFlags())
+ enumTypeEntry = static_cast<const FlagsTypeEntry *>(arg.type().typeEntry())->originator();
+ else if (arg.type().isEnum())
+ enumTypeEntry = arg.type().typeEntry();
+ if (enumTypeEntry)
+ argName = arg.type().cppSignature() + QLatin1Char('(') + argName + QLatin1Char(')');
+ args << argName;
+ }
+ s << args.join(QLatin1String(", ")) << ')';
+ s << "; }\n";
+ }
+}