diff options
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/headergenerator.cpp')
-rw-r--r-- | sources/shiboken2/generator/shiboken2/headergenerator.cpp | 232 |
1 files changed, 132 insertions, 100 deletions
diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index e47c37523..107e28a4a 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -45,7 +45,7 @@ QString HeaderGenerator::fileNameSuffix() const return QLatin1String("_wrapper.h"); } -QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const +QString HeaderGenerator::fileNameForContext(const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); if (!context.forSmartPointer()) { @@ -61,9 +61,9 @@ QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const void HeaderGenerator::writeCopyCtor(QTextStream &s, const AbstractMetaClass *metaClass) const { s << INDENT << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName() << "& self)"; - s << " : " << metaClass->qualifiedCppName() << "(self)" << endl; - s << INDENT << "{" << endl; - s << INDENT << "}" << endl << endl; + s << " : " << metaClass->qualifiedCppName() << "(self)\n"; + s << INDENT << "{\n"; + s << INDENT << "}\n\n"; } void HeaderGenerator::writeProtectedFieldAccessors(QTextStream &s, const AbstractMetaField *field) const @@ -84,18 +84,17 @@ void HeaderGenerator::writeProtectedFieldAccessors(QTextStream &s, const Abstrac << (useReference ? " *" : " ") << ' ' << protectedFieldGetterName(field) << "()" << " { return " - << (useReference ? " &" : " ") << "this->" << fieldName << "; }" << endl; + << (useReference ? " &" : " ") << "this->" << fieldName << "; }\n"; // Set function s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)" - << " { " << fieldName << " = value; }" << endl; + << " { " << fieldName << " = value; }\n"; } -void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +void HeaderGenerator::generateClass(QTextStream &s, const GeneratorContext &classContextIn) { - AbstractMetaClass *metaClass = classContext.metaClass(); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "Generating header for " << metaClass->fullName(); + GeneratorContext classContext = classContextIn; + const AbstractMetaClass *metaClass = classContext.metaClass(); m_inheritedOverloads.clear(); Indentation indent(INDENT); @@ -104,45 +103,58 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte QString wrapperName; if (!classContext.forSmartPointer()) { - wrapperName = HeaderGenerator::wrapperName(metaClass); + wrapperName = classContext.useWrapper() + ? classContext.wrapperName() : metaClass->qualifiedCppName(); } else { - wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); + wrapperName = classContext.smartPointerWrapperName(); } QString outerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper(); QString innerHeaderGuard; // Header - s << "#ifndef SBK_" << outerHeaderGuard << "_H" << endl; - s << "#define SBK_" << outerHeaderGuard << "_H" << endl << endl; + s << "#ifndef SBK_" << outerHeaderGuard << "_H\n"; + s << "#define SBK_" << outerHeaderGuard << "_H\n\n"; if (!avoidProtectedHack()) - s << "#define protected public" << endl << endl; + s << "#define protected public\n\n"; //Includes - s << metaClass->typeEntry()->include() << endl; + 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 (shouldGenerateCppWrapper(metaClass) && - usePySideExtensions() && metaClass->isQObject()) + if (classContext.useWrapper() && usePySideExtensions() && metaClass->isQObject()) s << "namespace PySide { class DynamicQMetaObject; }\n\n"; - while (shouldGenerateCppWrapper(metaClass)) { + while (classContext.useWrapper()) { if (!innerHeaderGuard.isEmpty()) { - s << "# ifndef SBK_" << innerHeaderGuard << "_H" << endl; - s << "# define SBK_" << innerHeaderGuard << "_H" << endl << endl; - s << "// Inherited base class:" << endl; + 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 << endl << '{' << endl << "public:" << endl; + s << "\n{\npublic:\n"; const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); + int maxOverrides = 0; for (AbstractMetaFunction *func : funcs) { - if ((func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0) + 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(); @@ -160,31 +172,37 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte s << INDENT; if (avoidProtectedHack() && metaClass->hasPrivateDestructor()) s << "// C++11: need to declare (unimplemented) destructor because " - "the base class destructor is private." << endl; - s << '~' << wrapperName << "();" << endl; + "the base class destructor is private.\n"; + s << '~' << wrapperName << "();\n"; } - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode); + 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;" << endl; - s << INDENT << "void *qt_metacast(const char *_clname) override;" << endl; + 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" << endl; + s << INDENT << "// Inherited overloads, because the using keyword sux\n"; writeInheritedOverloads(s); m_inheritedOverloads.clear(); } if (usePySideExtensions()) - s << INDENT << "static void pysideInitQtMetaTypes();" << endl; + s << INDENT << "static void pysideInitQtMetaTypes();\n"; + + s << INDENT << "void resetPyMethodCache();\n"; + s << "private:\n"; + s << INDENT << "mutable bool m_PyMethodCache[" << maxOverrides << "];\n"; - s << "};" << endl << endl; + s << "};\n\n"; if (!innerHeaderGuard.isEmpty()) - s << "# endif // SBK_" << innerHeaderGuard << "_H" << endl << endl; + 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. @@ -193,16 +211,17 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte metaClass = metaClass->baseClass(); if (!metaClass || !avoidProtectedHack()) break; - classContext = GeneratorContext(metaClass); + classContext = contextForClass(metaClass); if (!classContext.forSmartPointer()) { - wrapperName = HeaderGenerator::wrapperName(metaClass); + wrapperName = classContext.useWrapper() + ? classContext.wrapperName() : metaClass->qualifiedCppName(); } else { - wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); + wrapperName = classContext.smartPointerWrapperName(); } innerHeaderGuard = getFilteredCppSignatureString(wrapperName).toUpper(); } - s << "#endif // SBK_" << outerHeaderGuard << "_H" << endl << endl; + s << "#endif // SBK_" << outerHeaderGuard << "_H\n\n"; } void HeaderGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction *func) @@ -220,7 +239,8 @@ void HeaderGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction * s << INDENT << "inline " << (func->isStatic() ? "static " : ""); s << functionSignature(func, QString(), QLatin1String("_protected"), Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { "; - s << (func->type() ? "return " : ""); + if (!func->isVoid()) + s << "return "; if (!func->isAbstract()) s << func->ownerClass()->qualifiedCppName() << "::"; s << func->originalName() << '('; @@ -238,7 +258,7 @@ void HeaderGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction * args << argName; } s << args.join(QLatin1String(", ")) << ')'; - s << "; }" << endl; + s << "; }\n"; } // pure virtual functions need a default implementation @@ -263,7 +283,7 @@ void HeaderGenerator::writeFunction(QTextStream &s, const AbstractMetaFunction * if (virtualFunc) s << " override"; - s << ';' << endl; + s << ";\n"; // Check if this method hide other methods in base classes const AbstractMetaFunctionList &ownerFuncs = func->ownerClass()->functions(); for (const AbstractMetaFunction *f : ownerFuncs) { @@ -326,15 +346,16 @@ void HeaderGenerator::writeTypeIndexValueLine(QTextStream &s, const TypeEntry *t void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMetaClass *metaClass) { - if (!metaClass->typeEntry()->generateCode()) + auto typeEntry = metaClass->typeEntry(); + if (!typeEntry->generateCode()) return; - writeTypeIndexValueLine(s, metaClass->typeEntry()); - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->isPrivate()) - continue; - writeTypeIndexValueLine(s, metaEnum->typeEntry()); + // 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 @@ -377,22 +398,25 @@ bool HeaderGenerator::finishGeneration() 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"; - AbstractMetaEnumList globalEnums = this->globalEnums(); 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) { + for (const AbstractMetaClass *metaClass : classList) writeTypeIndexValueLines(macrosStream, metaClass); - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); - } - for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) + for (const AbstractMetaEnum *metaEnum : globalEnums()) writeTypeIndexValueLine(macrosStream, metaEnum->typeEntry()); // Write the smart pointer define indexes. @@ -400,9 +424,17 @@ bool HeaderGenerator::finishGeneration() int smartPointerCount = 0; const QVector<const AbstractMetaType *> &instantiatedSmartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType), - smartPointerCountIndex); - macrosStream << ", // " << metaType->cppSignature() << endl; + 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; } @@ -412,12 +444,12 @@ bool HeaderGenerator::finishGeneration() getMaxTypeIndex() + smartPointerCount); macrosStream << "\n};\n"; - macrosStream << "// This variable stores all Python types exported by this module." << endl; - macrosStream << "extern PyTypeObject **" << cppApiVariableName() << ';' << endl << endl; - macrosStream << "// This variable stores the Python module object exported by this module." << endl; - macrosStream << "extern PyObject *" << pythonModuleObjectName() << ';' << endl << endl; - macrosStream << "// This variable stores all type converters exported by this module." << endl; - macrosStream << "extern SbkConverter **" << convertersVariableName() << ';' << endl << endl; + 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(). @@ -438,7 +470,7 @@ bool HeaderGenerator::finishGeneration() const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); for (const AbstractMetaType *container : containers) { _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(container), pCount); - macrosStream << ", // " << container->cppSignature() << endl; + macrosStream << ", // " << container->cppSignature() << Qt::endl; pCount++; } @@ -453,18 +485,17 @@ bool HeaderGenerator::finishGeneration() // TODO-CONVERTER ------------------------------------------------------------------------------ - macrosStream << "// Macros for type check" << endl; + macrosStream << "// Macros for type check\n"; if (usePySideExtensions()) { - typeFunctions << "QT_WARNING_PUSH" << endl; - typeFunctions << "QT_WARNING_DISABLE_DEPRECATED" << endl; + typeFunctions << "QT_WARNING_PUSH\n"; + typeFunctions << "QT_WARNING_DISABLE_DEPRECATED\n"; } - for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - includes << cppEnum->typeEntry()->include(); - writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); - writeSbkTypeFunction(typeFunctions, cppEnum); + for (const AbstractMetaEnum *cppEnum : globalEnums()) { + if (!cppEnum->isAnonymous()) { + includes << cppEnum->typeEntry()->include(); + writeSbkTypeFunction(typeFunctions, cppEnum); + } } for (AbstractMetaClass *metaClass : classList) { @@ -475,8 +506,7 @@ bool HeaderGenerator::finishGeneration() const TypeEntry *classType = metaClass->typeEntry(); includes << classType->include(); - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *cppEnum : enums) { + for (const AbstractMetaEnum *cppEnum : metaClass->enums()) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; EnumTypeEntry *enumType = cppEnum->typeEntry(); @@ -495,7 +525,7 @@ bool HeaderGenerator::finishGeneration() writeSbkTypeFunction(typeFunctions, metaType); } if (usePySideExtensions()) - typeFunctions << "QT_WARNING_POP" << endl; + typeFunctions << "QT_WARNING_POP\n"; QString moduleHeaderFileName(outputDirectory() + QDir::separator() + subDirectoryForPackage(packageName()) @@ -506,61 +536,61 @@ bool HeaderGenerator::finishGeneration() FileOut file(moduleHeaderFileName); QTextStream &s = file.stream; // write license comment - s << licenseComment() << endl << endl; + s << licenseComment() << Qt::endl << Qt::endl; - s << "#ifndef " << includeShield << endl; - s << "#define " << includeShield << endl<< endl; + s << "#ifndef " << includeShield << Qt::endl; + s << "#define " << includeShield << Qt::endl << Qt::endl; if (!avoidProtectedHack()) { - s << "//workaround to access protected functions" << endl; - s << "#define protected public" << endl << endl; + s << "//workaround to access protected functions\n"; + s << "#define protected public\n\n"; } - s << "#include <sbkpython.h>" << endl; - s << "#include <sbkconverter.h>" << endl; + s << "#include <sbkpython.h>\n"; + s << "#include <sbkconverter.h>\n"; QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports(); if (!requiredTargetImports.isEmpty()) { - s << "// Module Includes" << endl; + s << "// Module Includes\n"; for (const QString &requiredModule : qAsConst(requiredTargetImports)) - s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl; - s << endl; + s << "#include <" << getModuleHeaderFileName(requiredModule) << ">\n"; + s << Qt::endl; } - s << "// Binded library includes" << endl; + s << "// Bound library includes\n"; for (const Include &include : qAsConst(includes)) s << include; if (!primitiveTypes().isEmpty()) { - s << "// Conversion Includes - Primitive Types" << endl; + s << "// Conversion Includes - Primitive Types\n"; const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); for (const PrimitiveTypeEntry *ptype : primitiveTypeList) s << ptype->include(); - s << endl; + s << Qt::endl; } if (!containerTypes().isEmpty()) { - s << "// Conversion Includes - Container Types" << endl; + s << "// Conversion Includes - Container Types\n"; const ContainerTypeEntryList &containerTypeList = containerTypes(); for (const ContainerTypeEntry *ctype : containerTypeList) s << ctype->include(); - s << endl; + s << Qt::endl; } - s << macros << endl; + s << macros << Qt::endl; if (!protectedEnumSurrogates.isEmpty()) { - s << "// Protected enum surrogates" << endl; - s << protectedEnumSurrogates << endl; + s << "// Protected enum surrogates\n"; + s << protectedEnumSurrogates << Qt::endl; } - s << "namespace Shiboken" << endl << '{' << endl << endl; + s << "namespace Shiboken\n{\n\n"; s << "// PyType functions, to get the PyObjectType for a type T\n"; - s << sbkTypeFunctions << endl; + s << sbkTypeFunctions << Qt::endl; - s << "} // namespace Shiboken" << endl << endl; + s << "} // namespace Shiboken\n\n"; - s << "#endif // " << includeShield << endl << endl; + s << "#endif // " << includeShield << Qt::endl << Qt::endl; return file.done() != FileOut::Failure; } @@ -568,7 +598,7 @@ bool HeaderGenerator::finishGeneration() void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream &s, const AbstractMetaEnum *cppEnum) { if (avoidProtectedHack() && cppEnum->isProtected()) - s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};" << endl; + s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};\n"; } void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaEnum *cppEnum) @@ -608,8 +638,10 @@ void HeaderGenerator::writeInheritedOverloads(QTextStream &s) { for (const AbstractMetaFunction *func : qAsConst(m_inheritedOverloads)) { s << INDENT << "inline "; - s << functionSignature(func, QString(), QString(), Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { "; - s << (func->type() ? "return " : ""); + 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(); @@ -625,6 +657,6 @@ void HeaderGenerator::writeInheritedOverloads(QTextStream &s) args << argName; } s << args.join(QLatin1String(", ")) << ')'; - s << "; }" << endl; + s << "; }\n"; } } |