aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/cppgenerator.cpp')
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp3400
1 files changed, 1927 insertions, 1473 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 5460fd7c7..786308023 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -29,10 +29,12 @@
#include <memory>
#include "cppgenerator.h"
+#include "ctypenames.h"
#include "fileout.h"
#include "overloaddata.h"
#include <abstractmetalang.h>
#include <messages.h>
+#include <propertyspec.h>
#include <reporthandler.h>
#include <typedatabase.h>
@@ -44,8 +46,7 @@
#include <QMetaType>
#include <algorithm>
-
-#include <algorithm>
+#include <cstring>
static const char CPP_ARG0[] = "cppArg0";
@@ -84,10 +85,9 @@ static const char *typeNameOf(const T &t)
inline AbstractMetaType *getTypeWithoutContainer(AbstractMetaType *arg)
{
if (arg && arg->typeEntry()->isContainer()) {
- AbstractMetaTypeList lst = arg->instantiations();
// only support containers with 1 type
- if (lst.size() == 1)
- return lst[0];
+ if (arg->instantiations().size() == 1)
+ return arg->instantiations().constFirst();
}
return arg;
}
@@ -151,16 +151,16 @@ CppGenerator::CppGenerator()
QLatin1String("PyObject*")});
m_sequenceProtocol.insert(QLatin1String("__setitem__"),
{QLatin1String("PyObject *self, Py_ssize_t _i, PyObject *_value"),
- QLatin1String("int")});
+ intT()});
m_sequenceProtocol.insert(QLatin1String("__getslice__"),
{QLatin1String("PyObject *self, Py_ssize_t _i1, Py_ssize_t _i2"),
QLatin1String("PyObject*")});
m_sequenceProtocol.insert(QLatin1String("__setslice__"),
{QLatin1String("PyObject *self, Py_ssize_t _i1, Py_ssize_t _i2, PyObject *_value"),
- QLatin1String("int")});
+ intT()});
m_sequenceProtocol.insert(QLatin1String("__contains__"),
{QLatin1String("PyObject *self, PyObject *_value"),
- QLatin1String("int")});
+ intT()});
m_sequenceProtocol.insert(QLatin1String("__concat__"),
{QLatin1String("PyObject *self, PyObject *_other"),
QLatin1String("PyObject*")});
@@ -183,7 +183,7 @@ CppGenerator::CppGenerator()
QLatin1String("PyObject*")});
m_mappingProtocol.insert(QLatin1String("__msetitem__"),
{QLatin1String("PyObject *self, PyObject *_key, PyObject *_value"),
- QLatin1String("int")});
+ intT()});
// Sequence protocol structure members names
m_mpFuncs.insert(QLatin1String("__mlen__"), QLatin1String("mp_length"));
@@ -196,7 +196,7 @@ QString CppGenerator::fileNameSuffix() const
return QLatin1String("_wrapper.cpp");
}
-QString CppGenerator::fileNameForContext(GeneratorContext &context) const
+QString CppGenerator::fileNameForContext(const GeneratorContext &context) const
{
const AbstractMetaClass *metaClass = context.metaClass();
if (!context.forSmartPointer()) {
@@ -246,7 +246,7 @@ const AbstractMetaFunction *CppGenerator::boolCast(const AbstractMetaClass *meta
return nullptr;
// TODO: This could be configurable someday
const AbstractMetaFunction *func = metaClass->findFunction(QLatin1String("isNull"));
- if (!func || !func->type() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic())
+ if (!func || func->isVoid() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic())
return nullptr;
auto pte = static_cast<const PrimitiveTypeEntry *>(func->type()->typeEntry());
while (pte->referencedTypeEntry())
@@ -255,6 +255,15 @@ const AbstractMetaFunction *CppGenerator::boolCast(const AbstractMetaClass *meta
&& func->arguments().isEmpty() ? func : nullptr;
}
+const AbstractMetaType *CppGenerator::findSmartPointerInstantiation(const TypeEntry *entry) const
+{
+ for (auto i : instantiatedSmartPointers()) {
+ if (i->instantiations().at(0)->typeEntry() == entry)
+ return i;
+ }
+ return nullptr;
+}
+
using FunctionGroupMap = QMap<QString, AbstractMetaFunctionList>;
// Prevent ELF symbol qt_version_tag from being generated into the source
@@ -288,44 +297,75 @@ static inline bool canGenerateFieldSetter(const AbstractMetaField *field)
return !type->isConstant() || isPointerToConst(type);
}
+static bool isStdSetterName(QString setterName, QString propertyName)
+{
+ return setterName.size() == propertyName.size() + 3
+ && setterName.startsWith(QLatin1String("set"))
+ && setterName.endsWith(propertyName.rightRef(propertyName.size() - 1))
+ && setterName.at(3) == propertyName.at(0).toUpper();
+}
+
+static QString buildPropertyString(QPropertySpec *spec)
+{
+ QString text;
+ text += QLatin1Char('"');
+ text += spec->name();
+ text += QLatin1Char(':');
+
+ if (spec->read() != spec->name())
+ text += spec->read();
+
+ if (!spec->write().isEmpty()) {
+ text += QLatin1Char(':');
+ if (!isStdSetterName(spec->write(), spec->name()))
+ text += spec->write();
+ }
+
+ text += QLatin1Char('"');
+ return text;
+}
+
+static void writePyGetSetDefEntry(QTextStream &s, const QString &name,
+ const QString &getFunc, const QString &setFunc)
+{
+ s << "{const_cast<char *>(\"" << name << "\"), " << getFunc << ", "
+ << (setFunc.isEmpty() ? QLatin1String(NULL_PTR) : setFunc) << "},\n";
+}
+
/*!
Function used to write the class generated binding code on the buffer
\param s the output buffer
\param metaClass the pointer to metaclass information
*/
-void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
+void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classContext)
{
- AbstractMetaClass *metaClass = classContext.metaClass();
- if (ReportHandler::isDebug(ReportHandler::SparseDebug))
- qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName();
+ const AbstractMetaClass *metaClass = classContext.metaClass();
// write license comment
- s << licenseComment() << endl;
+ s << licenseComment() << Qt::endl;
if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) {
- 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";
}
// headers
- s << "// default includes" << endl;
- s << "#include <shiboken.h>" << endl;
+ s << "// default includes\n";
+ s << "#include <shiboken.h>\n";
if (usePySideExtensions()) {
s << includeQDebug;
- s << "#include <pysidesignal.h>" << endl;
- s << "#include <pysideproperty.h>" << endl;
- s << "#include <pyside.h>" << endl;
- s << "#include <destroylistener.h>" << endl;
- s << "#include <qapp_macro.h>" << endl;
- s << endl;
- s << "QT_WARNING_DISABLE_DEPRECATED" << endl;
- s << endl;
+ s << "#include <pysidesignal.h>\n"
+ << "#include <pysideproperty.h>\n"
+ << "#include <pyside.h>\n"
+ << "#include <pysideqenum.h>\n"
+ << "#include <feature_select.h>\n"
+ << "QT_WARNING_DISABLE_DEPRECATED\n\n";
}
- s << "#include <typeinfo>" << endl;
+ s << "#include <typeinfo>\n";
if (usePySideExtensions() && metaClass->isQObject()) {
- s << "#include <signalmanager.h>" << endl;
- s << "#include <pysidemetafunction.h>" << endl;
+ s << "#include <signalmanager.h>\n";
+ s << "#include <pysidemetafunction.h>\n";
}
// The multiple inheritance initialization function
@@ -333,57 +373,65 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
if (getMultipleInheritingClass(metaClass) != nullptr)
s << "#include <algorithm>\n#include <set>\n";
if (metaClass->generateExceptionHandling())
- s << "#include <exception>" << endl;
+ s << "#include <exception>\n";
+ s << "#include <iterator>\n"; // For containers
+
+ if (wrapperDiagnostics())
+ s << "#include <helper.h>\n#include <iostream>\n";
- s << endl << "// module include" << endl << "#include \"" << getModuleHeaderFileName() << '"' << endl;
+ s << "\n// module include\n" << "#include \"" << getModuleHeaderFileName() << "\"\n";
QString headerfile = fileNameForContext(classContext);
headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h"));
- s << endl << "// main header" << endl << "#include \"" << headerfile << '"' << endl;
+ s << "\n// main header\n" << "#include \"" << headerfile << "\"\n";
- s << endl << "// inner classes" << endl;
+ s << Qt::endl << "// inner classes\n";
const AbstractMetaClassList &innerClasses = metaClass->innerClasses();
for (AbstractMetaClass *innerClass : innerClasses) {
- GeneratorContext innerClassContext(innerClass);
- if (shouldGenerate(innerClass)) {
+ GeneratorContext innerClassContext = contextForClass(innerClass);
+ if (shouldGenerate(innerClass) && !innerClass->typeEntry()->isSmartPointer()) {
QString headerfile = fileNameForContext(innerClassContext);
headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h"));
- s << "#include \"" << headerfile << '"' << endl;
+ s << "#include \"" << headerfile << "\"\n";
}
}
AbstractMetaEnumList classEnums = metaClass->enums();
- for (AbstractMetaClass *innerClass : innerClasses)
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+ metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
//Extra includes
- s << endl << "// Extra includes" << endl;
- QVector<Include> includes = metaClass->typeEntry()->extraIncludes();
+ QVector<Include> includes;
+ if (!classContext.useWrapper())
+ includes += metaClass->typeEntry()->extraIncludes();
for (AbstractMetaEnum *cppEnum : qAsConst(classEnums))
includes.append(cppEnum->typeEntry()->extraIncludes());
- std::sort(includes.begin(), includes.end());
- for (const Include &inc : qAsConst(includes))
- s << inc.toString() << endl;
- s << endl;
+ if (!includes.isEmpty()) {
+ s << "\n// Extra includes\n";
+ std::sort(includes.begin(), includes.end());
+ for (const Include &inc : qAsConst(includes))
+ s << inc.toString() << Qt::endl;
+ s << '\n';
+ }
s << "\n#include <cctype>\n#include <cstring>\n";
if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated)
- s << "#Deprecated" << endl;
+ s << "#Deprecated\n";
// Use class base namespace
{
const AbstractMetaClass *context = metaClass->enclosingClass();
while (context) {
- if (context->isNamespace() && !context->enclosingClass()) {
- s << "using namespace " << context->qualifiedCppName() << ";" << endl;
+ if (context->isNamespace() && !context->enclosingClass()
+ && static_cast<const NamespaceTypeEntry *>(context->typeEntry())->generateUsing()) {
+ s << "\nusing namespace " << context->qualifiedCppName() << ";\n";
break;
}
context = context->enclosingClass();
}
}
- s << endl << endl << typeNameFunc << endl;
+ s << Qt::endl << Qt::endl << typeNameFunc << Qt::endl;
// Create string literal for smart pointer getter method.
if (classContext.forSmartPointer()) {
@@ -396,46 +444,46 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
// class inject-code native/beginning
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass);
- s << endl;
+ writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(),
+ TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode,
+ classContext);
+ s << Qt::endl;
}
// python conversion rules
if (metaClass->typeEntry()->hasTargetConversionRule()) {
- s << "// Python Conversion" << endl;
- s << metaClass->typeEntry()->conversionRule() << endl;
+ s << "// Python Conversion\n";
+ s << metaClass->typeEntry()->conversionRule() << Qt::endl;
}
- if (shouldGenerateCppWrapper(metaClass)) {
- s << "// Native ---------------------------------------------------------" << endl;
- s << endl;
+ if (classContext.useWrapper()) {
+ s << "// Native ---------------------------------------------------------\n\n";
if (avoidProtectedHack() && usePySideExtensions()) {
- s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n";
+ s << "void " << classContext.wrapperName() << "::pysideInitQtMetaTypes()\n{\n";
Indentation indent(INDENT);
writeInitQtMetaTypeFunctionBody(s, classContext);
s << "}\n\n";
}
const AbstractMetaFunctionList &funcs = filterFunctions(metaClass);
+ int maxOverrides = 0;
+ writeCacheResetNative(s, classContext);
for (const AbstractMetaFunction *func : funcs) {
const bool notAbstract = !func->isAbstract();
if ((func->isPrivate() && notAbstract && !visibilityModifiedToPrivate(func))
|| (func->isModifiedRemoved() && notAbstract))
continue;
- if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) {
- writeConstructorNative(s, func);
- } else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor())
- && ((func->isVirtual() || func->isAbstract())
- && (func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0)) {
- writeVirtualMethodNative(s, func);
- }
+ if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded())
+ writeConstructorNative(s, classContext, func);
+ else if (shouldWriteVirtualMethodNative(func))
+ writeVirtualMethodNative(s, func, maxOverrides++);
}
if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) {
if (usePySideExtensions() && metaClass->isQObject())
- writeMetaObjectMethod(s, metaClass);
- writeDestructorNative(s, metaClass);
+ writeMetaObjectMethod(s, classContext);
+ writeDestructorNative(s, classContext);
}
}
@@ -448,8 +496,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
QString signaturesString;
QTextStream signatureStream(&signaturesString);
- s << endl << "// Target ---------------------------------------------------------" << endl << endl;
- s << "extern \"C\" {" << endl;
+ s << "\n// Target ---------------------------------------------------------\n\n"
+ << "extern \"C\" {\n";
const auto &functionGroups = getFunctionGroups(metaClass);
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
@@ -536,10 +584,10 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
writeSignatureInfo(signatureStream, overloads);
if (OverloadData::hasStaticAndInstanceFunctions(overloads)) {
QString methDefName = cpythonMethodDefinitionName(rfunc);
- smd << "static PyMethodDef " << methDefName << " = {" << endl;
+ smd << "static PyMethodDef " << methDefName << " = {\n";
smd << INDENT;
writeMethodDefinitionEntry(smd, overloads);
- smd << endl << "};" << endl << endl;
+ smd << "\n};\n\n";
}
writeMethodDefinition(md, overloads);
}
@@ -549,54 +597,67 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) {
writeCopyFunction(s, classContext);
- signatureStream << fullPythonClassName(metaClass) << ".__copy__()" << endl;
+ signatureStream << fullPythonClassName(metaClass) << ".__copy__()\n";
}
// Write single method definitions
s << singleMethodDefinitions;
+ if (usePySideExtensions()) {
+ // PYSIDE-1019: Write a compressed list of all properties `name:getter[:setter]`.
+ // Default values are suppressed.
+ QStringList sorter;
+ for (const auto spec : metaClass->propertySpecs()) {
+ if (!spec->generateGetSetDef())
+ sorter.append(buildPropertyString(spec));
+ }
+ sorter.sort();
+
+ s << '\n';
+ s << "static const char *" << className << "_PropertyStrings[] = {\n";
+ for (const auto &entry : qAsConst(sorter))
+ s << INDENT << entry << ",\n";
+ s << INDENT << NULL_PTR << " // Sentinel\n";
+ s << "};\n\n";
+ }
+
// Write methods definition
- s << "static PyMethodDef " << className << "_methods[] = {" << endl;
- s << methodsDefinitions << endl;
+ s << "static PyMethodDef " << className << "_methods[] = {\n";
+ s << methodsDefinitions << Qt::endl;
if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) {
s << INDENT << "{\"__copy__\", reinterpret_cast<PyCFunction>(" << className << "___copy__)"
- << ", METH_NOARGS}," << endl;
+ << ", METH_NOARGS},\n";
}
- s << INDENT << '{' << NULL_PTR << ", " << NULL_PTR << "} // Sentinel" << endl;
- s << "};" << endl << endl;
+ s << INDENT << '{' << NULL_PTR << ", " << NULL_PTR << "} // Sentinel\n";
+ s << "};\n\n";
- // Write tp_getattro function
- if ((usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))) {
- writeGetattroFunction(s, classContext);
- s << endl;
- writeSetattroFunction(s, classContext);
- s << endl;
+ // Write tp_s/getattro function
+ const AttroCheck attroCheck = checkAttroFunctionNeeds(metaClass);
+ if (attroCheck.testFlag(AttroCheckFlag::GetattroSmartPointer)) {
+ writeSmartPointerGetattroFunction(s, classContext);
+ writeSmartPointerSetattroFunction(s, classContext);
} else {
- if (classNeedsGetattroFunction(metaClass)) {
- writeGetattroFunction(s, classContext);
- s << endl;
- }
- if (classNeedsSetattroFunction(metaClass)) {
- writeSetattroFunction(s, classContext);
- s << endl;
- }
+ if ((attroCheck & AttroCheckFlag::GetattroMask) != 0)
+ writeGetattroFunction(s, attroCheck, classContext);
+ if ((attroCheck & AttroCheckFlag::SetattroMask) != 0)
+ writeSetattroFunction(s, attroCheck, classContext);
}
if (const AbstractMetaFunction *f = boolCast(metaClass)) {
ErrorCode errorCode(-1);
- s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject *self)" << endl;
- s << '{' << endl;
+ s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject *self)\n"
+ << "{\n";
writeCppSelfDefinition(s, classContext);
if (f->allowThread()) {
- s << INDENT << "int result;" << endl;
- s << INDENT << BEGIN_ALLOW_THREADS << endl;
- s << INDENT << "result = !" << CPP_SELF_VAR << "->isNull();" << endl;
- s << INDENT << END_ALLOW_THREADS << endl;
- s << INDENT << "return result;" << endl;
+ s << INDENT << "int result;\n";
+ s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl;
+ s << INDENT << "result = !" << CPP_SELF_VAR << "->isNull();\n";
+ s << INDENT << END_ALLOW_THREADS << Qt::endl;
+ s << INDENT << "return result;\n";
} else {
- s << INDENT << "return !" << CPP_SELF_VAR << "->isNull();" << endl;
+ s << INDENT << "return !" << CPP_SELF_VAR << "->isNull();\n";
}
- s << '}' << endl << endl;
+ s << "}\n\n";
}
if (supportsNumberProtocol(metaClass) && !metaClass->typeEntry()->isSmartPointer()) {
@@ -632,7 +693,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
}
if (!metaClass->isNamespace() && metaClass->hasComparisonOperatorOverload()) {
- s << "// Rich comparison" << endl;
+ s << "// Rich comparison\n";
writeRichCompareFunction(s, classContext);
}
@@ -644,28 +705,43 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
writeGetterFunction(s, metaField, classContext);
if (canGenerateFieldSetter(metaField))
writeSetterFunction(s, metaField, classContext);
- s << endl;
+ s << Qt::endl;
}
- s << "// Getters and Setters for " << metaClass->name() << endl;
- s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl;
+ for (const QPropertySpec *property : metaClass->propertySpecs()) {
+ if (property->generateGetSetDef() || !usePySideExtensions()) {
+ writeGetterFunction(s, property, classContext);
+ if (property->hasWrite())
+ writeSetterFunction(s, property, classContext);
+ }
+ }
+
+ s << "// Getters and Setters for " << metaClass->name() << Qt::endl;
+ s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {\n";
for (const AbstractMetaField *metaField : fields) {
- if (metaField->isStatic())
- continue;
+ if (!metaField->isStatic()) {
+ s << INDENT;
+ const QString setter = canGenerateFieldSetter(metaField)
+ ? cpythonSetterFunctionName(metaField) : QString();
+ writePyGetSetDefEntry(s, metaField->name(),
+ cpythonGetterFunctionName(metaField), setter);
+ }
+ }
- s << INDENT << "{const_cast<char *>(\"" << metaField->name() << "\"), ";
- s << cpythonGetterFunctionName(metaField) << ", ";
- if (canGenerateFieldSetter(metaField))
- s << cpythonSetterFunctionName(metaField);
- else
- s << NULL_PTR;
- s << "}," << endl;
+ for (const QPropertySpec *property : metaClass->propertySpecs()) {
+ if (property->generateGetSetDef() || !usePySideExtensions()) {
+ s << INDENT;
+ const QString setter = property->hasWrite()
+ ? cpythonSetterFunctionName(property, metaClass) : QString();
+ writePyGetSetDefEntry(s, property->name(),
+ cpythonGetterFunctionName(property, metaClass), setter);
+ }
}
- s << INDENT << '{' << NULL_PTR << "} // Sentinel" << endl;
- s << "};" << endl << endl;
+ s << INDENT << '{' << NULL_PTR << "} // Sentinel\n";
+ s << "};\n\n";
}
- s << "} // extern \"C\"" << endl << endl;
+ s << "} // extern \"C\"\n\n";
if (!metaClass->typeEntry()->hashFunction().isEmpty())
writeHashFunction(s, classContext);
@@ -675,58 +751,66 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
writeTpClearFunction(s, metaClass);
writeClassDefinition(s, metaClass, classContext);
- s << endl;
+ s << Qt::endl;
if (metaClass->isPolymorphic() && metaClass->baseClass())
writeTypeDiscoveryFunction(s, metaClass);
-
- for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) {
- if (cppEnum->isAnonymous() || cppEnum->isPrivate())
- continue;
-
- bool hasFlags = cppEnum->typeEntry()->flags();
- if (hasFlags) {
- writeFlagsMethods(s, cppEnum);
- writeFlagsNumberMethodsDefinition(s, cppEnum);
- s << endl;
- }
- }
- s << endl;
+ writeFlagsNumberMethodsDefinitions(s, classEnums);
+ s << Qt::endl;
writeConverterFunctions(s, metaClass, classContext);
writeClassRegister(s, metaClass, classContext, signatureStream);
// class inject-code native/end
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
- writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, metaClass);
- s << endl;
+ writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(),
+ TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode,
+ classContext);
+ s << Qt::endl;
}
}
-void CppGenerator::writeConstructorNative(QTextStream &s, const AbstractMetaFunction *func)
+void CppGenerator::writeCacheResetNative(QTextStream &s, const GeneratorContext &classContext)
{
Indentation indentation(INDENT);
- s << functionSignature(func, wrapperName(func->ownerClass()) + QLatin1String("::"), QString(),
+ s << "void " << classContext.wrapperName()
+ << "::resetPyMethodCache()\n{\n";
+ s << INDENT << "std::fill_n(m_PyMethodCache, sizeof(m_PyMethodCache) / sizeof(m_PyMethodCache[0]), false);\n";
+ s << "}\n\n";
+}
+
+void CppGenerator::writeConstructorNative(QTextStream &s, const GeneratorContext &classContext,
+ const AbstractMetaFunction *func)
+{
+ Indentation indentation(INDENT);
+ const QString qualifiedName = classContext.wrapperName() + QLatin1String("::");
+ s << functionSignature(func, qualifiedName, QString(),
OriginalTypeDescription | SkipDefaultValues);
s << " : ";
writeFunctionCall(s, func);
- s << endl << "{" << endl;
+ s << "\n{\n";
+ if (wrapperDiagnostics())
+ s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << this << '\n';)" << '\n';
const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
+ s << INDENT << "resetPyMethodCache();\n";
writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg);
- s << INDENT << "// ... middle" << endl;
+ s << INDENT << "// ... middle\n";
writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg);
- s << '}' << endl << endl;
+ s << "}\n\n";
}
-void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeDestructorNative(QTextStream &s, const GeneratorContext &classContext)
{
Indentation indentation(INDENT);
- s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl;
+ s << classContext.wrapperName() << "::~"
+ << classContext.wrapperName() << "()\n{\n";
+ if (wrapperDiagnostics())
+ s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << this << '\n';)" << '\n';
// kill pyobject
- s << INDENT << "SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "Shiboken::Object::destroy(wrapper, this);" << endl;
- s << '}' << endl;
+ s << INDENT << "SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);\n";
+ s << INDENT << "Shiboken::Object::destroy(wrapper, this);\n";
+ s << "}\n";
}
static bool allArgumentsRemoved(const AbstractMetaFunction *func)
@@ -750,11 +834,14 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"');
// SbkType would return null when the type is a container.
- if (func->type()->typeEntry()->isContainer()) {
+ auto typeEntry = func->type()->typeEntry();
+ if (typeEntry->isContainer()) {
return QLatin1Char('"')
- + reinterpret_cast<const ContainerTypeEntry *>(func->type()->typeEntry())->typeName()
+ + reinterpret_cast<const ContainerTypeEntry *>(typeEntry)->typeName()
+ QLatin1Char('"');
}
+ if (typeEntry->isSmartPointer())
+ return QLatin1Char('"') + typeEntry->qualifiedCppName() + QLatin1Char('"');
if (avoidProtectedHack()) {
const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(func->type());
@@ -765,134 +852,203 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
if (func->type()->isPrimitive())
return QLatin1Char('"') + func->type()->name() + QLatin1Char('"');
- return QString::fromLatin1("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< %1 >())->tp_name").arg(func->type()->typeEntry()->qualifiedCppName());
+ return QLatin1String("reinterpret_cast<PyTypeObject *>(Shiboken::SbkType< ")
+ + typeEntry->qualifiedCppName() + QLatin1String(" >())->tp_name");
+}
+
+// When writing an overridden method of a wrapper class, write the part
+// calling the C++ function in case no overload in Python exists.
+void CppGenerator::writeVirtualMethodCppCall(QTextStream &s,
+ const AbstractMetaFunction *func,
+ const QString &funcName,
+ const CodeSnipList &snips,
+ const AbstractMetaArgument *lastArg,
+ const TypeEntry *retType,
+ const QString &returnStatement)
+{
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning,
+ TypeSystem::ShellCode, func, lastArg);
+ }
+
+ if (func->isAbstract()) {
+ s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"
+ << func->ownerClass()->name() << '.' << funcName
+ << "()' not implemented.\");\n"
+ << INDENT << returnStatement << '\n';
+ return;
+ }
+
+ s << INDENT;
+ if (retType)
+ s << "return ";
+ s << "this->::" << func->implementingClass()->qualifiedCppName() << "::";
+ writeFunctionCall(s, func, Generator::VirtualCall);
+ s << ";\n";
+ if (retType)
+ return;
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd,
+ TypeSystem::ShellCode, func, lastArg);
+ }
+ s << INDENT << "return;\n";
}
-void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFunction *func)
+// Determine the return statement (void or a result value).
+QString CppGenerator::virtualMethodReturn(QTextStream &s,
+ const AbstractMetaFunction *func,
+ const FunctionModificationList &functionModifications)
+{
+ if (func->isVoid())
+ return QLatin1String("return;");
+ const AbstractMetaType *returnType = func->type();
+ for (const FunctionModification &mod : functionModifications) {
+ for (const ArgumentModification &argMod : mod.argument_mods) {
+ if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) {
+ static const QRegularExpression regex(QStringLiteral("%(\\d+)"));
+ Q_ASSERT(regex.isValid());
+ QString expr = argMod.replacedDefaultExpression;
+ for (int offset = 0; ; ) {
+ const QRegularExpressionMatch match = regex.match(expr, offset);
+ if (!match.hasMatch())
+ break;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ const int argId = match.capturedView(1).toInt() - 1;
+#else
+ const int argId = match.capturedRef(1).toInt() - 1;
+#endif
+ if (argId < 0 || argId > func->arguments().count()) {
+ qCWarning(lcShiboken, "The expression used in return value contains an invalid index.");
+ break;
+ }
+ expr.replace(match.captured(0), func->arguments().at(argId)->name());
+ offset = match.capturedStart(1);
+ }
+ DefaultValue defaultReturnExpr(DefaultValue::Custom, expr);
+ return QLatin1String("return ") + defaultReturnExpr.returnValue()
+ + QLatin1Char(';');
+ }
+ }
+ }
+ const DefaultValue defaultReturnExpr = minimalConstructor(returnType);
+ if (!defaultReturnExpr.isValid()) {
+ QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": ");
+ if (const AbstractMetaClass *c = func->implementingClass())
+ errorMsg += c->qualifiedCppName() + QLatin1String("::");
+ errorMsg += func->signature();
+ errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature());
+ qCWarning(lcShiboken).noquote().nospace() << errorMsg;
+ s << Qt::endl << INDENT << "#error " << errorMsg << Qt::endl;
+ }
+ if (returnType->referenceType() == LValueReference) {
+ s << INDENT << "static " << returnType->typeEntry()->qualifiedCppName()
+ << " result;\n";
+ return QLatin1String("return result;");
+ }
+ return QLatin1String("return ") + defaultReturnExpr.returnValue()
+ + QLatin1Char(';');
+}
+
+void CppGenerator::writeVirtualMethodNative(QTextStream &s,
+ const AbstractMetaFunction *func,
+ int cacheIndex)
{
//skip metaObject function, this will be written manually ahead
if (usePySideExtensions() && func->ownerClass() && func->ownerClass()->isQObject() &&
((func->name() == QLatin1String("metaObject")) || (func->name() == QLatin1String("qt_metacall"))))
return;
- const TypeEntry *retType = func->type() ? func->type()->typeEntry() : nullptr;
+ const TypeEntry *retType = func->type()->typeEntry();
const QString funcName = func->isOperatorOverload() ? pythonOperatorFunctionName(func) : func->name();
QString prefix = wrapperName(func->ownerClass()) + QLatin1String("::");
s << functionSignature(func, prefix, QString(), Generator::SkipDefaultValues|Generator::OriginalTypeDescription)
- << endl << '{' << endl;
+ << "\n{\n";
Indentation indentation(INDENT);
- DefaultValue defaultReturnExpr;
- if (retType) {
- const FunctionModificationList &mods = func->modifications();
- for (const FunctionModification &mod : mods) {
- for (const ArgumentModification &argMod : mod.argument_mods) {
- if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) {
- static const QRegularExpression regex(QStringLiteral("%(\\d+)"));
- Q_ASSERT(regex.isValid());
- QString expr = argMod.replacedDefaultExpression;
- for (int offset = 0; ; ) {
- const QRegularExpressionMatch match = regex.match(expr, offset);
- if (!match.hasMatch())
- break;
- const int argId = match.capturedRef(1).toInt() - 1;
- if (argId < 0 || argId > func->arguments().count()) {
- qCWarning(lcShiboken) << "The expression used in return value contains an invalid index.";
- break;
- }
- expr.replace(match.captured(0), func->arguments().at(argId)->name());
- offset = match.capturedStart(1);
- }
- defaultReturnExpr.setType(DefaultValue::Custom);
- defaultReturnExpr.setValue(expr);
- }
- }
- }
- if (!defaultReturnExpr.isValid())
- defaultReturnExpr = minimalConstructor(func->type());
- if (!defaultReturnExpr.isValid()) {
- QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": ");
- if (const AbstractMetaClass *c = func->implementingClass())
- errorMsg += c->qualifiedCppName() + QLatin1String("::");
- errorMsg += func->signature();
- errorMsg = msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature());
- qCWarning(lcShiboken).noquote().nospace() << errorMsg;
- s << endl << INDENT << "#error " << errorMsg << endl;
- }
- } else {
- defaultReturnExpr.setType(DefaultValue::Void);
- }
+ const FunctionModificationList &functionModifications = func->modifications();
+
+ const QString returnStatement = virtualMethodReturn(s, func, functionModifications);
if (func->isAbstract() && func->isModifiedRemoved()) {
qCWarning(lcShiboken).noquote().nospace()
<< QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\
"completely removed on type system.")
.arg(func->ownerClass()->name(), func->minimalSignature());
- s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
- s << '}' << endl << endl;
+ s << INDENT << returnStatement << "\n}\n\n";
return;
}
+ const CodeSnipList snips = func->hasInjectedCode()
+ ? func->injectedCodeSnips() : CodeSnipList();
+ const AbstractMetaArgument *lastArg = func->arguments().isEmpty()
+ ? nullptr : func->arguments().constLast();
+
//Write declaration/native injected code
- if (func->hasInjectedCode()) {
- CodeSnipList snips = func->injectedCodeSnips();
- const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg);
- s << endl;
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration,
+ TypeSystem::ShellCode, func, lastArg);
}
- s << INDENT << "Shiboken::GilState gil;" << endl;
-
- // Get out of virtual method call if someone already threw an error.
- s << INDENT << "if (PyErr_Occurred())" << endl;
+ if (wrapperDiagnostics()) {
+ s << INDENT << "std::cerr << ";
+#ifndef Q_CC_MSVC // g++ outputs __FUNCTION__ unqualified
+ s << '"' << prefix << R"(" << )";
+#endif
+ s << R"(__FUNCTION__ << ' ' << this << " m_PyMethodCache[" << )"
+ << cacheIndex << R"( << "]=" << m_PyMethodCache[)" << cacheIndex
+ << R"(] << '\n';)" << '\n';
+ }
+ // PYSIDE-803: Build a boolean cache for unused overrides.
+ const bool multi_line = func->isVoid() || !snips.isEmpty() || func->isAbstract();
+ s << INDENT << "if (m_PyMethodCache[" << cacheIndex << "])" << (multi_line ? " {\n" : "\n");
{
Indentation indentation(INDENT);
- s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
+ writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
+ returnStatement);
}
+ if (multi_line)
+ s << INDENT << "}\n";
- s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR << "(Shiboken::BindingManager::instance().getOverride(this, \"";
- s << funcName << "\"));" << endl;
-
- s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {" << endl;
- {
- Indentation indentation(INDENT);
- CodeSnipList snips;
- if (func->hasInjectedCode()) {
- snips = func->injectedCodeSnips();
- const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg);
- s << endl;
- }
+ s << INDENT << "Shiboken::GilState gil;\n";
- if (func->isAbstract()) {
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
- s << func->ownerClass()->name() << '.' << funcName;
- s << "()' not implemented.\");" << endl;
- s << INDENT << "return";
- if (retType)
- s << ' ' << defaultReturnExpr.returnValue();
- } else {
- s << INDENT << "gil.release();" << endl;
- s << INDENT;
- if (retType)
- s << "return ";
- s << "this->::" << func->implementingClass()->qualifiedCppName() << "::";
- writeFunctionCall(s, func, Generator::VirtualCall);
- if (!retType)
- s << ";\n" << INDENT << "return";
- }
- }
- s << ';' << endl;
- s << INDENT << '}' << endl << endl;
+ // Get out of virtual method call if someone already threw an error.
+ s << INDENT << "if (PyErr_Occurred())\n" << indent(INDENT)
+ << INDENT << returnStatement << '\n' << outdent(INDENT);
+
+ //PYSIDE-1019: Add info about properties.
+ int propFlag = 0;
+ if (func->isPropertyReader())
+ propFlag |= 1;
+ if (func->isPropertyWriter())
+ propFlag |= 2;
+ if (propFlag && func->isStatic())
+ propFlag |= 4;
+ QString propStr;
+ if (propFlag)
+ propStr = QString::number(propFlag) + QLatin1Char(':');
+
+ s << INDENT << "static PyObject *nameCache[2] = {};\n";
+ if (propFlag)
+ s << INDENT << "// This method belongs to a property.\n";
+ s << INDENT << "static const char *funcName = \"" << propStr << funcName << "\";\n";
+ s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR
+ << "(Shiboken::BindingManager::instance().getOverride(this, nameCache, funcName));\n";
+ s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n"
+ << indent(INDENT) << INDENT << "gil.release();\n";
+ if (useOverrideCaching(func->ownerClass()))
+ s << INDENT << "m_PyMethodCache[" << cacheIndex << "] = true;\n";
+ writeVirtualMethodCppCall(s, func, funcName, snips, lastArg, retType,
+ returnStatement);
+ s << outdent(INDENT) << INDENT << "}\n\n"; //WS
writeConversionRule(s, func, TypeSystem::TargetLangCode);
s << INDENT << "Shiboken::AutoDecRef " << PYTHON_ARGS << "(";
if (func->arguments().isEmpty() || allArgumentsRemoved(func)) {
- s << "PyTuple_New(0));" << endl;
+ s << "PyTuple_New(0));\n";
} else {
QStringList argConversions;
const AbstractMetaArgumentList &arguments = func->arguments();
@@ -918,8 +1074,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
convert = !m_formatUnits.contains(argType->name());
}
- Indentation indentation(INDENT);
- ac << INDENT;
+ Indentor nested;
+ Indentation indentation(nested);
+ ac << nested;
if (!func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty()) {
// Has conversion rule.
ac << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX);
@@ -934,95 +1091,90 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
argConversions << argConv;
}
- s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\"," << endl;
- s << argConversions.join(QLatin1String(",\n")) << endl;
- s << INDENT << "));" << endl;
+ s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\",\n";
+ s << argConversions.join(QLatin1String(",\n")) << Qt::endl;
+ s << INDENT << "));\n";
}
bool invalidateReturn = false;
QSet<int> invalidateArgs;
- const FunctionModificationList &mods = func->modifications();
- for (const FunctionModification &funcMod : mods) {
+ for (const FunctionModification &funcMod : functionModifications) {
for (const ArgumentModification &argMod : funcMod.argument_mods) {
if (argMod.resetAfterUse && !invalidateArgs.contains(argMod.index)) {
invalidateArgs.insert(argMod.index);
s << INDENT << "bool invalidateArg" << argMod.index;
- s << " = PyTuple_GET_ITEM(" << PYTHON_ARGS << ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl;
+ s << " = PyTuple_GET_ITEM(" << PYTHON_ARGS << ", " << argMod.index - 1 << ")->ob_refcnt == 1;\n";
} else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) {
invalidateReturn = true;
}
}
}
- s << endl;
-
- CodeSnipList snips;
- if (func->hasInjectedCode()) {
- snips = func->injectedCodeSnips();
+ s << Qt::endl;
+ if (!snips.isEmpty()) {
if (injectedCodeUsesPySelf(func))
- s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);" << endl;
+ s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);\n";
const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg);
- s << endl;
}
if (!injectedCodeCallsPythonOverride(func)) {
s << INDENT;
s << "Shiboken::AutoDecRef " << PYTHON_RETURN_VAR << "(PyObject_Call("
- << PYTHON_OVERRIDE_VAR << ", " << PYTHON_ARGS << ", nullptr));" << endl;
+ << PYTHON_OVERRIDE_VAR << ", " << PYTHON_ARGS << ", nullptr));\n";
- s << INDENT << "// An error happened in python code!" << endl;
- s << INDENT << "if (" << PYTHON_RETURN_VAR << ".isNull()) {" << endl;
+ s << INDENT << "// An error happened in python code!\n";
+ s << INDENT << "if (" << PYTHON_RETURN_VAR << ".isNull()) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_Print();" << endl;
- s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
+ s << INDENT << "PyErr_Print();\n";
+ s << INDENT << returnStatement << '\n';
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
- if (retType) {
+ if (!func->isVoid()) {
if (invalidateReturn)
- s << INDENT << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;" << endl;
+ s << INDENT << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;\n";
if (func->typeReplaced(0) != QLatin1String("PyObject")) {
- s << INDENT << "// Check return type" << endl;
+ s << INDENT << "// Check return type\n";
s << INDENT;
if (func->typeReplaced(0).isEmpty()) {
s << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << " = " << cpythonIsConvertibleFunction(func->type());
- s << PYTHON_RETURN_VAR << ");" << endl;
- s << INDENT << "if (!" << PYTHON_TO_CPP_VAR << ") {" << endl;
+ s << PYTHON_RETURN_VAR << ");\n";
+ s << INDENT << "if (!" << PYTHON_TO_CPP_VAR << ") {\n";
{
Indentation indent(INDENT);
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);" << endl;
- s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
+ s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n";
+ s << INDENT << returnStatement << '\n';
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
} else {
- s << INDENT << "// Check return type" << endl;
+ s << INDENT << "// Check return type\n";
s << INDENT << "bool typeIsValid = ";
writeTypeCheck(s, func->type(), QLatin1String(PYTHON_RETURN_VAR),
isNumber(func->type()->typeEntry()), func->typeReplaced(0));
- s << ';' << endl;
+ s << ";\n";
s << INDENT << "if (!typeIsValid";
if (isPointerToWrapperType(func->type()))
s << " && " << PYTHON_RETURN_VAR << " != Py_None";
- s << ") {" << endl;
+ s << ") {\n";
{
Indentation indent(INDENT);
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);" << endl;
- s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << endl;
+ s << ", Py_TYPE(" << PYTHON_RETURN_VAR << ")->tp_name);\n";
+ s << INDENT << returnStatement << '\n';
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
}
@@ -1038,37 +1190,35 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
}
if (invalidateReturn) {
- s << INDENT << "if (invalidateArg0)" << endl;
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ".object());" << endl;
+ s << INDENT << "if (invalidateArg0)\n" << indent(INDENT)
+ << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR
+ << ".object());\n" << outdent(INDENT);
}
for (int argIndex : qAsConst(invalidateArgs)) {
- s << INDENT << "if (invalidateArg" << argIndex << ')' << endl;
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS << ", ";
- s << (argIndex - 1) << "));" << endl;
+ s << INDENT << "if (invalidateArg" << argIndex << ")\n" << indent(INDENT)
+ << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" << PYTHON_ARGS
+ << ", " << (argIndex - 1) << "));\n" << outdent(INDENT);
}
- const FunctionModificationList &funcMods = func->modifications();
- for (const FunctionModification &funcMod : funcMods) {
+ for (const FunctionModification &funcMod : functionModifications) {
for (const ArgumentModification &argMod : funcMod.argument_mods) {
if (argMod.ownerships.contains(TypeSystem::NativeCode)
&& argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) {
- s << INDENT << "if (Shiboken::Object::checkType(" << PYTHON_RETURN_VAR << "))" << endl;
+ s << INDENT << "if (Shiboken::Object::checkType(" << PYTHON_RETURN_VAR << "))\n";
Indentation indent(INDENT);
- s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ");" << endl;
+ s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR << ");\n";
}
}
}
if (func->hasInjectedCode()) {
- s << endl;
+ s << Qt::endl;
const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg);
}
- if (retType) {
+ if (!func->isVoid()) {
s << INDENT << "return ";
if (avoidProtectedHack() && retType->isEnum()) {
const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(retType);
@@ -1083,32 +1233,33 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
}
if (func->type()->referenceType() == LValueReference && !isPointer(func->type()))
s << " *";
- s << CPP_RETURN_VAR << ';' << endl;
+ s << CPP_RETURN_VAR << ";\n";
}
- s << '}' << endl << endl;
+ s<< "}\n\n";
}
-void CppGenerator::writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeMetaObjectMethod(QTextStream &s, const GeneratorContext &classContext)
{
Indentation indentation(INDENT);
- QString wrapperClassName = wrapperName(metaClass);
- s << "const QMetaObject *" << wrapperClassName << "::metaObject() const" << endl;
- s << '{' << endl;
- s << INDENT << "if (QObject::d_ptr->metaObject)" << endl
- << INDENT << INDENT << "return QObject::d_ptr->dynamicMetaObject();" << endl;
- s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "if (pySelf == nullptr)" << endl;
- s << INDENT << INDENT << "return " << metaClass->qualifiedCppName() << "::metaObject();" << endl;
- s << INDENT << "return PySide::SignalManager::retrieveMetaObject(reinterpret_cast<PyObject *>(pySelf));" << endl;
- s << '}' << endl << endl;
+ const QString wrapperClassName = classContext.wrapperName();
+ const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName();
+ s << "const QMetaObject *" << wrapperClassName << "::metaObject() const\n{\n";
+ s << INDENT << "if (QObject::d_ptr->metaObject)\n"
+ << INDENT << INDENT << "return QObject::d_ptr->dynamicMetaObject();\n";
+ s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n";
+ s << INDENT << "if (pySelf == nullptr)\n";
+ s << INDENT << INDENT << "return " << qualifiedCppName << "::metaObject();\n";
+ s << INDENT << "return PySide::SignalManager::retrieveMetaObject(reinterpret_cast<PyObject *>(pySelf));\n";
+ s<< "}\n\n";
// qt_metacall function
- s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void **args)" << endl;
- s << "{" << endl;
+ s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void **args)\n";
+ s << "{\n";
AbstractMetaFunction *func = nullptr;
- AbstractMetaFunctionList list = metaClass->queryFunctionsByName(QLatin1String("qt_metacall"));
+ AbstractMetaFunctionList list =
+ classContext.metaClass()->queryFunctionsByName(QLatin1String("qt_metacall"));
if (list.size() == 1)
func = list[0];
@@ -1121,26 +1272,26 @@ void CppGenerator::writeMetaObjectMethod(QTextStream &s, const AbstractMetaClass
}
}
- s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);" << endl;
- s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);" << endl;
- s << "}" << endl << endl;
+ s << INDENT << "int result = " << qualifiedCppName << "::qt_metacall(call, id, args);\n";
+ s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);\n";
+ s << "}\n\n";
// qt_metacast function
- writeMetaCast(s, metaClass);
+ writeMetaCast(s, classContext);
}
-void CppGenerator::writeMetaCast(QTextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::writeMetaCast(QTextStream &s, const GeneratorContext &classContext)
{
Indentation indentation(INDENT);
- QString wrapperClassName = wrapperName(metaClass);
- s << "void *" << wrapperClassName << "::qt_metacast(const char *_clname)" << endl;
- s << '{' << endl;
- s << INDENT << "if (!_clname) return {};" << endl;
- s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl;
- s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))" << endl;
- s << INDENT << INDENT << "return static_cast<void *>(const_cast< " << wrapperClassName << " *>(this));" << endl;
- s << INDENT << "return " << metaClass->qualifiedCppName() << "::qt_metacast(_clname);" << endl;
- s << "}" << endl << endl;
+ const QString wrapperClassName = classContext.wrapperName();
+ const QString qualifiedCppName = classContext.metaClass()->qualifiedCppName();
+ s << "void *" << wrapperClassName << "::qt_metacast(const char *_clname)\n{\n";
+ s << INDENT << "if (!_clname) return {};\n";
+ s << INDENT << "SbkObject *pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n";
+ s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))\n";
+ s << INDENT << INDENT << "return static_cast<void *>(const_cast< " << wrapperClassName << " *>(this));\n";
+ s << INDENT << "return " << qualifiedCppName << "::qt_metacast(_clname);\n";
+ s << "}\n\n";
}
void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const AbstractMetaEnum *metaEnum)
@@ -1164,13 +1315,14 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry *
}
QString code;
QTextStream c(&code);
- c << INDENT << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << INDENT << " ";
+ Indentor nested;
+ c << nested << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
+ << nested << " ";
if (enumType->isFlags())
c << cppTypeName << "(QFlag(int(PySide::QFlags::getValue(reinterpret_cast<PySideQFlagsObject *>(pyIn)))))";
else
c << "static_cast<" << cppTypeName << ">(Shiboken::Enum::getValue(pyIn))";
- c << ';' << endl;
+ c << ";\n";
writePythonToCppFunction(s, code, typeName, typeName);
QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, %1)").arg(enumPythonType);
@@ -1178,9 +1330,9 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry *
code.clear();
- c << INDENT << "const int castCppIn = int(*reinterpret_cast<const "
- << cppTypeName << " *>(cppIn));" << endl;
- c << INDENT;
+ c << nested << "const int castCppIn = int(*reinterpret_cast<const "
+ << cppTypeName << " *>(cppIn));\n";
+ c << nested;
c << "return ";
if (enumType->isFlags()) {
c << "reinterpret_cast<PyObject *>(PySide::QFlags::newObject(castCppIn, "
@@ -1188,9 +1340,9 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry *
} else {
c << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn)";
}
- c << ';' << endl;
+ c << ";\n";
writeCppToPythonFunction(s, code, typeName, typeName);
- s << endl;
+ s << Qt::endl;
if (enumType->isFlags())
return;
@@ -1205,19 +1357,19 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry *
code.clear();
cppTypeName = getFullTypeName(flags).trimmed();
- c << INDENT << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << INDENT << " " << cppTypeName
- << "(QFlag(int(Shiboken::Enum::getValue(pyIn))));" << endl;
+ c << nested << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
+ << nested << " " << cppTypeName
+ << "(QFlag(int(Shiboken::Enum::getValue(pyIn))));\n";
QString flagsTypeName = fixedCppTypeName(flags);
writePythonToCppFunction(s, code, typeName, flagsTypeName);
writeIsPythonConvertibleToCppFunction(s, typeName, flagsTypeName, pyTypeCheck);
code.clear();
- c << INDENT << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));" << endl;
- c << INDENT << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
- << INDENT << " " << cppTypeName
- << "(QFlag(int(PyLong_AsLong(pyLong.object()))));" << endl;
+ c << nested << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));\n";
+ c << nested << "*reinterpret_cast<" << cppTypeName << " *>(cppOut) =\n"
+ << nested << " " << cppTypeName
+ << "(QFlag(int(PyLong_AsLong(pyLong.object()))));\n";
// PYSIDE-898: Include an additional condition to detect if the type of the
// enum corresponds to the object that is being evaluated.
// Using only `PyNumber_Check(...)` is too permissive,
@@ -1232,16 +1384,14 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream &s, const TypeEntry *
}
void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass,
- GeneratorContext &classContext)
+ const GeneratorContext &classContext)
{
- s << "// Type conversion functions." << endl << endl;
+ s << "// Type conversion functions.\n\n";
AbstractMetaEnumList classEnums = metaClass->enums();
- const AbstractMetaClassList &innerClasses = metaClass->innerClasses();
- for (AbstractMetaClass *innerClass : innerClasses)
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+ metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
if (!classEnums.isEmpty())
- s << "// Python to C++ enum conversion." << endl;
+ s << "// Python to C++ enum conversion.\n";
for (const AbstractMetaEnum *metaEnum : qAsConst(classEnums))
writeEnumConverterFunctions(s, metaEnum);
@@ -1257,62 +1407,63 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
QString cpythonType = cpythonTypeName(metaClass);
// Returns the C++ pointer of the Python wrapper.
- s << "// Python to C++ pointer conversion - returns the C++ object of the Python wrapper (keeps object identity)." << endl;
+ s << "// Python to C++ pointer conversion - returns the C++ object of the Python wrapper (keeps object identity).\n";
QString sourceTypeName = metaClass->name();
QString targetTypeName = metaClass->name() + QLatin1String("_PTR");
QString code;
QTextStream c(&code);
- c << INDENT << "Shiboken::Conversions::pythonToCppPointer(" << cpythonType << ", pyIn, cppOut);";
+ Indentor nested;
+ c << nested << "Shiboken::Conversions::pythonToCppPointer(" << cpythonType << ", pyIn, cppOut);";
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// "Is convertible" function for the Python object to C++ pointer conversion.
const QString pyTypeCheck = QLatin1String("PyObject_TypeCheck(pyIn, reinterpret_cast<PyTypeObject *>(")
+ cpythonType + QLatin1String("))");
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true);
- s << endl;
+ s << Qt::endl;
// C++ pointer to a Python wrapper, keeping identity.
- s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity)." << endl;
+ s << "// C++ to Python pointer conversion - tries to find the Python wrapper for the C++ object (keeps object identity).\n";
code.clear();
if (usePySideExtensions() && metaClass->isQObject())
{
- c << INDENT << "return PySide::getWrapperForQObject(reinterpret_cast<"
- << typeName << " *>(const_cast<void *>(cppIn)), " << cpythonType << ");" << endl;
+ c << nested << "return PySide::getWrapperForQObject(reinterpret_cast<"
+ << typeName << " *>(const_cast<void *>(cppIn)), " << cpythonType << ");\n";
} else {
- c << INDENT << "auto pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppIn));" << endl;
- c << INDENT << "if (pyOut) {" << endl;
+ c << nested << "auto pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppIn));\n";
+ c << nested << "if (pyOut) {\n";
{
- Indentation indent(INDENT);
- c << INDENT << "Py_INCREF(pyOut);" << endl;
- c << INDENT << "return pyOut;" << endl;
- }
- c << INDENT << '}' << endl;
- c << INDENT << "bool changedTypeName = false;\n"
- << INDENT << "auto tCppIn = reinterpret_cast<const " << typeName << " *>(cppIn);\n"
- << INDENT << "const char *typeName = typeid(*tCppIn).name();\n"
- << INDENT << "auto sbkType = Shiboken::ObjectType::typeForTypeName(typeName);\n"
- << INDENT << "if (sbkType && Shiboken::ObjectType::hasSpecialCastFunction(sbkType)) {\n"
- << INDENT << " typeName = typeNameOf(tCppIn);\n"
- << INDENT << " changedTypeName = true;\n"
- << INDENT << " }\n"
- << INDENT << "PyObject *result = Shiboken::Object::newObject(" << cpythonType
+ Indentation indent(nested);
+ c << nested << "Py_INCREF(pyOut);\n";
+ c << nested << "return pyOut;\n";
+ }
+ c << nested << "}\n";
+ c << nested << "bool changedTypeName = false;\n"
+ << nested << "auto tCppIn = reinterpret_cast<const " << typeName << " *>(cppIn);\n"
+ << nested << "const char *typeName = typeid(*tCppIn).name();\n"
+ << nested << "auto sbkType = Shiboken::ObjectType::typeForTypeName(typeName);\n"
+ << nested << "if (sbkType && Shiboken::ObjectType::hasSpecialCastFunction(sbkType)) {\n"
+ << nested << " typeName = typeNameOf(tCppIn);\n"
+ << nested << " changedTypeName = true;\n"
+ << nested << "}\n"
+ << nested << "PyObject *result = Shiboken::Object::newObject(" << cpythonType
<< ", const_cast<void *>(cppIn), false, /* exactType */ changedTypeName, typeName);\n"
- << INDENT << "if (changedTypeName)\n"
- << INDENT << " delete [] typeName;\n"
- << INDENT << "return result;";
+ << nested << "if (changedTypeName)\n"
+ << nested << " delete [] typeName;\n"
+ << nested << "return result;";
}
std::swap(targetTypeName, sourceTypeName);
writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
// The conversions for an Object Type end here.
if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) {
- s << endl;
+ s << Qt::endl;
return;
}
// Always copies C++ value (not pointer, and not reference) to a new Python wrapper.
- s << endl << "// C++ to Python copy conversion." << endl;
+ s << Qt::endl << "// C++ to Python copy conversion.\n";
if (!classContext.forSmartPointer())
targetTypeName = metaClass->name();
else
@@ -1323,19 +1474,21 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
code.clear();
QString computedWrapperName;
- if (!classContext.forSmartPointer())
- computedWrapperName = wrapperName(metaClass);
- else
- computedWrapperName = wrapperName(classContext.preciseType());
+ if (!classContext.forSmartPointer()) {
+ computedWrapperName = classContext.useWrapper()
+ ? classContext.wrapperName() : metaClass->qualifiedCppName();
+ } else {
+ computedWrapperName = classContext.smartPointerWrapperName();
+ }
- c << INDENT << "return Shiboken::Object::newObject(" << cpythonType
+ c << nested << "return Shiboken::Object::newObject(" << cpythonType
<< ", new ::" << computedWrapperName << "(*reinterpret_cast<const "
<< typeName << " *>(cppIn)), true, true);";
writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
- s << endl;
+ s << Qt::endl;
// Python to C++ copy conversion.
- s << "// Python to C++ copy conversion." << endl;
+ s << "// Python to C++ copy conversion.\n";
if (!classContext.forSmartPointer())
sourceTypeName = metaClass->name();
else
@@ -1351,13 +1504,13 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
else
wrappedCPtrExpression = cpythonWrapperCPtr(classContext.preciseType(), pyInVariable);
- c << INDENT << "*reinterpret_cast<" << typeName << " *>(cppOut) = *"
+ c << nested << "*reinterpret_cast<" << typeName << " *>(cppOut) = *"
<< wrappedCPtrExpression << ';';
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// "Is convertible" function for the Python object to C++ value copy conversion.
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck);
- s << endl;
+ s << Qt::endl;
// User provided implicit conversions.
CustomConversion *customConversion = metaClass->typeEntry()->customConversion();
@@ -1373,7 +1526,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
}
if (!implicitConvs.isEmpty())
- s << "// Implicit conversions." << endl;
+ s << "// Implicit conversions.\n";
AbstractMetaType *targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
for (const AbstractMetaFunction *conv : qAsConst(implicitConvs)) {
@@ -1420,9 +1573,9 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
|| sourceType->typeEntry()->isEnum()
|| sourceType->typeEntry()->isFlags()) {
QTextStream pc(&toCppPreConv);
- pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn";
+ pc << nested << getFullTypeNameWithoutModifiers(sourceType) << " cppIn";
writeMinimalConstructorExpression(pc, sourceType);
- pc << ';' << endl;
+ pc << ";\n";
writeToCppConversion(pc, sourceType, nullptr, QLatin1String("pyIn"), QLatin1String("cppIn"));
pc << ';';
toCppConv.append(QLatin1String("cppIn"));
@@ -1449,52 +1602,72 @@ void CppGenerator::writeCustomConverterFunctions(QTextStream &s, const CustomCon
const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
if (toCppConversions.isEmpty())
return;
- s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'." << endl;
+ s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'.\n";
for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions)
writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType());
- s << endl;
+ s << Qt::endl;
}
void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass,
- GeneratorContext &classContext)
+ const GeneratorContext &classContext)
{
if (metaClass->isNamespace())
return;
- s << INDENT << "// Register Converter" << endl;
+ s << INDENT << "// Register Converter\n";
s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(";
- s << cpythonTypeName(metaClass) << ',' << endl;
+ s << cpythonTypeName(metaClass) << ',' << Qt::endl;
{
Indentation indent(INDENT);
QString sourceTypeName = metaClass->name();
QString targetTypeName = sourceTypeName + QLatin1String("_PTR");
- s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl;
- s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl;
+ s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl;
+ s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << Qt::endl;
std::swap(targetTypeName, sourceTypeName);
s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) {
- s << ',' << endl;
+ s << ',' << Qt::endl;
sourceTypeName = metaClass->name() + QLatin1String("_COPY");
s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
}
}
- s << ");" << endl;
+ s << ");\n";
+
+ s << Qt::endl;
+
+ auto writeConversions = [&s, this](const QString &signature)
+ {
+ s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");\n";
+ s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");\n";
+ s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");\n";
+ };
+
+ auto writeConversionsForType = [writeConversions](const QString &fullTypeName)
+ {
+ QStringList lst = fullTypeName.split(QLatin1String("::"),
+ Qt::SkipEmptyParts);
+ while (!lst.isEmpty()) {
+ QString signature = lst.join(QLatin1String("::"));
+ writeConversions(signature);
+ lst.removeFirst();
+ }
+ };
- s << endl;
- QStringList cppSignature;
if (!classContext.forSmartPointer()) {
- cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"),
- QString::SkipEmptyParts);
+ writeConversionsForType(metaClass->qualifiedCppName());
} else {
- cppSignature = classContext.preciseType()->cppSignature().split(QLatin1String("::"),
- QString::SkipEmptyParts);
- }
- while (!cppSignature.isEmpty()) {
- QString signature = cppSignature.join(QLatin1String("::"));
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");" << endl;
- cppSignature.removeFirst();
+ const QString &smartPointerType = classContext.preciseType()->instantiations().at(0)->cppSignature();
+ const QString &smartPointerName = classContext.preciseType()->typeEntry()->name();
+
+ QStringList lst = smartPointerType.split(QLatin1String("::"),
+ Qt::SkipEmptyParts);
+ while (!lst.isEmpty()) {
+ QString signature = lst.join(QLatin1String("::"));
+ writeConversions(QStringLiteral("%1<%2 >").arg(smartPointerName, signature));
+ lst.removeFirst();
+ }
+
+ writeConversionsForType(smartPointerType);
}
s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
@@ -1504,20 +1677,20 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
else
qualifiedCppNameInvocation = classContext.preciseType()->cppSignature();
- s << qualifiedCppNameInvocation << ").name());" << endl;
+ s << qualifiedCppNameInvocation << ").name());\n";
- if (shouldGenerateCppWrapper(metaClass)) {
+ if (classContext.useWrapper()) {
s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
- s << wrapperName(metaClass) << ").name());" << endl;
+ s << classContext.wrapperName() << ").name());\n";
}
- s << endl;
+ s << Qt::endl;
if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer())
return;
// Python to C++ copy (value, not pointer neither reference) conversion.
- s << INDENT << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter." << endl;
+ s << INDENT << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter.\n";
QString sourceTypeName = metaClass->name();
QString targetTypeName = sourceTypeName + QLatin1String("_COPY");
QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
@@ -1538,7 +1711,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
}
if (!implicitConvs.isEmpty())
- s << INDENT << "// Add implicit conversions to type converter." << endl;
+ s << INDENT << "// Add implicit conversions to type converter.\n";
AbstractMetaType *targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
for (const AbstractMetaFunction *conv : qAsConst(implicitConvs)) {
@@ -1568,7 +1741,7 @@ void CppGenerator::writeCustomConverterRegister(QTextStream &s, const CustomConv
const CustomConversion::TargetToNativeConversions &toCppConversions = customConversion->targetToNativeConversions();
if (toCppConversions.isEmpty())
return;
- s << INDENT << "// Add user defined implicit conversions to type converter." << endl;
+ s << INDENT << "// Add user defined implicit conversions to type converter.\n";
for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) {
QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType());
QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType());
@@ -1582,11 +1755,36 @@ void CppGenerator::writeContainerConverterFunctions(QTextStream &s, const Abstra
writePythonToCppConversionFunctions(s, containerType);
}
+void CppGenerator::writeSmartPointerConverterFunctions(QTextStream &s, const AbstractMetaType *smartPointerType)
+{
+ const AbstractMetaClass *targetClass = AbstractMetaClass::findClass(classes(), smartPointerType->instantiations().at(0)->typeEntry());
+
+ if (targetClass) {
+ const auto *smartPointerTypeEntry =
+ static_cast<const SmartPointerTypeEntry *>(
+ smartPointerType->typeEntry());
+
+ // TODO: Missing conversion to smart pointer pointer type:
+
+ s << "// Register smartpointer conversion for all derived classes\n";
+ const auto classes = getBaseClasses(targetClass);
+ for (auto k : classes) {
+ if (smartPointerTypeEntry->matchesInstantiation(k->typeEntry())) {
+ if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry())) {
+ s << INDENT << "// SmartPointer derived class: " << smartTargetType->cppSignature() << "\n";
+ writePythonToCppConversionFunctions(s, smartPointerType, smartTargetType, {}, {}, {});
+ }
+ }
+ }
+ }
+}
+
void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
- const AbstractMetaClass *ownerClass = rfunc->ownerClass();
+ const AbstractMetaClass *ownerClass = rfunc->targetLangOwner();
+ Q_ASSERT(ownerClass == context.metaClass());
int minArgs = overloadData.minArgs();
int maxArgs = overloadData.maxArgs();
bool initPythonArguments;
@@ -1604,19 +1802,18 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
else
qualifiedCppName = context.preciseType()->cppSignature();
- s << qualifiedCppName << " >()))" << endl;
+ s << qualifiedCppName << " >()))\n";
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl;
}
// Declare pointer for the underlying C++ object.
s << INDENT << "::";
if (!context.forSmartPointer()) {
- s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass)
- : ownerClass->qualifiedCppName());
+ s << (context.useWrapper() ? context.wrapperName() : ownerClass->qualifiedCppName());
} else {
- s << context.preciseType()->cppSignature();
+ s << context.smartPointerWrapperName();
}
- s << " *cptr{};" << endl;
+ s << " *cptr{};\n";
initPythonArguments = maxArgs > 0;
usesNamedArguments = !ownerClass->isQObject() && overloadData.hasArgumentWithDefaultValue();
@@ -1627,40 +1824,42 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over
writeCppSelfDefinition(s, rfunc, context, overloadData.hasStaticFunction());
}
if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType())
- s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};" << endl;
+ s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};\n";
initPythonArguments = minArgs != maxArgs || maxArgs > 1;
usesNamedArguments = rfunc->isCallOperator() || overloadData.hasArgumentWithDefaultValue();
}
+ s << INDENT << "PyObject *errInfo{};\n";
+ s << INDENT << "SBK_UNUSED(errInfo)\n";
+ s << INDENT << "static const char *fullName = \""
+ << fullPythonFunctionName(rfunc, true) << "\";\n";
+ s << INDENT << "SBK_UNUSED(fullName)\n";
if (maxArgs > 0) {
- s << INDENT << "int overloadId = -1;" << endl;
+ s << INDENT << "int overloadId = -1;\n";
s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR;
if (pythonFunctionWrapperUsesListOfArguments(overloadData)) {
s << "[] = { " << NULL_PTR;
for (int i = 1; i < maxArgs; ++i)
s << ", " << NULL_PTR;
- s << " };" << endl;
+ s << " };\n";
} else {
- s << "{};" << endl;
+ s << "{};\n";
}
writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR));
}
- if (usesNamedArguments && !rfunc->isCallOperator())
- s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl;
-
if (initPythonArguments) {
- s << INDENT << "int numArgs = ";
+ s << INDENT << "const Py_ssize_t numArgs = ";
if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData))
- s << "(" << PYTHON_ARG << " == 0 ? 0 : 1);" << endl;
+ s << "(" << PYTHON_ARG << " == 0 ? 0 : 1);\n";
else
writeArgumentsInitializer(s, overloadData);
}
}
void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads,
- GeneratorContext &classContext)
+ const GeneratorContext &classContext)
{
ErrorCode errorCode(-1);
OverloadData overloadData(overloads, this);
@@ -1668,116 +1867,90 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
const AbstractMetaClass *metaClass = rfunc->ownerClass();
- s << "static int" << endl;
- s << cpythonFunctionName(rfunc) << "(PyObject *self, PyObject *args, PyObject *kwds)" << endl;
- s << '{' << endl;
+ s << "static int\n";
+ s << cpythonFunctionName(rfunc) << "(PyObject *self, PyObject *args, PyObject *kwds)\n{\n";
- QSet<QString> argNamesSet;
- if (usePySideExtensions() && metaClass->isQObject()) {
- // Write argNames variable with all known argument names.
- const OverloadData::MetaFunctionList &overloads = overloadData.overloads();
- for (const AbstractMetaFunction *func : overloads) {
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument *arg : arguments) {
- if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1))
- continue;
- argNamesSet << arg->name();
- }
- }
- QStringList argNamesList = argNamesSet.values();
- std::sort(argNamesList.begin(), argNamesList.end());
- if (argNamesList.isEmpty()) {
- s << INDENT << "const char **argNames{};" << endl;
- } else {
- s << INDENT << "const char *argNames[] = {\""
- << argNamesList.join(QLatin1String("\", \"")) << "\"};" << endl;
- }
- s << INDENT << "const QMetaObject *metaObject;" << endl;
- }
+ if (usePySideExtensions() && metaClass->isQObject())
+ s << INDENT << "const QMetaObject *metaObject;\n";
- s << INDENT << "SbkObject *sbkSelf = reinterpret_cast<SbkObject *>(self);" << endl;
+ s << INDENT << "SbkObject *sbkSelf = reinterpret_cast<SbkObject *>(self);\n";
if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) {
- s << INDENT << "SbkObjectType *type = reinterpret_cast<SbkObjectType *>(self->ob_type);" << endl;
- s << INDENT << "SbkObjectType *myType = reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl;
+ s << INDENT << "SbkObjectType *type = reinterpret_cast<SbkObjectType *>(self->ob_type);\n";
+ s << INDENT << "SbkObjectType *myType = reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");\n";
}
if (metaClass->isAbstract()) {
- s << INDENT << "if (type == myType) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "\"'" << metaClass->qualifiedCppName();
- }
- s << "' represents a C++ abstract class and cannot be instantiated\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
- }
- s << INDENT << '}' << endl << endl;
+ s << INDENT << "if (type == myType) {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_NotImplementedError,\n" << indent(INDENT)
+ << INDENT << "\"'" << metaClass->qualifiedCppName()
+ << "' represents a C++ abstract class and cannot be instantiated\");\n" << outdent(INDENT)
+ << INDENT << returnStatement(m_currentErrorCode) << '\n' << outdent(INDENT)
+ << INDENT<< "}\n\n";
}
if (metaClass->baseClassNames().size() > 1) {
- if (!metaClass->isAbstract()) {
- s << INDENT << "if (type != myType) {" << endl;
- }
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::ObjectType::copyMultipleInheritance(type, myType);" << endl;
- }
if (!metaClass->isAbstract())
- s << INDENT << '}' << endl << endl;
+ s << INDENT << "if (type != myType)\n" << indent(INDENT);
+ s << INDENT << "Shiboken::ObjectType::copyMultipleInheritance(type, myType);\n";
+ if (!metaClass->isAbstract())
+ s << outdent(INDENT) << '\n';
}
writeMethodWrapperPreamble(s, overloadData, classContext);
- s << endl;
+ s << Qt::endl;
if (overloadData.maxArgs() > 0)
writeOverloadedFunctionDecisor(s, overloadData);
writeFunctionCalls(s, overloadData, classContext);
- s << endl;
+ s << Qt::endl;
- s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl;
+ s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "delete cptr;" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "delete cptr;\n";
+ if (overloadData.maxArgs() > 0)
+ s << INDENT << "Py_XDECREF(errInfo);\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
if (overloadData.maxArgs() > 0) {
- s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;" << endl;
- s << endl;
+ s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;\n";
+ s << Qt::endl;
}
- s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);" << endl;
+ s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);\n";
// If the created C++ object has a C++ wrapper the ownership is assigned to Python
// (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper
// is marked as true (the second "1"). Otherwise the default values apply:
// Python owns it and C++ wrapper is false.
if (shouldGenerateCppWrapper(overloads.constFirst()->ownerClass()))
- s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl;
+ s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);\n";
// Need to check if a wrapper for same pointer is already registered
// Caused by bug PYSIDE-217, where deleted objects' wrappers are not released
- s << INDENT << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {" << endl;
+ s << INDENT << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "Shiboken::BindingManager::instance().releaseWrapper(Shiboken::BindingManager::instance().retrieveWrapper(cptr));" << endl;
+ s << INDENT << "Shiboken::BindingManager::instance().releaseWrapper("
+ "Shiboken::BindingManager::instance().retrieveWrapper(cptr));\n";
}
- s << INDENT << "}" << endl;
- s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl;
+ s << INDENT << "}\n";
+ s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);\n";
// Create metaObject and register signal/slot
+ bool errHandlerNeeded = overloadData.maxArgs() > 0;
if (metaClass->isQObject() && usePySideExtensions()) {
- s << endl << INDENT << "// QObject setup" << endl;
- s << INDENT << "PySide::Signal::updateSourceObject(self);" << endl;
- s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl;
- s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
- }
+ errHandlerNeeded = true;
+ s << Qt::endl << INDENT << "// QObject setup\n";
+ s << INDENT << "PySide::Signal::updateSourceObject(self);\n";
+ s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties\n";
+ s << INDENT << "if (errInfo && PyDict_Check(errInfo)) {\n" << indent(INDENT)
+ << INDENT << "if (!PySide::fillQtProperties(self, metaObject, errInfo))\n" << indent(INDENT)
+ << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n" << outdent(INDENT)
+ << INDENT << "Py_DECREF(errInfo);\n" << outdent(INDENT)
+ << INDENT << "};\n";
}
// Constructor code injections, position=end
@@ -1793,35 +1966,36 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun
}
if (hasCodeInjectionsAtEnd) {
// FIXME: C++ arguments are not available in code injection on constructor when position = end.
- s << INDENT << "switch(overloadId) {" << endl;
+ s << INDENT << "switch (overloadId) {\n";
for (AbstractMetaFunction *func : overloads) {
Indentation indent(INDENT);
const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips();
for (const CodeSnip &cs : injectedCodeSnips) {
if (cs.position == TypeSystem::CodeSnipPositionEnd) {
- s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl;
- s << INDENT << '{' << endl;
+ s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << Qt::endl;
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func);
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n"
+ << INDENT << "break;\n";
break;
}
}
}
- s << '}' << endl;
+ s << "}\n";
}
- s << endl;
- s << endl << INDENT << "return 1;" << endl;
- if (overloadData.maxArgs() > 0)
+ s << Qt::endl;
+ s << Qt::endl << INDENT << "return 1;\n";
+ if (errHandlerNeeded)
writeErrorSection(s, overloadData);
- s << '}' << endl << endl;
+ s<< "}\n\n";
}
void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList &overloads,
- GeneratorContext &classContext)
+ const GeneratorContext &classContext)
{
OverloadData overloadData(overloads, this);
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
@@ -1835,11 +2009,11 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator())
s << ", PyObject *kwds";
}
- s << ')' << endl << '{' << endl;
+ s << ")\n{\n";
writeMethodWrapperPreamble(s, overloadData, classContext);
- s << endl;
+ s << Qt::endl;
/*
* This code is intended for shift operations only:
@@ -1855,45 +2029,49 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
&& !rfunc->isInplaceOperator()
&& !rfunc->isCallOperator()
&& rfunc->isOperatorOverload();
+
+ QScopedPointer<Indentation> reverseIndent;
+
if (callExtendedReverseOperator) {
QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, QLatin1Char('r'));
// For custom classes, operations like __radd__ and __rmul__
// will enter an infinite loop.
if (rfunc->isBinaryOperator() && revOpName.contains(QLatin1String("shift"))) {
- s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"" << revOpName << "\"));" << endl;
- s << INDENT << "if (!isReverse" << endl;
+ s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"" << revOpName << "\"));\n";
+ s << INDENT << "if (!isReverse\n";
{
Indentation indent(INDENT);
- s << INDENT << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")" << endl;
- s << INDENT << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)" << endl;
- s << INDENT << "&& PyObject_HasAttr(" << PYTHON_ARG << ", attrName)) {" << endl;
+ s << INDENT << "&& Shiboken::Object::checkType(" << PYTHON_ARG << ")\n";
+ s << INDENT << "&& !PyObject_TypeCheck(" << PYTHON_ARG << ", self->ob_type)\n";
+ s << INDENT << "&& PyObject_HasAttr(" << PYTHON_ARG << ", attrName)) {\n";
// This PyObject_CallMethod call will emit lots of warnings like
// "deprecated conversion from string constant to char *" during compilation
// due to the method name argument being declared as "char *" instead of "const char *"
// issue 6952 http://bugs.python.org/issue6952
- s << INDENT << "PyObject *revOpMethod = PyObject_GetAttr(" << PYTHON_ARG << ", attrName);" << endl;
- s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl;
+ s << INDENT << "PyObject *revOpMethod = PyObject_GetAttr(" << PYTHON_ARG << ", attrName);\n";
+ s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {\n";
{
Indentation indent(INDENT);
- s << INDENT << PYTHON_RETURN_VAR << " = PyObject_CallFunction(revOpMethod, const_cast<char *>(\"O\"), self);" << endl;
+ s << INDENT << PYTHON_RETURN_VAR << " = PyObject_CallFunction(revOpMethod, const_cast<char *>(\"O\"), self);\n";
s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)";
- s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl;
+ s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_Clear();" << endl;
- s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");" << endl;
- s << INDENT << PYTHON_RETURN_VAR << " = " << NULL_PTR << ';' << endl;
+ s << INDENT << "PyErr_Clear();\n";
+ s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n";
+ s << INDENT << PYTHON_RETURN_VAR << " = " << NULL_PTR << ";\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
- s << INDENT << "}" << endl;
- s << INDENT << "Py_XDECREF(revOpMethod);" << endl << endl;
- }
- s << INDENT << "}" << endl;
- }
- s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl;
- s << INDENT << "if (!" << PYTHON_RETURN_VAR << ") {" << endl << endl;
+ s << INDENT << "}\n";
+ s << INDENT << "Py_XDECREF(revOpMethod);\n\n";
+ } //
+ s << INDENT << "}\n\n";
+ s << INDENT << "// Do not enter here if other object has implemented a reverse operator.\n";
+ s << INDENT << "if (!" << PYTHON_RETURN_VAR << ") {\n";
+ reverseIndent.reset(new Indentation(INDENT));
+ } // binary shift operator
}
if (maxArgs > 0)
@@ -1901,10 +2079,12 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
writeFunctionCalls(s, overloadData, classContext);
- if (callExtendedReverseOperator)
- s << endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"" << endl;
+ if (!reverseIndent.isNull()) { // binary shift operator
+ reverseIndent.reset();
+ s << Qt::endl << INDENT << "} // End of \"if (!" << PYTHON_RETURN_VAR << ")\"\n";
+ }
- s << endl;
+ s << Qt::endl;
writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator());
@@ -1916,19 +2096,19 @@ void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunction
s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n";
}
} else {
- s << INDENT << "Py_RETURN_NONE;" << endl;
+ s << INDENT << "Py_RETURN_NONE;\n";
}
if (maxArgs > 0)
writeErrorSection(s, overloadData);
- s << '}' << endl << endl;
+ s<< "}\n\n";
}
void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overloadData)
{
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
- s << "PyTuple_GET_SIZE(args);" << endl;
+ s << "PyTuple_GET_SIZE(args);\n";
writeUnusedVariableCast(s, QLatin1String("numArgs"));
int minArgs = overloadData.minArgs();
@@ -1936,33 +2116,36 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl
s << INDENT << "PyObject *";
s << PYTHON_ARGS << "[] = {"
- << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), QString::SkipEmptyParts).join(QLatin1String(", "))
- << "};" << endl;
- s << endl;
+ << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), Qt::SkipEmptyParts).join(QLatin1String(", "))
+ << "};\n";
+ s << Qt::endl;
if (overloadData.hasVarargs()) {
maxArgs--;
if (minArgs > maxArgs)
minArgs = maxArgs;
- s << INDENT << "PyObject *nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl;
- s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl;
- s << INDENT << PYTHON_ARGS << '[' << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl;
- s << INDENT << "Shiboken::AutoDecRef auto_varargs(" << PYTHON_ARGS << "[" << maxArgs << "]);" << endl;
- s << endl;
+ s << INDENT << "PyObject *nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");\n";
+ s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);\n";
+ s << INDENT << PYTHON_ARGS << '[' << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);\n";
+ s << INDENT << "Shiboken::AutoDecRef auto_varargs(" << PYTHON_ARGS << "[" << maxArgs << "]);\n";
+ s << Qt::endl;
}
bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue();
- s << INDENT << "// invalid argument lengths" << endl;
+ s << INDENT << "// invalid argument lengths\n";
bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor();
if (usesNamedArguments) {
if (!ownerClassIsQObject) {
- s << INDENT << "if (numArgs" << (overloadData.hasArgumentWithDefaultValue() ? " + numNamedArgs" : "") << " > " << maxArgs << ") {" << endl;
+ s << INDENT << "if (numArgs > " << maxArgs << ") {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "static PyObject *const too_many = "
+ "Shiboken::String::createStaticString(\">\");\n";
+ s << INDENT << "errInfo = too_many;\n";
+ s << INDENT << "Py_INCREF(errInfo);\n";
+ s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n";
}
s << INDENT << '}';
}
@@ -1971,11 +2154,14 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl
s << INDENT;
else
s << " else ";
- s << "if (numArgs < " << minArgs << ") {" << endl;
+ s << "if (numArgs < " << minArgs << ") {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "static PyObject *const too_few = "
+ "Shiboken::String::createStaticString(\"<\");\n";
+ s << INDENT << "errInfo = too_few;\n";
+ s << INDENT << "Py_INCREF(errInfo);\n";
+ s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;\n";
}
s << INDENT << '}';
}
@@ -1989,11 +2175,11 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl
s << " else ";
else
s << INDENT;
- s << "if (" << invArgsLen.join(QLatin1String(" || ")) << ")" << endl;
+ s << "if (" << invArgsLen.join(QLatin1String(" || ")) << ")\n";
Indentation indent(INDENT);
s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;";
}
- s << endl << endl;
+ s << Qt::endl << Qt::endl;
QString funcName;
if (rfunc->isOperatorOverload())
@@ -2009,24 +2195,18 @@ void CppGenerator::writeArgumentsInitializer(QTextStream &s, OverloadData &overl
s << "PyArg_UnpackTuple(" << argsVar << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs;
for (int i = 0; i < maxArgs; i++)
s << ", &(" << PYTHON_ARGS << '[' << i << "])";
- s << "))" << endl;
+ s << "))\n";
{
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
- s << endl;
+ s << Qt::endl;
}
-void CppGenerator::writeCppSelfAssigment(QTextStream &s, const GeneratorContext &context,
- const QString &className, bool cppSelfAsReference,
- bool useWrapperClass)
+void CppGenerator::writeCppSelfConversion(QTextStream &s, const GeneratorContext &context,
+ const QString &className, bool useWrapperClass)
{
static const QString pythonSelfVar = QLatin1String("self");
- if (cppSelfAsReference)
- s << className << " &";
- s << CPP_SELF_VAR << " = ";
- if (cppSelfAsReference)
- s << " *";
if (useWrapperClass)
s << "static_cast<" << className << " *>(";
if (!context.forSmartPointer())
@@ -2038,49 +2218,58 @@ void CppGenerator::writeCppSelfAssigment(QTextStream &s, const GeneratorContext
}
void CppGenerator::writeCppSelfDefinition(QTextStream &s,
- GeneratorContext &context,
+ const GeneratorContext &context,
bool hasStaticOverload,
bool cppSelfAsReference)
{
+ Q_ASSERT(!(cppSelfAsReference && hasStaticOverload));
+
const AbstractMetaClass *metaClass = context.metaClass();
- bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers();
+ bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers()
+ && !metaClass->attributes().testFlag(AbstractMetaAttributes::FinalCppClass);
+ Q_ASSERT(!useWrapperClass || context.useWrapper());
QString className;
if (!context.forSmartPointer()) {
className = useWrapperClass
- ? wrapperName(metaClass)
+ ? context.wrapperName()
: (QLatin1String("::") + metaClass->qualifiedCppName());
} else {
- className = context.preciseType()->cppSignature();
+ className = context.smartPointerWrapperName();
}
- if (!cppSelfAsReference) {
- s << INDENT << className << " *" << CPP_SELF_VAR << " = nullptr;" << endl;
- writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
+ writeInvalidPyObjectCheck(s, QLatin1String("self"));
+
+ if (cppSelfAsReference) {
+ s << INDENT << "auto &" << CPP_SELF_VAR << " = *";
+ writeCppSelfConversion(s, context, className, useWrapperClass);
+ s << ";\n";
+ return;
}
- // Checks if the underlying C++ object is valid.
- if (hasStaticOverload && !cppSelfAsReference) {
- s << INDENT << "if (self) {" << endl;
- {
- Indentation indent(INDENT);
- writeInvalidPyObjectCheck(s, QLatin1String("self"));
- s << INDENT;
- writeCppSelfAssigment(s, context, className, cppSelfAsReference, useWrapperClass);
- s << ';' << endl;
- }
- s << INDENT << '}' << endl;
+ if (!hasStaticOverload) {
+ s << INDENT << "auto " << CPP_SELF_VAR << " = ";
+ writeCppSelfConversion(s, context, className, useWrapperClass);
+ s << ";\n";
+ writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
return;
}
- writeInvalidPyObjectCheck(s, QLatin1String("self"));
- s << INDENT;
- writeCppSelfAssigment(s, context, className, cppSelfAsReference, useWrapperClass);
- s << ';' << endl;
+ s << INDENT << className << " *" << CPP_SELF_VAR << " = nullptr;\n";
+ writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
+
+ // Checks if the underlying C++ object is valid.
+ s << INDENT << "if (self)\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << CPP_SELF_VAR << " = ";
+ writeCppSelfConversion(s, context, className, useWrapperClass);
+ s << ";\n";
+ }
}
void CppGenerator::writeCppSelfDefinition(QTextStream &s,
const AbstractMetaFunction *func,
- GeneratorContext &context,
+ const GeneratorContext &context,
bool hasStaticOverload)
{
if (!func->ownerClass() || func->isConstructor())
@@ -2088,14 +2277,14 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
if (func->isOperatorOverload() && func->isBinaryOperator()) {
QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry());
- s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG << ')' << endl;
+ s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG << ")\n";
{
Indentation indent1(INDENT, 4);
- s << INDENT << "&& !" << checkFunc << "self);" << endl;
+ s << INDENT << "&& !" << checkFunc << "self);\n";
}
- s << INDENT << "if (isReverse)" << endl;
+ s << INDENT << "if (isReverse)\n";
Indentation indent(INDENT);
- s << INDENT << "std::swap(self, " << PYTHON_ARG << ");" << endl;
+ s << INDENT << "std::swap(self, " << PYTHON_ARG << ");\n";
}
writeCppSelfDefinition(s, context, hasStaticOverload);
@@ -2104,14 +2293,16 @@ void CppGenerator::writeCppSelfDefinition(QTextStream &s,
void CppGenerator::writeErrorSection(QTextStream &s, OverloadData &overloadData)
{
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
- s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:" << endl;
+ s << Qt::endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:\n";
Indentation indentation(INDENT);
- QString funcName = fullPythonFunctionName(rfunc);
+ QString funcName = fullPythonFunctionName(rfunc, true);
QString argsVar = pythonFunctionWrapperUsesListOfArguments(overloadData)
? QLatin1String("args") : QLatin1String(PYTHON_ARG);
- s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\");" << endl;
- s << INDENT << "return " << m_currentErrorCode << ';' << endl;
+ s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar
+ << ", fullName, errInfo);\n";
+ s << INDENT << "Py_XDECREF(errInfo);\n";
+ s << INDENT << "return " << m_currentErrorCode << ";\n";
}
void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream &s, bool hasReturnValue)
@@ -2119,21 +2310,21 @@ void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream &s, bool has
s << INDENT << "if (PyErr_Occurred()";
if (hasReturnValue)
s << " || !" << PYTHON_RETURN_VAR;
- s << ") {" << endl;
+ s << ") {\n";
{
Indentation indent(INDENT);
if (hasReturnValue)
- s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "Py_XDECREF(" << PYTHON_RETURN_VAR << ");\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
void CppGenerator::writeInvalidPyObjectCheck(QTextStream &s, const QString &pyObj)
{
- s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))" << endl;
+ s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))\n";
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
static QString pythonToCppConverterForArgumentName(const QString &argumentName)
@@ -2187,6 +2378,7 @@ void CppGenerator::writeTypeCheck(QTextStream &s, const AbstractMetaType *argTyp
static void checkTypeViability(const AbstractMetaFunction *func, const AbstractMetaType *type, int argIdx)
{
if (!type
+ || type->isVoid()
|| !type->typeEntry()->isPrimitive()
|| type->indirections() == 0
|| (type->indirections() == 1 && type->typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern)
@@ -2198,7 +2390,8 @@ static void checkTypeViability(const AbstractMetaFunction *func, const AbstractM
return;
QString message;
QTextStream str(&message);
- str << "There's no user provided way (conversion rule, argument"
+ str << func->sourceLocation()
+ << "There's no user provided way (conversion rule, argument"
" removal, custom code, etc) to handle the primitive ";
if (argIdx == 0)
str << "return type '" << type->cppSignature() << '\'';
@@ -2336,7 +2529,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s,
if (mayHaveImplicitConversion) {
s << INDENT << typeName << ' ' << cppOutAux;
writeMinimalConstructorExpression(s, type, defaultValue);
- s << ';' << endl;
+ s << ";\n";
} else if (avoidProtectedHack() && type->typeEntry()->isEnum()) {
const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(type);
if (metaEnum && metaEnum->isProtected()) {
@@ -2350,8 +2543,17 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s,
s << ' ' << cppOut;
} else if (treatAsPointer || isPointerOrObjectType) {
s << " *" << cppOut;
- if (!defaultValue.isEmpty())
- s << " = " << defaultValue;
+ if (!defaultValue.isEmpty()) {
+ const bool needsConstCast = !isNullPtr(defaultValue)
+ && type->indirections() == 1 && type->isConstant()
+ && type->referenceType() == NoReference;
+ s << " = ";
+ if (needsConstCast)
+ s << "const_cast<" << typeName << " *>(";
+ s << defaultValue;
+ if (needsConstCast)
+ s << ')';
+ }
} else if (type->referenceType() == LValueReference && !typeEntry->isPrimitive() && isNotContainerEnumOrFlags) {
s << " *" << cppOut << " = &" << cppOutAux;
} else {
@@ -2368,7 +2570,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s,
writeMinimalConstructorExpression(s, type, defaultValue);
}
}
- s << ';' << endl;
+ s << ";\n";
QString pythonToCppFunc = pythonToCppConverterForArgumentName(pyIn);
@@ -2378,28 +2580,28 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream &s,
QString pythonToCppCall = QString::fromLatin1("%1(%2, &%3)").arg(pythonToCppFunc, pyIn, cppOut);
if (!mayHaveImplicitConversion) {
- s << pythonToCppCall << ';' << endl;
+ s << pythonToCppCall << ";\n";
return;
}
if (!defaultValue.isEmpty())
- s << '{' << endl << INDENT;
+ s << "{\n" << INDENT;
s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast<SbkObjectType *>("
- << cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))" << endl;
+ << cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))\n";
{
Indentation indent(INDENT);
- s << INDENT << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");" << endl;
+ s << INDENT << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");\n";
}
- s << INDENT << "else" << endl;
+ s << INDENT << "else\n";
{
Indentation indent(INDENT);
- s << INDENT << pythonToCppCall << ';' << endl;
+ s << INDENT << pythonToCppCall << ";\n";
}
if (!defaultValue.isEmpty())
s << INDENT << '}';
- s << endl;
+ s << Qt::endl;
}
static void addConversionRuleCodeSnippet(CodeSnipList &snippetList, QString &rule,
@@ -2444,15 +2646,15 @@ void CppGenerator::writeConversionRule(QTextStream &s, const AbstractMetaFunctio
void CppGenerator::writeNoneReturn(QTextStream &s, const AbstractMetaFunction *func, bool thereIsReturnValue)
{
- if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) {
- s << INDENT << PYTHON_RETURN_VAR << " = Py_None;" << endl;
- s << INDENT << "Py_INCREF(Py_None);" << endl;
+ if (thereIsReturnValue && (func->isVoid() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) {
+ s << INDENT << PYTHON_RETURN_VAR << " = Py_None;\n";
+ s << INDENT << "Py_INCREF(Py_None);\n";
}
}
void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const OverloadData &overloadData)
{
- s << INDENT << "// Overloaded function decisor" << endl;
+ s << INDENT << "// Overloaded function decisor\n";
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
const OverloadData::MetaFunctionList &functionOverloads = overloadData.overloadsWithoutRepetition();
for (int i = 0; i < functionOverloads.count(); i++) {
@@ -2462,26 +2664,26 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream &s, const Overload
s << "static ";
if (const auto *decl = func->declaringClass())
s << decl->name() << "::";
- s << func->minimalSignature() << endl;
+ s << func->minimalSignature() << Qt::endl;
}
writeOverloadedFunctionDecisorEngine(s, &overloadData);
- s << endl;
+ s << Qt::endl;
// Ensure that the direct overload that called this reverse
// is called.
if (rfunc->isOperatorOverload() && !rfunc->isCallOperator()) {
- s << INDENT << "if (isReverse && overloadId == -1) {" << endl;
+ s << INDENT << "if (isReverse && overloadId == -1) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"reverse operator not implemented.\");" << endl;
- s << INDENT << "return {};" << endl;
+ s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"reverse operator not implemented.\");\n";
+ s << INDENT << "return {};\n";
}
- s << INDENT << "}" << endl << endl;
+ s << INDENT << "}\n\n";
}
- s << INDENT << "// Function signature not found." << endl;
- s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;" << endl;
- s << endl;
+ s << INDENT << "// Function signature not found.\n";
+ s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;\n";
+ s << Qt::endl;
}
void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const OverloadData *parentOverloadData)
@@ -2512,7 +2714,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
// Functions without arguments are identified right away.
if (maxArgs == 0) {
s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction);
- s << "; // " << referenceFunction->minimalSignature() << endl;
+ s << "; // " << referenceFunction->minimalSignature() << Qt::endl;
return;
}
@@ -2528,7 +2730,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
if (isLastArgument || (signatureFound && !hasDefaultCall)) {
const AbstractMetaFunction *func = parentOverloadData->referenceFunction();
s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func);
- s << "; // " << func->minimalSignature() << endl;
+ s << "; // " << func->minimalSignature() << Qt::endl;
return;
}
}
@@ -2542,7 +2744,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
if (hasDefaultCall) {
isFirst = false;
int numArgs = parentOverloadData->argPos() + 1;
- s << INDENT << "if (numArgs == " << numArgs << ") {" << endl;
+ s << INDENT << "if (numArgs == " << numArgs << ") {\n";
{
Indentation indent(INDENT);
const AbstractMetaFunction *func = referenceFunction;
@@ -2554,7 +2756,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
}
}
s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func);
- s << "; // " << func->minimalSignature() << endl;
+ s << "; // " << func->minimalSignature() << Qt::endl;
}
s << INDENT << '}';
}
@@ -2587,7 +2789,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
const AbstractMetaClass *ownerClass = func->ownerClass();
const ComplexTypeEntry *baseContainerType = ownerClass->typeEntry()->baseContainerType();
if (baseContainerType && baseContainerType == func->arguments().constFirst()->type()->typeEntry() && isCopyable(ownerClass)) {
- tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ')' << endl;
+ tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ")\n";
Indentation indent(INDENT);
tck << INDENT << "&& ";
}
@@ -2611,9 +2813,11 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
if (usePyArgs && signatureFound) {
AbstractMetaArgumentList args = refFunc->arguments();
- int lastArgIsVarargs = (int) (args.size() > 1 && args.constLast()->type()->isVarargs());
- int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs;
- typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs));
+ const bool isVarargs = args.size() > 1 && args.constLast()->type()->isVarargs();
+ int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc);
+ if (isVarargs)
+ --numArgs;
+ typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(isVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs));
} else if (sequenceArgCount > 1) {
typeChecks.prepend(QString::fromLatin1("numArgs >= %1").arg(startArg + sequenceArgCount));
} else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) {
@@ -2633,25 +2837,25 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream &s, const Ov
Indentation indent(INDENT);
QString separator;
QTextStream sep(&separator);
- sep << endl << INDENT << "&& ";
+ sep << Qt::endl << INDENT << "&& ";
s << typeChecks.join(separator);
}
- s << ") {" << endl;
+ s << ") {\n";
{
Indentation indent(INDENT);
writeOverloadedFunctionDecisorEngine(s, overloadData);
}
s << INDENT << "}";
}
- s << endl;
+ s << Qt::endl;
}
void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
const OverloadData::MetaFunctionList &overloads = overloadData.overloadsWithoutRepetition();
- s << INDENT << "// Call function/method" << endl;
- s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl;
+ s << INDENT << "// Call function/method\n";
+ s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << "{\n";
{
Indentation indent(INDENT);
if (overloads.count() == 1) {
@@ -2659,8 +2863,8 @@ void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overlo
} else {
for (int i = 0; i < overloads.count(); i++) {
const AbstractMetaFunction *func = overloads.at(i);
- s << INDENT << "case " << i << ": // " << func->signature() << endl;
- s << INDENT << '{' << endl;
+ s << INDENT << "case " << i << ": // " << func->signature() << Qt::endl;
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
writeSingleFunctionCall(s, overloadData, func, context);
@@ -2670,40 +2874,40 @@ void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overlo
s << cls->name() << '.';
s << func->signature() << " is deprecated\", 1);\n";
}
- s << INDENT << "break;" << endl;
+ s << INDENT << "break;\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
}
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
void CppGenerator::writeSingleFunctionCall(QTextStream &s,
const OverloadData &overloadData,
const AbstractMetaFunction *func,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
if (func->isDeprecated()) {
s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '"
<< func->signature().replace(QLatin1String("::"), QLatin1String("."))
- << "' is marked as deprecated, please check the documentation for more information.\");" << endl;
+ << "' is marked as deprecated, please check the documentation for more information.\");\n";
}
if (func->functionType() == AbstractMetaFunction::EmptyFunction) {
s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \""
<< func->signature().replace(QLatin1String("::"), QLatin1String("."))
- << "\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ << "\");\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
return;
}
bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData);
// Handle named arguments.
- writeNamedArgumentResolution(s, func, usePyArgs);
+ writeNamedArgumentResolution(s, func, usePyArgs, overloadData);
- bool injectCodeCallsFunc = injectedCodeCallsCppFunction(func);
+ bool injectCodeCallsFunc = injectedCodeCallsCppFunction(context, func);
bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc;
int removedArgs = 0;
for (int argIdx = 0; argIdx < func->arguments().count(); ++argIdx) {
@@ -2714,7 +2918,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
const QString cppArgRemoved = QLatin1String(CPP_ARG_REMOVED)
+ QString::number(argIdx);
s << INDENT << getFullTypeName(arg->type()) << ' ' << cppArgRemoved;
- s << " = " << guessScopeForDefaultValue(func, arg) << ';' << endl;
+ s << " = " << guessScopeForDefaultValue(func, arg) << ";\n";
writeUnusedVariableCast(s, cppArgRemoved);
} else if (!injectCodeCallsFunc && !func->isUserAdded() && !hasConversionRule) {
// When an argument is removed from a method signature and no other means of calling
@@ -2737,18 +2941,15 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s,
writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded());
}
- s << endl;
+ s << Qt::endl;
int numRemovedArgs = OverloadData::numberOfRemovedArguments(func);
- s << INDENT << "if (!PyErr_Occurred()) {" << endl;
- {
- Indentation indentation(INDENT);
- writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs);
- if (!func->isConstructor())
- writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
- }
- s << INDENT << '}' << endl;
+ s << INDENT << "if (!PyErr_Occurred()) {\n" << indent(INDENT);
+ writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs);
+ if (!func->isConstructor())
+ writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
+ s << outdent(INDENT) << INDENT << "}\n";
}
QString CppGenerator::cppToPythonFunctionName(const QString &sourceTypeName, QString targetTypeName)
@@ -2794,15 +2995,16 @@ void CppGenerator::writeCppToPythonFunction(QTextStream &s, const QString &code,
processCodeSnip(prettyCode);
s << "static PyObject *" << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- s << "(const void *cppIn) {" << endl;
+ s << "(const void *cppIn) {\n";
s << prettyCode;
- s << '}' << endl;
+ s << "}\n";
}
static void replaceCppToPythonVariables(QString &code, const QString &typeName)
{
- code.prepend(QLatin1String("auto &cppInRef = *reinterpret_cast<")
- + typeName + QLatin1String(" *>(const_cast<void *>(cppIn));\n"));
+ const QString line = QLatin1String("auto &cppInRef = *reinterpret_cast<")
+ + typeName + QLatin1String(" *>(const_cast<void *>(cppIn));");
+ CodeSnipAbstract::prependCode(&code, line);
code.replace(QLatin1String("%INTYPE"), typeName);
code.replace(QLatin1String("%OUTTYPE"), QLatin1String("PyObject *"));
code.replace(QLatin1String("%in"), QLatin1String("cppInRef"));
@@ -2846,9 +3048,9 @@ void CppGenerator::writePythonToCppFunction(QTextStream &s, const QString &code,
formatCode(c, code, INDENT);
processCodeSnip(prettyCode);
s << "static void " << pythonToCppFunctionName(sourceTypeName, targetTypeName);
- s << "(PyObject *pyIn, void *cppOut) {" << endl;
+ s << "(PyObject *pyIn, void *cppOut) {\n";
s << prettyCode;
- s << '}' << endl;
+ s << "}\n";
}
void CppGenerator::writeIsPythonConvertibleToCppFunction(QTextStream &s,
@@ -2862,19 +3064,19 @@ void CppGenerator::writeIsPythonConvertibleToCppFunction(QTextStream &s,
pythonToCppFuncName = pythonToCppFunctionName(sourceTypeName, targetTypeName);
s << "static PythonToCppFunc " << convertibleToCppFunctionName(sourceTypeName, targetTypeName);
- s << "(PyObject *pyIn) {" << endl;
+ s << "(PyObject *pyIn) {\n";
if (acceptNoneAsCppNull) {
- s << INDENT << "if (pyIn == Py_None)" << endl;
+ s << INDENT << "if (pyIn == Py_None)\n";
Indentation indent(INDENT);
- s << INDENT << "return Shiboken::Conversions::nonePythonToCppNullPtr;" << endl;
+ s << INDENT << "return Shiboken::Conversions::nonePythonToCppNullPtr;\n";
}
- s << INDENT << "if (" << condition << ')' << endl;
+ s << INDENT << "if (" << condition << ")\n";
{
Indentation indent(INDENT);
- s << INDENT << "return " << pythonToCppFuncName << ';' << endl;
+ s << INDENT << "return " << pythonToCppFuncName << ";\n";
}
- s << INDENT << "return {};" << endl;
- s << '}' << endl;
+ s << INDENT << "return {};\n";
+ s << "}\n";
}
void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s,
@@ -2889,12 +3091,13 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s,
// Python to C++ conversion function.
QString code;
QTextStream c(&code);
+ Indentor nested;
if (conversion.isEmpty())
- conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn"));
+ conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType, QLatin1String("pyIn"));
if (!preConversion.isEmpty())
- c << INDENT << preConversion << endl;
- const QString fullTypeName = getFullTypeName(targetType->typeEntry());
- c << INDENT << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = "
+ c << nested << preConversion << Qt::endl;
+ const QString fullTypeName = targetType->isSmartPointer() ? targetType->cppSignature() : getFullTypeName(targetType->typeEntry());
+ c << nested << "*reinterpret_cast<" << fullTypeName << " *>(cppOut) = "
<< fullTypeName << '(' << conversion << ");";
QString sourceTypeName = fixedCppTypeName(sourceType);
QString targetTypeName = fixedCppTypeName(targetType);
@@ -2904,7 +3107,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s,
if (typeCheck.isEmpty())
typeCheck = QString::fromLatin1("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType);
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck);
- s << endl;
+ s << Qt::endl;
}
void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s,
@@ -2976,11 +3179,10 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, const Abs
}
// Python to C++ conversion function.
QString cppTypeName = getFullTypeNameWithoutModifiers(containerType);
- QString code;
- QTextStream c(&code);
- c << INDENT << "auto &cppOutRef = *reinterpret_cast<"
- << cppTypeName << " *>(cppOut);\n";
- code.append(toCppConversions.constFirst()->conversion());
+ QString code = toCppConversions.constFirst()->conversion();
+ const QString line = QLatin1String("auto &cppOutRef = *reinterpret_cast<")
+ + cppTypeName + QLatin1String(" *>(cppOut);");
+ CodeSnipAbstract::prependCode(&code, line);
for (int i = 0; i < containerType->instantiations().count(); ++i) {
const AbstractMetaType *type = containerType->instantiations().at(i);
QString typeName = getFullTypeName(type);
@@ -3012,67 +3214,101 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream &s, const Abs
else
typeCheck = QString::fromLatin1("%1pyIn)").arg(typeCheck);
writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck);
- s << endl;
+ s << Qt::endl;
}
void CppGenerator::writeAddPythonToCppConversion(QTextStream &s, const QString &converterVar, const QString &pythonToCppFunc, const QString &isConvertibleFunc)
{
- s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl;
+ s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << Qt::endl;
{
Indentation indent(INDENT);
- s << INDENT << pythonToCppFunc << ',' << endl;
+ s << INDENT << pythonToCppFunc << ',' << Qt::endl;
s << INDENT << isConvertibleFunc;
}
- s << ");" << endl;
+ s << ");\n";
}
-void CppGenerator::writeNamedArgumentResolution(QTextStream &s, const AbstractMetaFunction *func, bool usePyArgs)
+void CppGenerator::writeNamedArgumentResolution(QTextStream &s, const AbstractMetaFunction *func,
+ bool usePyArgs, const OverloadData &overloadData)
{
const AbstractMetaArgumentList &args = OverloadData::getArgumentsWithDefaultValues(func);
- if (args.isEmpty())
+ if (args.isEmpty()) {
+ if (overloadData.hasArgumentWithDefaultValue()) {
+ s << INDENT << "if (kwds) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "errInfo = kwds;\n";
+ s << INDENT << "Py_INCREF(errInfo);\n";
+ s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
+ }
+ s << INDENT << "}\n";
+ }
return;
+ }
- QString pyErrString(QLatin1String("PyErr_SetString(PyExc_TypeError, \"") + fullPythonFunctionName(func)
- + QLatin1String("(): got multiple values for keyword argument '%1'.\");"));
-
- s << INDENT << "if (kwds) {" << endl;
+ s << INDENT << "if (kwds) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyObject *keyName = nullptr;" << endl;
- s << INDENT << "PyObject *value = nullptr;" << endl;
+ s << INDENT << "PyObject *value{};\n";
+ s << INDENT << "PyObject *kwds_dup = PyDict_Copy(kwds);\n";
for (const AbstractMetaArgument *arg : args) {
- int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex());
+ const int pyArgIndex = arg->argumentIndex()
+ - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex());
QString pyArgName = usePyArgs ? pythonArgsAt(pyArgIndex) : QLatin1String(PYTHON_ARG);
- s << INDENT << "keyName = Py_BuildValue(\"s\",\"" << arg->name() << "\");" << endl;
- s << INDENT << "if (PyDict_Contains(kwds, keyName)) {" << endl;
+ QString pyKeyName = QLatin1String("key_") + arg->name();
+ s << INDENT << "static PyObject *const " << pyKeyName
+ << " = Shiboken::String::createStaticString(\"" << arg->name() << "\");\n";
+ s << INDENT << "if (PyDict_Contains(kwds, " << pyKeyName << ")) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "value = PyDict_GetItem(kwds, keyName);" << endl;
- s << INDENT << "if (value && " << pyArgName << ") {" << endl;
+ s << INDENT << "value = PyDict_GetItem(kwds, " << pyKeyName << ");\n";
+ s << INDENT << "if (value && " << pyArgName << ") {\n";
{
Indentation indent(INDENT);
- s << INDENT << pyErrString.arg(arg->name()) << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "errInfo = " << pyKeyName << ";\n";
+ s << INDENT << "Py_INCREF(errInfo);\n";
+ s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
}
- s << INDENT << '}' << endl;
- s << INDENT << "if (value) {" << endl;
+ s << INDENT << "}\n";
+ s << INDENT << "if (value) {\n";
{
Indentation indent(INDENT);
- s << INDENT << pyArgName << " = value;" << endl;
+ s << INDENT << pyArgName << " = value;\n";
s << INDENT << "if (!";
- writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1));
- s << ')' << endl;
+ writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()),
+ func->typeReplaced(arg->argumentIndex() + 1));
+ s << ")\n";
{
Indentation indent(INDENT);
- s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl;
+ s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
}
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
+ s << INDENT << "PyDict_DelItem(kwds_dup, " << pyKeyName << ");\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
+ // PYSIDE-1305: Handle keyword args correctly.
+ // Normal functions handle their parameters immediately.
+ // For constructors that are QObject, we need to delay that
+ // until extra keyword signals and properties are handled.
+ s << INDENT << "if (PyDict_Size(kwds_dup) > 0) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "errInfo = kwds_dup;\n";
+ if (!(func->isConstructor() && func->ownerClass()->isQObject()))
+ s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;\n";
+ else
+ s << INDENT << "// fall through to handle extra keyword signals and properties\n";
+ }
+ s << INDENT << "} else {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "Py_DECREF(kwds_dup);\n";
+ }
+ s << INDENT << "}\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction *func, int argIndex, const AbstractMetaClass **wrappedClass)
@@ -3085,7 +3321,7 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction *func, in
} else if (argIndex == 0) {
AbstractMetaType *funcType = func->type();
AbstractMetaType *returnType = getTypeWithoutContainer(funcType);
- if (returnType) {
+ if (!returnType->isVoid()) {
pyArgName = QLatin1String(PYTHON_RETURN_VAR);
*wrappedClass = AbstractMetaClass::findClass(classes(), returnType->typeEntry());
} else {
@@ -3125,14 +3361,17 @@ static QStringList defaultExceptionHandling()
}
void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func,
- GeneratorContext &context, int maxArgs)
+ const GeneratorContext &context, int maxArgs)
{
- s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl;
+ s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << Qt::endl;
if (func->isConstructor()) {
const CodeSnipList &snips = func->injectedCodeSnips();
for (const CodeSnip &cs : snips) {
if (cs.position == TypeSystem::CodeSnipPositionEnd) {
- s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast<AbstractMetaFunction *const>(func)) << ';' << endl;
+ auto klass = func->ownerClass();
+ s << INDENT << "overloadId = "
+ << klass->functions().indexOf(const_cast<AbstractMetaFunction *>(func))
+ << ";\n";
break;
}
}
@@ -3143,8 +3382,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '";
- s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
s << INDENT << "}\n";
}
@@ -3171,7 +3410,6 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg);
- s << endl;
}
writeConversionRule(s, func, TypeSystem::NativeCode);
@@ -3256,14 +3494,14 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
std::swap(firstArg, secondArg);
QString op = func->originalName();
- op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1));
+ op.remove(0, int(std::strlen("operator")));
if (func->isBinaryOperator()) {
if (func->isReverseOperator())
std::swap(firstArg, secondArg);
if (((op == QLatin1String("++")) || (op == QLatin1String("--"))) && !func->isReverseOperator()) {
- s << endl << INDENT << "for(int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");" << endl;
+ s << Qt::endl << INDENT << "for (int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");\n";
mc << firstArg;
} else {
mc << firstArg << ' ' << op << ' ' << secondArg;
@@ -3271,35 +3509,38 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
} else {
mc << op << ' ' << secondArg;
}
- } else if (!injectedCodeCallsCppFunction(func)) {
+ } else if (!injectedCodeCallsCppFunction(context, func)) {
if (func->isConstructor()) {
isCtor = true;
- QString className = wrapperName(func->ownerClass());
+ const auto owner = func->ownerClass();
+ Q_ASSERT(owner == context.metaClass());
+ QString className = context.useWrapper()
+ ? context.wrapperName() : owner->qualifiedCppName();
if (func->functionType() == AbstractMetaFunction::CopyConstructorFunction && maxArgs == 1) {
mc << "new ::" << className << "(*" << CPP_ARG0 << ')';
} else {
QString ctorCall = className + QLatin1Char('(') + userArgs.join(QLatin1String(", ")) + QLatin1Char(')');
- if (usePySideExtensions() && func->ownerClass()->isQObject()) {
- s << INDENT << "void *addr = PySide::nextQObjectMemoryAddr();" << endl;
- uva << "if (addr) {" << endl;
+ if (usePySideExtensions() && owner->isQObject()) {
+ s << INDENT << "void *addr = PySide::nextQObjectMemoryAddr();\n";
+ uva << "if (addr) {\n";
{
Indentation indent(INDENT);
uva << INDENT << "cptr = " << "new (addr) ::"
- << ctorCall << ';' << endl
+ << ctorCall << ";\n"
<< INDENT
<< "PySide::setNextQObjectMemoryAddr(0);"
- << endl;
+ << Qt::endl;
}
- uva << INDENT << "} else {" << endl;
+ uva << INDENT << "} else {\n";
{
Indentation indent(INDENT);
uva << INDENT << "cptr = " << "new ::"
- << ctorCall << ';' << endl;
+ << ctorCall << ";\n";
}
- uva << INDENT << "}" << endl;
+ uva << INDENT << "}\n";
} else {
mc << "new ::" << ctorCall;
}
@@ -3322,14 +3563,16 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
+ QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
if (func->isConstant()) {
if (avoidProtectedHack()) {
+ auto ownerClass = func->ownerClass();
mc << "const_cast<const ::";
- if (func->ownerClass()->hasProtectedMembers()) {
+ if (ownerClass->hasProtectedMembers()
+ && !ownerClass->attributes().testFlag(AbstractMetaAttributes::FinalCppClass)) {
// PYSIDE-500: Need a special wrapper cast when inherited
- const QString selfWrapCast = func->ownerClass() == func->implementingClass()
+ const QString selfWrapCast = ownerClass == func->implementingClass()
? QLatin1String(CPP_SELF_VAR)
- : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass())
+ : QLatin1String("reinterpret_cast<") + wrapperName(ownerClass)
+ QLatin1String(" *>(") + QLatin1String(CPP_SELF_VAR) + QLatin1Char(')');
- mc << wrapperName(func->ownerClass());
+ mc << wrapperName(ownerClass);
mc << " *>(" << selfWrapCast << ")->";
}
else {
@@ -3372,18 +3615,19 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
if (!avoidProtectedHack() || !func->isProtected()) {
QString virtualCall(methodCall);
QString normalCall(methodCall);
- virtualCall = virtualCall.replace(QLatin1String("%CLASS_NAME"),
- methodCallClassName);
+ virtualCall.replace(QLatin1String("%CLASS_NAME"),
+ methodCallClassName);
normalCall.remove(QLatin1String("::%CLASS_NAME::"));
methodCall.clear();
- mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>(self)) ? ";
- mc << virtualCall << " : " << normalCall;
+ mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>(self))\n"
+ << INDENT << " ? " << virtualCall << '\n'
+ << INDENT << " : " << normalCall;
}
}
}
}
- if (!injectedCodeCallsCppFunction(func)) {
+ if (!injectedCodeCallsCppFunction(context, func)) {
const bool allowThread = func->allowThread();
const bool generateExceptionHandling = func->generateExceptionHandling();
if (generateExceptionHandling) {
@@ -3394,13 +3638,13 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
<< INDENT << "threadSaver.save();\n";
}
} else if (allowThread) {
- s << INDENT << BEGIN_ALLOW_THREADS << endl;
+ s << INDENT << BEGIN_ALLOW_THREADS << Qt::endl;
}
s << INDENT;
if (isCtor) {
s << (useVAddr.isEmpty() ?
- QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl;
- } else if (func->type() && !func->isInplaceOperator()) {
+ QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << Qt::endl;
+ } else if (!func->isVoid() && !func->isInplaceOperator()) {
bool writeReturnType = true;
if (avoidProtectedHack()) {
const AbstractMetaEnum *metaEnum = findAbstractMetaEnum(func->type());
@@ -3425,9 +3669,9 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
}
s << " " << CPP_RETURN_VAR << " = ";
- s << methodCall << ';' << endl;
+ s << methodCall << ";\n";
} else {
- s << methodCall << ';' << endl;
+ s << methodCall << ";\n";
}
if (allowThread) {
@@ -3438,7 +3682,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
// Convert result
if (!func->conversionRule(TypeSystem::TargetLangCode, 0).isEmpty()) {
writeConversionRule(s, func, TypeSystem::TargetLangCode, QLatin1String(PYTHON_RETURN_VAR));
- } else if (!isCtor && !func->isInplaceOperator() && func->type()
+ } else if (!isCtor && !func->isInplaceOperator() && !func->isVoid()
&& !injectedCodeHasReturnValueAttribution(func, TypeSystem::TargetLangCode)) {
s << INDENT << PYTHON_RETURN_VAR << " = ";
if (isObjectTypeUsedAsValueType(func->type())) {
@@ -3447,7 +3691,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
} else {
writeToPythonConversion(s, func->type(), func->ownerClass(), QLatin1String(CPP_RETURN_VAR));
}
- s << ';' << endl;
+ s << ";\n";
}
if (generateExceptionHandling) { // "catch" code
@@ -3459,10 +3703,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
}
}
- if (func->hasInjectedCode() && !func->isConstructor()) {
- s << endl;
+ if (func->hasInjectedCode() && !func->isConstructor())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func, lastArg);
- }
bool hasReturnPolicy = false;
@@ -3485,12 +3727,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
hasReturnPolicy = true;
if (!ownership_mods.isEmpty()) {
- s << endl << INDENT << "// Ownership transferences." << endl;
+ s << Qt::endl << INDENT << "// Ownership transferences.\n";
for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) {
const AbstractMetaClass *wrappedClass = nullptr;
QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass);
if (!wrappedClass) {
- s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl;
+ s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ")\n" << Qt::endl;
break;
}
@@ -3513,7 +3755,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
} else {
s << "invalidate(" << pyArgName << ");";
}
- s << endl;
+ s << Qt::endl;
}
} else if (!refcount_mods.isEmpty()) {
@@ -3533,7 +3775,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
} else {
pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass);
if (pyArgName.isEmpty()) {
- s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl;
+ s << "#error Invalid reference count modification for argument " << arg_mod.index << Qt::endl << Qt::endl;
break;
}
}
@@ -3550,7 +3792,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
s << varName << "\", " << pyArgName
<< (refCount.action == ReferenceCount::Add ? ", true" : "")
- << ");" << endl;
+ << ");\n";
if (arg_mod.index == 0)
hasReturnPolicy = true;
@@ -3590,29 +3832,29 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream &s, c
s << "static int mi_offsets[] = { ";
for (int i = 0; i < ancestors.size(); i++)
s << "-1, ";
- s << "-1 };" << endl;
- s << "int *" << endl;
- s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void *cptr)" << endl;
- s << '{' << endl;
- s << INDENT << "if (mi_offsets[0] == -1) {" << endl;
+ s << "-1 };\n";
+ s << "int *\n";
+ s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void *cptr)\n";
+ s << "{\n";
+ s << INDENT << "if (mi_offsets[0] == -1) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "std::set<int> offsets;" << endl;
- s << INDENT << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);" << endl;
- s << INDENT << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);" << endl;
+ s << INDENT << "std::set<int> offsets;\n";
+ s << INDENT << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);\n";
+ s << INDENT << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);\n";
for (const QString &ancestor : ancestors)
- s << INDENT << "offsets.insert(int(" << ancestor << "));" << endl;
+ s << INDENT << "offsets.insert(int(" << ancestor << "));\n";
- s << endl;
- s << INDENT << "offsets.erase(0);" << endl;
- s << endl;
+ s << Qt::endl;
+ s << INDENT << "offsets.erase(0);\n";
+ s << Qt::endl;
s << INDENT << "std::copy(offsets.cbegin(), offsets.cend(), mi_offsets);\n";
}
- s << INDENT << '}' << endl;
- s << INDENT << "return mi_offsets;" << endl;
- s << '}' << endl;
+ s << INDENT << "}\n";
+ s << INDENT << "return mi_offsets;\n";
+ s << "}\n";
}
void CppGenerator::writeSpecialCastFunction(QTextStream &s, const AbstractMetaClass *metaClass)
@@ -3637,7 +3879,7 @@ void CppGenerator::writePrimitiveConverterInitialization(QTextStream &s, const C
{
const TypeEntry *type = customConversion->ownerType();
QString converter = converterObject(type);
- s << INDENT << "// Register converter for type '" << type->qualifiedTargetLangName() << "'." << endl;
+ s << INDENT << "// Register converter for type '" << type->qualifiedTargetLangName() << "'.\n";
s << INDENT << converter << " = Shiboken::Conversions::createConverter(";
if (type->targetLangApiName() == type->name())
s << '0';
@@ -3646,8 +3888,8 @@ void CppGenerator::writePrimitiveConverterInitialization(QTextStream &s, const C
else
s << '&' << type->targetLangApiName() << "_Type";
QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << type->qualifiedCppName() << "\");" << endl;
+ s << ", " << cppToPythonFunctionName(typeName, typeName) << ");\n";
+ s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << type->qualifiedCppName() << "\");\n";
writeCustomConverterRegister(s, customConversion, converter);
}
@@ -3669,15 +3911,15 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn
if (enumType->isFlags())
flags = static_cast<const FlagsTypeEntry *>(enumType);
- s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'." << endl;
- s << INDENT << '{' << endl;
+ s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'.\n";
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
QString typeName = fixedCppTypeName(enumType);
- s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl;
+ s << INDENT << "SbkConverter *converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << Qt::endl;
{
Indentation indent(INDENT);
- s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
+ s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");\n";
}
if (flags) {
@@ -3697,7 +3939,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn
writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv);
}
- s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl;
+ s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);\n";
QString signature = enumType->qualifiedCppName();
// Replace "QFlags<Class::Option>" by "Class::Options"
@@ -3723,7 +3965,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn
break;
}
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
if (!flags)
writeEnumConverterInitialization(s, static_cast<const EnumTypeEntry *>(enumType)->flags());
@@ -3732,7 +3974,7 @@ void CppGenerator::writeEnumConverterInitialization(QTextStream &s, const TypeEn
void CppGenerator::writeContainerConverterInitialization(QTextStream &s, const AbstractMetaType *type)
{
QByteArray cppSignature = QMetaObject::normalizedSignature(type->cppSignature().toUtf8());
- s << INDENT << "// Register converter for type '" << cppSignature << "'." << endl;
+ s << INDENT << "// Register converter for type '" << cppSignature << "'.\n";
QString converter = converterObject(type);
s << INDENT << converter << " = Shiboken::Conversions::createConverter(";
if (type->typeEntry()->targetLangApiName() == QLatin1String("PyObject")) {
@@ -3744,22 +3986,60 @@ void CppGenerator::writeContainerConverterInitialization(QTextStream &s, const A
s << '&' << baseName << "_Type";
}
QString typeName = fixedCppTypeName(type);
- s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl;
+ s << ", " << cppToPythonFunctionName(typeName, typeName) << ");\n";
QString toCpp = pythonToCppFunctionName(typeName, typeName);
QString isConv = convertibleToCppFunctionName(typeName, typeName);
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl;
+ s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");\n";
if (usePySideExtensions() && cppSignature.startsWith("const ") && cppSignature.endsWith("&")) {
cppSignature.chop(1);
cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1);
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl;
+ s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");\n";
}
writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv);
}
+void CppGenerator::writeSmartPointerConverterInitialization(QTextStream &s, const AbstractMetaType *type)
+{
+ const QByteArray cppSignature = type->cppSignature().toUtf8();
+ auto writeConversionRegister = [this, &s](const AbstractMetaType *sourceType, const QString &targetTypeName, const QString &targetConverter)
+ {
+ const QString sourceTypeName = fixedCppTypeName(sourceType);
+ const QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
+ const QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
+
+ writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
+ };
+
+ auto klass = AbstractMetaClass::findClass(classes(), type->instantiations().at(0)->typeEntry());
+ if (!klass)
+ return;
+
+ const auto classes = getBaseClasses(klass);
+ if (classes.isEmpty())
+ return;
+
+ s << INDENT << "// Register SmartPointer converter for type '" << cppSignature << "'." << Qt::endl;
+ s << INDENT << "///////////////////////////////////////////////////////////////////////////////////////"<< Qt::endl;
+ s << Qt::endl;
+
+ for (auto k : classes) {
+ if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry()))
+ {
+ s << INDENT << "// Convert to SmartPointer derived class: [" << smartTargetType->cppSignature() << "]" << Qt::endl;
+ const QString converter = QLatin1String("Shiboken::Conversions::getConverter(\"%1\")").arg(smartTargetType->cppSignature());
+ writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter);
+ } else {
+ s << INDENT << "// Class not found:" << type->instantiations().at(0)->cppSignature();
+ }
+ }
+
+ s << INDENT << "///////////////////////////////////////////////////////////////////////////////////////"<< Qt::endl << Qt::endl;
+}
+
void CppGenerator::writeExtendedConverterInitialization(QTextStream &s, const TypeEntry *externalType,
const QVector<const AbstractMetaClass *>& conversions)
{
- s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl;
+ s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl;
for (const AbstractMetaClass *sourceClass : conversions) {
const QString converterVar = QLatin1String("reinterpret_cast<SbkObjectType *>(")
+ cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[')
@@ -3813,6 +4093,13 @@ bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass *metaClass)
if (!f->isStatic())
return true;
}
+ // Generate all user-added properties unless Pyside extensions are used,
+ // in which only the explicitly specified ones are generated (rest is handled
+ // in libpyside).
+ return usePySideExtensions()
+ ? std::any_of(metaClass->propertySpecs().cbegin(), metaClass->propertySpecs().cend(),
+ [] (const QPropertySpec *s) { return s->generateGetSetDef(); })
+ : !metaClass->propertySpecs().isEmpty();
return false;
}
@@ -3841,7 +4128,7 @@ QTextStream &operator<<(QTextStream &str, const pyTypeSlotEntry &e)
void CppGenerator::writeClassDefinition(QTextStream &s,
const AbstractMetaClass *metaClass,
- GeneratorContext &classContext)
+ const GeneratorContext &classContext)
{
QString tp_flags;
QString tp_init;
@@ -3871,14 +4158,11 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) {
tp_dealloc = metaClass->hasPrivateDestructor() ?
QLatin1String("SbkDeallocWrapperWithPrivateDtor") :
- QLatin1String("object_dealloc /* PYSIDE-832: Prevent replacement of \"0\" with subtype_dealloc. */");
+ QLatin1String("Sbk_object_dealloc /* PYSIDE-832: Prevent replacement of \"0\" with subtype_dealloc. */");
tp_init.clear();
} else {
- QString deallocClassName;
- if (shouldGenerateCppWrapper(metaClass))
- deallocClassName = wrapperName(metaClass);
- else
- deallocClassName = cppClassName;
+ QString deallocClassName = classContext.useWrapper()
+ ? classContext.wrapperName() : cppClassName;
if (isQApp)
tp_dealloc = QLatin1String("&SbkDeallocQAppWrapper");
else
@@ -3887,17 +4171,11 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
tp_init = cpythonFunctionName(ctors.constFirst());
}
- QString tp_getattro;
- QString tp_setattro;
- if (usePySideExtensions() && (metaClass->qualifiedCppName() == QLatin1String("QObject"))) {
- tp_getattro = cpythonGetattroFunctionName(metaClass);
- tp_setattro = cpythonSetattroFunctionName(metaClass);
- } else {
- if (classNeedsGetattroFunction(metaClass))
- tp_getattro = cpythonGetattroFunctionName(metaClass);
- if (classNeedsSetattroFunction(metaClass))
- tp_setattro = cpythonSetattroFunctionName(metaClass);
- }
+ const AttroCheck attroCheck = checkAttroFunctionNeeds(metaClass);
+ const QString tp_getattro = (attroCheck & AttroCheckFlag::GetattroMask) != 0
+ ? cpythonGetattroFunctionName(metaClass) : QString();
+ const QString tp_setattro = (attroCheck & AttroCheckFlag::SetattroMask) != 0
+ ? cpythonSetattroFunctionName(metaClass) : QString();
if (metaClass->hasPrivateDestructor() || onlyPrivCtor) {
// tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES");
@@ -3915,15 +4193,14 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
tp_new = QLatin1String("SbkDummyNew /* PYSIDE-595: Prevent replacement "
"of \"0\" with base->tp_new. */");
}
- tp_flags.append(QLatin1String("|Py_TPFLAGS_HAVE_GC"));
}
else if (isQApp) {
tp_new = QLatin1String("SbkQAppTpNew"); // PYSIDE-571: need singleton app
}
else {
tp_new = QLatin1String("SbkObjectTpNew");
- tp_flags.append(QLatin1String("|Py_TPFLAGS_HAVE_GC"));
}
+ tp_flags.append(QLatin1String("|Py_TPFLAGS_HAVE_GC"));
QString tp_richcompare;
if (!metaClass->isNamespace() && metaClass->hasComparisonOperatorOverload())
@@ -3953,11 +4230,11 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
if (metaClass == miClass)
writeMultipleInheritanceInitializerFunction(s, metaClass);
writeSpecialCastFunction(s, metaClass);
- s << endl;
+ s << Qt::endl;
}
- s << "// Class Definition -----------------------------------------------" << endl;
- s << "extern \"C\" {" << endl;
+ s << "// Class Definition -----------------------------------------------\n";
+ s << "extern \"C\" {\n";
if (!metaClass->typeEntry()->hashFunction().isEmpty())
tp_hash = QLatin1Char('&') + cpythonBaseName(metaClass) + QLatin1String("_HashFunc");
@@ -3977,14 +4254,14 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
suffix = QLatin1String(" *");
const QString typePtr = QLatin1String("_") + className
+ QLatin1String("_Type");
- s << "static SbkObjectType *" << typePtr << " = nullptr;" << endl;
- s << "static SbkObjectType *" << className << "_TypeF(void)" << endl;
- s << "{" << endl;
- s << INDENT << "return " << typePtr << ";" << endl;
- s << "}" << endl;
- s << endl;
- s << "static PyType_Slot " << className << "_slots[] = {" << endl;
- s << INDENT << "{Py_tp_base, nullptr}, // inserted by introduceWrapperType" << endl;
+ s << "static SbkObjectType *" << typePtr << " = nullptr;\n";
+ s << "static SbkObjectType *" << className << "_TypeF(void)\n";
+ s << "{\n";
+ s << INDENT << "return " << typePtr << ";\n";
+ s << "}\n";
+ s << Qt::endl;
+ s << "static PyType_Slot " << className << "_slots[] = {\n";
+ s << INDENT << "{Py_tp_base, nullptr}, // inserted by introduceWrapperType\n";
s << INDENT << pyTypeSlotEntry("Py_tp_dealloc", tp_dealloc)
<< INDENT << pyTypeSlotEntry("Py_tp_repr", m_tpFuncs.value(QLatin1String("__repr__")))
<< INDENT << pyTypeSlotEntry("Py_tp_hash", tp_hash)
@@ -4002,34 +4279,36 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
<< INDENT << pyTypeSlotEntry("Py_tp_init", tp_init)
<< INDENT << pyTypeSlotEntry("Py_tp_new", tp_new);
if (supportsSequenceProtocol(metaClass)) {
- s << INDENT << "// type supports sequence protocol" << endl;
+ s << INDENT << "// type supports sequence protocol\n";
writeTypeAsSequenceDefinition(s, metaClass);
}
if (supportsMappingProtocol(metaClass)) {
- s << INDENT << "// type supports mapping protocol" << endl;
+ s << INDENT << "// type supports mapping protocol\n";
writeTypeAsMappingDefinition(s, metaClass);
}
if (supportsNumberProtocol(metaClass)) {
// This one must come last. See the function itself.
- s << INDENT << "// type supports number protocol" << endl;
+ s << INDENT << "// type supports number protocol\n";
writeTypeAsNumberDefinition(s, metaClass);
}
- s << INDENT << "{0, " << NULL_PTR << '}' << endl;
- s << "};" << endl;
- s << "static PyType_Spec " << className << "_spec = {" << endl;
- s << INDENT << "\"" << computedClassTargetFullName << "\"," << endl;
- s << INDENT << "sizeof(SbkObject)," << endl;
- s << INDENT << "0," << endl;
- s << INDENT << tp_flags << "," << endl;
- s << INDENT << className << "_slots" << endl;
- s << "};" << endl;
- s << endl;
- s << "} //extern \"C\"" << endl;
+ s << INDENT << "{0, " << NULL_PTR << "}\n";
+ s << "};\n";
+
+ int packageLevel = packageName().count(QLatin1Char('.')) + 1;
+ s << "static PyType_Spec " << className << "_spec = {\n";
+ s << INDENT << '"' << packageLevel << ':' << computedClassTargetFullName << "\",\n";
+ s << INDENT << "sizeof(SbkObject),\n";
+ s << INDENT << "0,\n";
+ s << INDENT << tp_flags << ",\n";
+ s << INDENT << className << "_slots\n";
+ s << "};\n";
+ s << Qt::endl;
+ s << "} //extern \"C\"" << Qt::endl;
}
void CppGenerator::writeMappingMethods(QTextStream &s,
const AbstractMetaClass *metaClass,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
for (auto it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) {
const AbstractMetaFunction *func = metaClass->findFunction(it.key());
@@ -4040,20 +4319,20 @@ void CppGenerator::writeMappingMethods(QTextStream &s,
QString funcRetVal = it.value().second;
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
- s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
+ s << funcRetVal << ' ' << funcName << '(' << funcArgs << ")\n{\n";
writeInvalidPyObjectCheck(s, QLatin1String("self"));
writeCppSelfDefinition(s, func, context);
const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg);
- s << '}' << endl << endl;
+ s<< "}\n\n";
}
}
void CppGenerator::writeSequenceMethods(QTextStream &s,
const AbstractMetaClass *metaClass,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
bool injectedCode = false;
@@ -4067,18 +4346,18 @@ void CppGenerator::writeSequenceMethods(QTextStream &s,
QString funcRetVal = it.value().second;
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
- s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
+ s << funcRetVal << ' ' << funcName << '(' << funcArgs << ")\n{\n";
writeInvalidPyObjectCheck(s, QLatin1String("self"));
writeCppSelfDefinition(s, func, context);
- const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast();
+ const AbstractMetaArgument *lastArg = func->arguments().isEmpty() ? nullptr : func->arguments().constLast();
writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg);
- s << '}' << endl << endl;
+ s<< "}\n\n";
}
if (!injectedCode)
- writeStdListWrapperMethods(s, context);
+ writeDefaultSequenceMethods(s, context);
}
void CppGenerator::writeTypeAsSequenceDefinition(QTextStream &s, const AbstractMetaClass *metaClass)
@@ -4107,10 +4386,10 @@ void CppGenerator::writeTypeAsSequenceDefinition(QTextStream &s, const AbstractM
if (funcs[sqName].isEmpty())
continue;
if (it.value() == QLatin1String("sq_slice"))
- s << "#ifndef IS_PY3K" << endl;
- s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[sqName] << "}," << endl;
+ s << "#ifndef IS_PY3K\n";
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[sqName] << "},\n";
if (it.value() == QLatin1String("sq_slice"))
- s << "#endif" << endl;
+ s << "#endif\n";
}
}
@@ -4137,7 +4416,7 @@ void CppGenerator::writeTypeAsMappingDefinition(QTextStream &s, const AbstractMe
const QString &mpName = it.key();
if (funcs[mpName].isEmpty())
continue;
- s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[mpName] << "}," << endl;
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[mpName] << "},\n";
}
}
@@ -4194,28 +4473,28 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream &s, const AbstractMet
// bool is special because the field name differs on Python 2 and 3 (nb_nonzero vs nb_bool)
// so a shiboken macro is used.
if (nbName == QLatin1String("bool")) {
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << "{Py_nb_bool, (void *)" << nb[nbName] << "}," << endl;
- s << "#else" << endl;
- s << INDENT << "{Py_nb_nonzero, (void *)" << nb[nbName] << "}," << endl;
- s << "#endif" << endl;
+ s << "#ifdef IS_PY3K\n";
+ s << INDENT << "{Py_nb_bool, (void *)" << nb[nbName] << "},\n";
+ s << "#else\n";
+ s << INDENT << "{Py_nb_nonzero, (void *)" << nb[nbName] << "},\n";
+ s << "#endif\n";
} else {
bool excludeFromPy3K = nbName == QLatin1String("__div__") || nbName == QLatin1String("__idiv__");
if (!excludeFromPy3K)
- s << INDENT << "{Py_" << it.value() << ", (void *)" << nb[nbName] << "}," << endl;
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << nb[nbName] << "},\n";
}
}
if (!nb[QLatin1String("__div__")].isEmpty()) {
- s << INDENT << "{Py_nb_true_divide, (void *)" << nb[QLatin1String("__div__")] << "}," << endl;
- s << "#ifndef IS_PY3K" << endl;
- s << INDENT << "{Py_nb_divide, (void *)" << nb[QLatin1String("__div__")] << "}," << endl;
- s << "#endif" << endl;
+ s << INDENT << "{Py_nb_true_divide, (void *)" << nb[QLatin1String("__div__")] << "},\n";
+ s << "#ifndef IS_PY3K\n";
+ s << INDENT << "{Py_nb_divide, (void *)" << nb[QLatin1String("__div__")] << "},\n";
+ s << "#endif\n";
}
if (!nb[QLatin1String("__idiv__")].isEmpty()) {
- s << INDENT << "// This function is unused in Python 3. We reference it here." << endl;
- s << INDENT << "{0, (void *)" << nb[QLatin1String("__idiv__")] << "}," << endl;
- s << INDENT << "// This list is ending at the first 0 entry." << endl;
- s << INDENT << "// Therefore, we need to put the unused functions at the very end." << endl;
+ s << INDENT << "// This function is unused in Python 3. We reference it here.\n";
+ s << INDENT << "{0, (void *)" << nb[QLatin1String("__idiv__")] << "},\n";
+ s << INDENT << "// This list is ending at the first 0 entry.\n";
+ s << INDENT << "// Therefore, we need to put the unused functions at the very end.\n";
}
}
@@ -4223,28 +4502,28 @@ void CppGenerator::writeTpTraverseFunction(QTextStream &s, const AbstractMetaCla
{
QString baseName = cpythonBaseName(metaClass);
s << "static int ";
- s << baseName << "_traverse(PyObject *self, visitproc visit, void *arg)" << endl;
- s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_traverse(self, visit, arg);" << endl;
- s << '}' << endl;
+ s << baseName << "_traverse(PyObject *self, visitproc visit, void *arg)\n";
+ s << "{\n";
+ s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_traverse(self, visit, arg);\n";
+ s << "}\n";
}
void CppGenerator::writeTpClearFunction(QTextStream &s, const AbstractMetaClass *metaClass)
{
QString baseName = cpythonBaseName(metaClass);
s << "static int ";
- s << baseName << "_clear(PyObject *self)" << endl;
- s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_clear(self);" << endl;
- s << '}' << endl;
+ s << baseName << "_clear(PyObject *self)\n";
+ s << "{\n";
+ s << INDENT << "return reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())->tp_clear(self);\n";
+ s << "}\n";
}
-void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeCopyFunction(QTextStream &s, const GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
const QString className = chopType(cpythonTypeName(metaClass));
- s << "static PyObject *" << className << "___copy__(PyObject *self)" << endl;
- s << "{" << endl;
+ s << "static PyObject *" << className << "___copy__(PyObject *self)\n";
+ s << "{\n";
writeCppSelfDefinition(s, context, false, true);
QString conversionCode;
if (!context.forSmartPointer())
@@ -4253,20 +4532,25 @@ void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
conversionCode = cpythonToPythonConversionFunction(context.preciseType());
s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << " = " << conversionCode;
- s << CPP_SELF_VAR << ");" << endl;
+ s << CPP_SELF_VAR << ");\n";
writeFunctionReturnErrorCheckSection(s);
- s << INDENT << "return " << PYTHON_RETURN_VAR << ";" << endl;
- s << "}" << endl;
- s << endl;
+ s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n";
+ s << "}\n";
+ s << Qt::endl;
+}
+
+static inline void writeGetterFunctionStart(QTextStream &s, const QString &funcName)
+{
+ s << "static PyObject *" << funcName << "(PyObject *self, void *)\n";
+ s << "{\n";
}
void CppGenerator::writeGetterFunction(QTextStream &s,
const AbstractMetaField *metaField,
- GeneratorContext &context)
+ const GeneratorContext &context)
{
ErrorCode errorCode(QString::fromLatin1(NULL_PTR));
- s << "static PyObject *" << cpythonGetterFunctionName(metaField) << "(PyObject *self, void *)" << endl;
- s << '{' << endl;
+ writeGetterFunctionStart(s, cpythonGetterFunctionName(metaField));
writeCppSelfDefinition(s, context);
@@ -4277,7 +4561,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
QString cppField;
if (avoidProtectedHack() && metaField->isProtected()) {
QTextStream(&cppField) << "static_cast<"
- << wrapperName(metaField->enclosingClass()) << " *>("
+ << context.wrapperName() << " *>("
<< CPP_SELF_VAR << ")->" << protectedFieldGetterName(metaField) << "()";
} else {
cppField = QLatin1String(CPP_SELF_VAR) + QLatin1String("->") + metaField->name();
@@ -4287,7 +4571,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
}
}
if (isCppIntegralPrimitive(fieldType) || fieldType->isEnum()) {
- s << INDENT << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
+ s << INDENT << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ";\n";
cppField = QLatin1String("cppOut_local");
} else if (avoidProtectedHack() && metaField->isProtected()) {
s << INDENT << getFullTypeNameWithoutModifiers(fieldType);
@@ -4297,7 +4581,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
} else if ((!fieldType->isConstant() && !fieldType->isEnum() && !fieldType->isPrimitive()) || fieldType->indirections() == 1) {
s << " *";
}
- s << " fieldValue = " << cppField << ';' << endl;
+ s << " fieldValue = " << cppField << ";\n";
cppField = QLatin1String("fieldValue");
}
@@ -4314,11 +4598,16 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
<< "reinterpret_cast<SbkObject *>(self), reinterpret_cast<SbkObjectType *>("
<< cpythonTypeNameExt(fieldType)
<< ")));\n";
- s << INDENT << "if (pyOut) {Py_IncRef(pyOut); return pyOut;}\n";
+ s << INDENT << "if (pyOut) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "Py_IncRef(pyOut);\n"
+ << INDENT << "return pyOut;\n";
+ }
+ s << INDENT << "}\n";
}
- s << INDENT << "}\n";
// Check if field wrapper has already been created.
- s << INDENT << "else if (Shiboken::BindingManager::instance().hasWrapper(" << cppField << ")) {" << "\n";
+ s << INDENT << "} else if (Shiboken::BindingManager::instance().hasWrapper(" << cppField << ")) {" << "\n";
{
Indentation indent(INDENT);
s << INDENT << "pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper("
@@ -4330,98 +4619,144 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
// Create and register new wrapper
s << INDENT << "pyOut = ";
s << "Shiboken::Object::newObject(reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(fieldType)
- << "), " << cppField << ", false, true);" << endl;
+ << "), " << cppField << ", false, true);\n";
s << INDENT << "Shiboken::Object::setParent(self, pyOut)";
} else {
s << INDENT << "pyOut = ";
writeToPythonConversion(s, fieldType, metaField->enclosingClass(), cppField);
}
- s << ';' << endl;
+ s << ";\n";
- s << INDENT << "return pyOut;" << endl;
- s << '}' << endl;
+ s << INDENT << "return pyOut;\n";
+ s << "}\n";
}
-void CppGenerator::writeSetterFunction(QTextStream &s,
- const AbstractMetaField *metaField,
- GeneratorContext &context)
+// Write a getter for QPropertySpec
+void CppGenerator::writeGetterFunction(QTextStream &s, const QPropertySpec *property,
+ const GeneratorContext &context)
{
ErrorCode errorCode(0);
- s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject *self, PyObject *pyIn, void *)" << endl;
- s << '{' << endl;
-
+ writeGetterFunctionStart(s, cpythonGetterFunctionName(property, context.metaClass()));
writeCppSelfDefinition(s, context);
-
- s << INDENT << "if (pyIn == " << NULL_PTR << ") {" << endl;
+ const QString value = QStringLiteral("value");
+ s << INDENT << "auto " << value << " = " << CPP_SELF_VAR << "->" << property->read() << "();\n"
+ << INDENT << "auto pyResult = ";
+ writeToPythonConversion(s, property->type(), context.metaClass(), value);
+ s << ";\n"
+ << INDENT << "if (PyErr_Occurred() || !pyResult) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'";
- s << metaField->name() << "' may not be deleted\");" << endl;
- s << INDENT << "return -1;" << endl;
+ s << INDENT << "Py_XDECREF(pyResult);\n"
+ << INDENT << " return {};\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n"
+ << INDENT << "return pyResult;\n}\n\n";
+}
- AbstractMetaType *fieldType = metaField->type();
+// Write setter function preamble (type checks on "pyIn")
+void CppGenerator::writeSetterFunctionPreamble(QTextStream &s, const QString &name,
+ const QString &funcName,
+ const AbstractMetaType *type,
+ const GeneratorContext &context)
+{
+ s << "static int " << funcName << "(PyObject *self, PyObject *pyIn, void *)\n";
+ s << "{\n";
+
+ writeCppSelfDefinition(s, context);
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};" << endl;
+ s << INDENT << "if (pyIn == " << NULL_PTR << ") {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"
+ << name << "' may not be deleted\");\n"
+ << INDENT << "return -1;\n"
+ << outdent(INDENT) << INDENT << "}\n";
+
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};\n";
s << INDENT << "if (!";
- writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry()));
- s << ") {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '";
- s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");" << endl;
- s << INDENT << "return -1;" << endl;
- }
- s << INDENT << '}' << endl << endl;
+ writeTypeCheck(s, type, QLatin1String("pyIn"), isNumber(type->typeEntry()));
+ s << ") {\n" << indent(INDENT)
+ << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"
+ << name << "', '" << type->name() << "' or convertible type expected\");\n"
+ << INDENT << "return -1;\n"
+ << outdent(INDENT) << INDENT<< "}\n\n";
+}
+
+void CppGenerator::writeSetterFunction(QTextStream &s,
+ const AbstractMetaField *metaField,
+ const GeneratorContext &context)
+{
+ ErrorCode errorCode(0);
+
+ AbstractMetaType *fieldType = metaField->type();
+ writeSetterFunctionPreamble(s, metaField->name(), cpythonSetterFunctionName(metaField),
+ fieldType, context);
QString cppField = QString::fromLatin1("%1->%2").arg(QLatin1String(CPP_SELF_VAR), metaField->name());
s << INDENT;
if (avoidProtectedHack() && metaField->isProtected()) {
s << getFullTypeNameWithoutModifiers(fieldType);
- s << (fieldType->indirections() == 1 ? " *" : "") << " cppOut;" << endl;
- s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);" << endl;
- s << INDENT << "static_cast<" << wrapperName(metaField->enclosingClass())
+ s << (fieldType->indirections() == 1 ? " *" : "") << " cppOut;\n";
+ s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);\n";
+ s << INDENT << "static_cast<" << context.wrapperName()
<< " *>(" << CPP_SELF_VAR << ")->" << protectedFieldSetterName(metaField)
<< "(cppOut)";
} else if (isCppIntegralPrimitive(fieldType) || fieldType->typeEntry()->isEnum() || fieldType->typeEntry()->isFlags()) {
- s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl;
- s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl;
+ s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ";\n";
+ s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);\n";
s << INDENT << cppField << " = cppOut_local";
} else {
if (isPointerToConst(fieldType))
s << "const ";
s << getFullTypeNameWithoutModifiers(fieldType);
s << QString::fromLatin1(" *").repeated(fieldType->indirections()) << "& cppOut_ptr = ";
- s << cppField << ';' << endl;
+ s << cppField << ";\n";
s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)";
}
- s << ';' << endl << endl;
+ s << ";\n" << Qt::endl;
if (isPointerToWrapperType(fieldType)) {
s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(self), \"";
- s << metaField->name() << "\", pyIn);" << endl;
+ s << metaField->name() << "\", pyIn);\n";
}
- s << INDENT << "return 0;" << endl;
- s << '}' << endl;
+ s << INDENT << "return 0;\n";
+ s << "}\n";
+}
+
+// Write a setter for QPropertySpec
+void CppGenerator::writeSetterFunction(QTextStream &s, const QPropertySpec *property,
+ const GeneratorContext &context)
+{
+ ErrorCode errorCode(0);
+ writeSetterFunctionPreamble(s, property->name(),
+ cpythonSetterFunctionName(property, context.metaClass()),
+ property->type(), context);
+
+ s << INDENT << "auto cppOut = " << CPP_SELF_VAR << "->" << property->read() << "();\n"
+ << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);\n"
+ << INDENT << "if (PyErr_Occurred())\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return -1;\n";
+ }
+ s << INDENT << CPP_SELF_VAR << "->" << property->write() << "(cppOut);\n"
+ << INDENT << "return 0;\n}\n\n";
}
-void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeRichCompareFunction(QTextStream &s, const GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
QString baseName = cpythonBaseName(metaClass);
s << "static PyObject * ";
- s << baseName << "_richcompare(PyObject *self, PyObject *" << PYTHON_ARG << ", int op)" << endl;
- s << '{' << endl;
+ s << baseName << "_richcompare(PyObject *self, PyObject *" << PYTHON_ARG
+ << ", int op)\n{\n";
writeCppSelfDefinition(s, context, false, true);
writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
- s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};" << endl;
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
+ s << INDENT << "PyObject *" << PYTHON_RETURN_VAR << "{};\n";
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n";
writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR));
- s << endl;
+ s << Qt::endl;
- s << INDENT << "switch (op) {" << endl;
+ s << INDENT << "switch (op) {\n";
{
Indentation indent(INDENT);
const QVector<AbstractMetaFunctionList> &groupedFuncs = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp);
@@ -4429,7 +4764,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
const AbstractMetaFunction *rfunc = overloads[0];
QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc);
- s << INDENT << "case " << operatorId << ':' << endl;
+ s << INDENT << "case " << operatorId << ':' << Qt::endl;
Indentation indent(INDENT);
@@ -4461,21 +4796,28 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
}
s << "if (";
writeTypeCheck(s, argType, QLatin1String(PYTHON_ARG), alternativeNumericTypes == 1 || isPyInt(argType));
- s << ") {" << endl;
+ s << ") {\n";
{
Indentation indent(INDENT);
- s << INDENT << "// " << func->signature() << endl;
+ s << INDENT << "// " << func->signature() << Qt::endl;
writeArgumentConversion(s, argType, QLatin1String(CPP_ARG0),
QLatin1String(PYTHON_ARG), metaClass,
QString(), func->isUserAdded());
// If the function is user added, use the inject code
+ bool generateOperatorCode = true;
if (func->isUserAdded()) {
CodeSnipList snips = func->injectedCodeSnips();
- writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().constLast());
- } else {
+ if (!snips.isEmpty()) {
+ writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, func,
+ func->arguments().constLast());
+ generateOperatorCode = false;
+ }
+ }
+ if (generateOperatorCode) {
s << INDENT;
- if (func->type())
+ if (!func->isVoid())
s << func->type()->cppSignature() << " " << CPP_RETURN_VAR << " = ";
// expression
if (func->isPointerOperator())
@@ -4483,49 +4825,51 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co
s << CPP_SELF_VAR << ' ' << op << '(';
if (shouldDereferenceAbstractMetaTypePointer(argType))
s << '*';
- s << CPP_ARG0 << ");" << endl;
+ s << CPP_ARG0 << ");\n";
s << INDENT << PYTHON_RETURN_VAR << " = ";
- if (func->type())
+ if (!func->isVoid())
writeToPythonConversion(s, func->type(), metaClass, QLatin1String(CPP_RETURN_VAR));
else
- s << "Py_None;" << endl << INDENT << "Py_INCREF(Py_None)";
- s << ';' << endl;
+ s << "Py_None;\n" << INDENT << "Py_INCREF(Py_None)";
+ s << ";\n";
}
}
s << INDENT << '}';
}
- s << " else {" << endl;
+ s << " else {\n";
if (operatorId == QLatin1String("Py_EQ") || operatorId == QLatin1String("Py_NE")) {
Indentation indent(INDENT);
s << INDENT << PYTHON_RETURN_VAR << " = "
- << (operatorId == QLatin1String("Py_EQ") ? "Py_False" : "Py_True") << ';' << endl;
- s << INDENT << "Py_INCREF(" << PYTHON_RETURN_VAR << ");" << endl;
+ << (operatorId == QLatin1String("Py_EQ") ? "Py_False" : "Py_True") << ";\n";
+ s << INDENT << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n";
} else {
Indentation indent(INDENT);
- s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl;
+ s << INDENT << "goto " << baseName << "_RichComparison_TypeError;\n";
}
- s << INDENT << '}' << endl << endl;
+ s << INDENT<< "}\n\n";
- s << INDENT << "break;" << endl;
+ s << INDENT << "break;\n";
}
- s << INDENT << "default:" << endl;
+ s << INDENT << "default:\n";
{
Indentation indent(INDENT);
- s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl;
+ s << INDENT << "// PYSIDE-74: By default, we redirect to object's tp_richcompare (which is `==`, `!=`).\n";
+ s << INDENT << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n";
+ s << INDENT << "goto " << baseName << "_RichComparison_TypeError;\n";
}
}
- s << INDENT << '}' << endl << endl;
+ s << INDENT<< "}\n\n";
- s << INDENT << "if (" << PYTHON_RETURN_VAR << " && !PyErr_Occurred())" << endl;
+ s << INDENT << "if (" << PYTHON_RETURN_VAR << " && !PyErr_Occurred())\n";
{
Indentation indent(INDENT);
- s << INDENT << "return " << PYTHON_RETURN_VAR << ";" << endl;
+ s << INDENT << "return " << PYTHON_RETURN_VAR << ";\n";
}
- s << INDENT << baseName << "_RichComparison_TypeError:" << endl;
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
- s << '}' << endl << endl;
+ s << INDENT << baseName << "_RichComparison_TypeError:\n";
+ s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl;
+ s<< "}\n\n";
}
void CppGenerator::writeMethodDefinitionEntry(QTextStream &s, const AbstractMetaFunctionList &overloads)
@@ -4549,8 +4893,14 @@ void CppGenerator::writeMethodDefinitionEntry(QTextStream &s, const AbstractMeta
if (overloadData.hasArgumentWithDefaultValue())
s << "|METH_KEYWORDS";
}
- if (func->ownerClass() && overloadData.hasStaticFunction())
+ // METH_STATIC causes a crash when used for global functions (also from
+ // invisible namespaces).
+ auto ownerClass = func->ownerClass();
+ if (ownerClass
+ && !invisibleTopNamespaces().contains(const_cast<AbstractMetaClass *>(ownerClass))
+ && overloadData.hasStaticFunction()) {
s << "|METH_STATIC";
+ }
}
void CppGenerator::writeMethodDefinition(QTextStream &s, const AbstractMetaFunctionList &overloads)
@@ -4568,20 +4918,24 @@ void CppGenerator::writeMethodDefinition(QTextStream &s, const AbstractMetaFunct
writeMethodDefinitionEntry(s, overloads);
s << '}';
}
- s << ',' << endl;
+ s << ',' << Qt::endl;
}
void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunctionList &overloads)
{
OverloadData overloadData(overloads, this);
const AbstractMetaFunction *rfunc = overloadData.referenceFunction();
- QString funcName = fullPythonFunctionName(rfunc);
+ QString funcName = fullPythonFunctionName(rfunc, false);
int idx = overloads.length() - 1;
bool multiple = idx > 0;
for (const AbstractMetaFunction *f : overloads) {
QStringList args;
+ // PYSIDE-1328: `self`-ness cannot be computed in Python because there are mixed cases.
+ // Toplevel functions like `PySide2.QtCore.QEnum` are always self-less.
+ if (!(f->isStatic()) && f->ownerClass())
+ args << QLatin1String("self");
const AbstractMetaArgumentList &arguments = f->arguments();
for (const AbstractMetaArgument *arg : arguments) {
QString strArg = arg->type()->pythonSignature();
@@ -4589,8 +4943,6 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction
strArg += QLatin1Char('=');
QString e = arg->defaultValueExpression();
e.replace(QLatin1String("::"), QLatin1String("."));
- // the tests insert stuff like Str("<unknown>"):
- e.replace(QLatin1Char('"'), QLatin1String("\\\""));
strArg += e;
}
args << arg->name() + QLatin1Char(':') + strArg;
@@ -4599,9 +4951,9 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction
if (multiple)
s << idx-- << ':';
s << funcName << '(' << args.join(QLatin1Char(',')) << ')';
- if (f->type())
+ if (!f->isVoid())
s << "->" << f->type()->pythonSignature();
- s << endl;
+ s << Qt::endl;
}
}
@@ -4609,7 +4961,7 @@ void CppGenerator::writeEnumsInitialization(QTextStream &s, AbstractMetaEnumList
{
if (enums.isEmpty())
return;
- s << INDENT << "// Initialization of enums." << endl << endl;
+ s << INDENT << "// Initialization of enums.\n\n";
for (const AbstractMetaEnum *cppEnum : qAsConst(enums)) {
if (cppEnum->isPrivate())
continue;
@@ -4628,9 +4980,8 @@ static QString mangleName(QString name)
void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *cppEnum)
{
- const AbstractMetaClass *enclosingClass = getProperEnclosingClassForEnum(cppEnum);
- const AbstractMetaClass *upper = enclosingClass ? enclosingClass->enclosingClass() : nullptr;
- bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass;
+ const AbstractMetaClass *enclosingClass = cppEnum->targetLangEnclosingClass();
+ bool hasUpperEnclosingClass = enclosingClass && enclosingClass->targetLangEnclosingClass() != nullptr;
const EnumTypeEntry *enumTypeEntry = cppEnum->typeEntry();
QString enclosingObjectVariable;
if (enclosingClass)
@@ -4642,10 +4993,11 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
s << INDENT << "// Initialization of ";
s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum");
- s << " '" << cppEnum->name() << "'." << endl;
+ s << " '" << cppEnum->name() << "'.\n";
QString enumVarTypeObj;
if (!cppEnum->isAnonymous()) {
+ int packageLevel = packageName().count(QLatin1Char('.')) + 1;
FlagsTypeEntry *flags = enumTypeEntry->flags();
if (flags) {
// The following could probably be made nicer:
@@ -4653,29 +5005,29 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
QString fullPath = getClassTargetFullName(cppEnum);
fullPath.truncate(fullPath.lastIndexOf(QLatin1Char('.')) + 1);
s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\""
- << fullPath << flags->flagsName() << "\", "
- << cpythonEnumName(cppEnum) << "_number_slots);" << endl;
+ << packageLevel << ':' << fullPath << flags->flagsName() << "\", "
+ << cpythonEnumName(cppEnum) << "_number_slots);\n";
}
enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
s << INDENT << enumVarTypeObj << " = Shiboken::Enum::";
s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum");
- s << '(' << enclosingObjectVariable << ',' << endl;
+ s << '(' << enclosingObjectVariable << ',' << Qt::endl;
{
Indentation indent(INDENT);
- s << INDENT << '"' << cppEnum->name() << "\"," << endl;
- s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\"," << endl;
+ s << INDENT << '"' << cppEnum->name() << "\",\n";
+ s << INDENT << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n";
s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString());
s << cppEnum->name() << '"';
if (flags)
- s << ',' << endl << INDENT << cpythonTypeNameExt(flags);
- s << ");" << endl;
+ s << ',' << Qt::endl << INDENT << cpythonTypeNameExt(flags);
+ s << ");\n";
}
- s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl;
+ s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ")\n";
{
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl << Qt::endl;
}
}
@@ -4700,45 +5052,45 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
switch (cppEnum->enumKind()) {
case AnonymousEnum:
if (enclosingClass || hasUpperEnclosingClass) {
- s << INDENT << '{' << endl;
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyObject *anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl;
+ s << INDENT << "PyObject *anonEnumItem = PyInt_FromLong(" << enumValueText << ");\n";
s << INDENT << "if (PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(reinterpret_cast<SbkObjectType *>(" << enclosingObjectVariable
- << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)" << endl;
+ << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)\n";
{
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
- s << INDENT << "Py_DECREF(anonEnumItem);" << endl;
+ s << INDENT << "Py_DECREF(anonEnumItem);\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
} else {
s << INDENT << "if (PyModule_AddIntConstant(module, \"" << mangleName(enumValue->name()) << "\", ";
- s << enumValueText << ") < 0)" << endl;
+ s << enumValueText << ") < 0)\n";
{
Indentation indent(INDENT);
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
}
break;
case CEnum: {
s << INDENT << "if (!Shiboken::Enum::";
s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem");
- s << '(' << enumVarTypeObj << ',' << endl;
+ s << '(' << enumVarTypeObj << ',' << Qt::endl;
Indentation indent(INDENT);
s << INDENT << enclosingObjectVariable << ", \"" << mangleName(enumValue->name()) << "\", ";
- s << enumValueText << "))" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << enumValueText << "))\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
break;
case EnumClass: {
s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem("
- << enumVarTypeObj << ',' << endl;
+ << enumVarTypeObj << ',' << Qt::endl;
Indentation indent(INDENT);
s << INDENT << enumVarTypeObj<< ", \"" << mangleName(enumValue->name()) << "\", "
- << enumValueText << "))" << endl
- << INDENT << returnStatement(m_currentErrorCode) << endl;
+ << enumValueText << "))\n"
+ << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
break;
}
@@ -4749,7 +5101,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
s << INDENT << "// End of '" << cppEnum->name() << "' enum";
if (cppEnum->typeEntry()->flags())
s << "/flags";
- s << '.' << endl << endl;
+ s << '.' << Qt::endl << Qt::endl;
}
void CppGenerator::writeSignalInitialization(QTextStream &s, const AbstractMetaClass *metaClass)
@@ -4775,7 +5127,7 @@ void CppGenerator::writeSignalInitialization(QTextStream &s, const AbstractMetaC
}
s << INDENT << "PySide::Signal::registerSignals(" << cpythonTypeName(metaClass) << ", &::"
- << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl;
+ << metaClass->qualifiedCppName() << "::staticMetaObject);\n";
}
void CppGenerator::writeFlagsToLong(QTextStream &s, const AbstractMetaEnum *cppEnum)
@@ -4783,13 +5135,13 @@ void CppGenerator::writeFlagsToLong(QTextStream &s, const AbstractMetaEnum *cppE
FlagsTypeEntry *flagsEntry = cppEnum->typeEntry()->flags();
if (!flagsEntry)
return;
- s << "static PyObject *" << cpythonEnumName(cppEnum) << "_long(PyObject *self)" << endl;
- s << "{" << endl;
- s << INDENT << "int val;" << endl;
+ s << "static PyObject *" << cpythonEnumName(cppEnum) << "_long(PyObject *self)\n";
+ s << "{\n";
+ s << INDENT << "int val;\n";
AbstractMetaType *flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);" << endl;
- s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<int>(), &val);" << endl;
- s << "}" << endl;
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);\n";
+ s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<int>(), &val);\n";
+ s << "}\n";
}
void CppGenerator::writeFlagsNonZero(QTextStream &s, const AbstractMetaEnum *cppEnum)
@@ -4797,14 +5149,14 @@ void CppGenerator::writeFlagsNonZero(QTextStream &s, const AbstractMetaEnum *cpp
FlagsTypeEntry *flagsEntry = cppEnum->typeEntry()->flags();
if (!flagsEntry)
return;
- s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject *self)" << endl;
- s << "{" << endl;
+ s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject *self)\n";
+ s << "{\n";
- s << INDENT << "int val;" << endl;
+ s << INDENT << "int val;\n";
AbstractMetaType *flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);" << endl;
- s << INDENT << "return val != 0;" << endl;
- s << "}" << endl;
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &val);\n";
+ s << INDENT << "return val != 0;\n";
+ s << "}\n";
}
void CppGenerator::writeFlagsMethods(QTextStream &s, const AbstractMetaEnum *cppEnum)
@@ -4817,30 +5169,42 @@ void CppGenerator::writeFlagsMethods(QTextStream &s, const AbstractMetaEnum *cpp
writeFlagsToLong(s, cppEnum);
writeFlagsNonZero(s, cppEnum);
- s << endl;
+ s << Qt::endl;
}
void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const AbstractMetaEnum *cppEnum)
{
QString cpythonName = cpythonEnumName(cppEnum);
- s << "static PyType_Slot " << cpythonName << "_number_slots[] = {" << endl;
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << "{Py_nb_bool, (void *)" << cpythonName << "__nonzero}," << endl;
- s << "#else" << endl;
- s << INDENT << "{Py_nb_nonzero, (void *)" << cpythonName << "__nonzero}," << endl;
- s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long}," << endl;
- s << "#endif" << endl;
- s << INDENT << "{Py_nb_invert, (void *)" << cpythonName << "___invert__}," << endl;
- s << INDENT << "{Py_nb_and, (void *)" << cpythonName << "___and__}," << endl;
- s << INDENT << "{Py_nb_xor, (void *)" << cpythonName << "___xor__}," << endl;
- s << INDENT << "{Py_nb_or, (void *)" << cpythonName << "___or__}," << endl;
- s << INDENT << "{Py_nb_int, (void *)" << cpythonName << "_long}," << endl;
- s << "#ifndef IS_PY3K" << endl;
- s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long}," << endl;
- s << "#endif" << endl;
- s << INDENT << "{0, " << NULL_PTR << "} // sentinel" << endl;
- s << "};" << endl << endl;
+ s << "static PyType_Slot " << cpythonName << "_number_slots[] = {\n";
+ s << "#ifdef IS_PY3K\n";
+ s << INDENT << "{Py_nb_bool, reinterpret_cast<void *>(" << cpythonName << "__nonzero)},\n";
+ s << "#else\n";
+ s << INDENT << "{Py_nb_nonzero, reinterpret_cast<void *>(" << cpythonName << "__nonzero)},\n";
+ s << INDENT << "{Py_nb_long, reinterpret_cast<void *>(" << cpythonName << "_long)},\n";
+ s << "#endif\n";
+ s << INDENT << "{Py_nb_invert, reinterpret_cast<void *>(" << cpythonName << "___invert__)},\n";
+ s << INDENT << "{Py_nb_and, reinterpret_cast<void *>(" << cpythonName << "___and__)},\n";
+ s << INDENT << "{Py_nb_xor, reinterpret_cast<void *>(" << cpythonName << "___xor__)},\n";
+ s << INDENT << "{Py_nb_or, reinterpret_cast<void *>(" << cpythonName << "___or__)},\n";
+ s << INDENT << "{Py_nb_int, reinterpret_cast<void *>(" << cpythonName << "_long)},\n";
+ s << INDENT << "{Py_nb_index, reinterpret_cast<void *>(" << cpythonName << "_long)},\n";
+ s << "#ifndef IS_PY3K\n";
+ s << INDENT << "{Py_nb_long, reinterpret_cast<void *>(" << cpythonName << "_long)},\n";
+ s << "#endif\n";
+ s << INDENT << "{0, " << NULL_PTR << "} // sentinel\n";
+ s << "};\n\n";
+}
+
+void CppGenerator::writeFlagsNumberMethodsDefinitions(QTextStream &s, const AbstractMetaEnumList &enums)
+{
+ for (AbstractMetaEnum *e : enums) {
+ if (!e->isAnonymous() && !e->isPrivate() && e->typeEntry()->flags()) {
+ writeFlagsMethods(s, e);
+ writeFlagsNumberMethodsDefinition(s, e);
+ s << '\n';
+ }
+ }
}
void CppGenerator::writeFlagsBinaryOperator(QTextStream &s, const AbstractMetaEnum *cppEnum,
@@ -4849,27 +5213,29 @@ void CppGenerator::writeFlagsBinaryOperator(QTextStream &s, const AbstractMetaEn
FlagsTypeEntry *flagsEntry = cppEnum->typeEntry()->flags();
Q_ASSERT(flagsEntry);
- s << "PyObject * " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")" << endl;
- s << '{' << endl;
+ s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName
+ << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")\n{\n";
AbstractMetaType *flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " << CPP_SELF_VAR << ", cppArg;" << endl;
- s << "#ifdef IS_PY3K" << endl;
+ s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " << CPP_SELF_VAR << ", cppArg;\n";
+ s << "#ifdef IS_PY3K\n";
s << INDENT << CPP_SELF_VAR << " = static_cast<::" << flagsEntry->originalName()
- << ">(int(PyLong_AsLong(self)));" << endl;
+ << ">(int(PyLong_AsLong(self)));\n";
s << INDENT << "cppArg = static_cast<" << flagsEntry->originalName() << ">(int(PyLong_AsLong("
- << PYTHON_ARG << ")));" << endl;
- s << "#else" << endl;
+ << PYTHON_ARG << ")));\n";
+ s << "#else\n";
s << INDENT << CPP_SELF_VAR << " = static_cast<::" << flagsEntry->originalName()
- << ">(int(PyInt_AsLong(self)));" << endl;
+ << ">(int(PyInt_AsLong(self)));\n";
s << INDENT << "cppArg = static_cast<" << flagsEntry->originalName()
- << ">(int(PyInt_AsLong(" << PYTHON_ARG << ")));" << endl;
- s << "#endif" << endl << endl;
- s << INDENT << "cppResult = " << CPP_SELF_VAR << " " << cppOpName << " cppArg;" << endl;
+ << ">(int(PyInt_AsLong(" << PYTHON_ARG << ")));\n";
+ s << "#endif\n\n";
+ s << INDENT << "if (PyErr_Occurred())\n" << indent(INDENT)
+ << INDENT << "return nullptr;\n" << outdent(INDENT);
+ s << INDENT << "cppResult = " << CPP_SELF_VAR << " " << cppOpName << " cppArg;\n";
s << INDENT << "return ";
writeToPythonConversion(s, flagsType, nullptr, QLatin1String("cppResult"));
- s << ';' << endl;
- s << '}' << endl << endl;
+ s << ";\n";
+ s<< "}\n\n";
}
void CppGenerator::writeFlagsUnaryOperator(QTextStream &s, const AbstractMetaEnum *cppEnum,
@@ -4879,25 +5245,25 @@ void CppGenerator::writeFlagsUnaryOperator(QTextStream &s, const AbstractMetaEnu
FlagsTypeEntry *flagsEntry = cppEnum->typeEntry()->flags();
Q_ASSERT(flagsEntry);
- s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")" << endl;
- s << '{' << endl;
+ s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName
+ << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")\n{\n";
AbstractMetaType *flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry);
- s << INDENT << "::" << flagsEntry->originalName() << " " << CPP_SELF_VAR << ";" << endl;
- s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &" << CPP_SELF_VAR << ");" << endl;
+ s << INDENT << "::" << flagsEntry->originalName() << " " << CPP_SELF_VAR << ";\n";
+ s << INDENT << cpythonToCppConversionFunction(flagsType) << "self, &" << CPP_SELF_VAR << ");\n";
s << INDENT;
if (boolResult)
s << "bool";
else
s << "::" << flagsEntry->originalName();
- s << " cppResult = " << cppOpName << CPP_SELF_VAR << ';' << endl;
+ s << " cppResult = " << cppOpName << CPP_SELF_VAR << ";\n";
s << INDENT << "return ";
if (boolResult)
s << "PyBool_FromLong(cppResult)";
else
writeToPythonConversion(s, flagsType, nullptr, QLatin1String("cppResult"));
- s << ';' << endl;
- s << '}' << endl << endl;
+ s << ";\n";
+ s<< "}\n\n";
}
QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const
@@ -4911,64 +5277,75 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me
return initFunctionName;
}
-QString CppGenerator::getInitFunctionName(GeneratorContext &context) const
+QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const
{
return !context.forSmartPointer()
? getSimpleClassInitFunctionName(context.metaClass())
: getFilteredCppSignatureString(context.preciseType()->cppSignature());
}
+void CppGenerator::writeSignatureStrings(QTextStream &s,
+ QTextStream &signatureStream,
+ const QString &arrayName,
+ const char *comment) const
+{
+ s << "// The signatures string for the " << comment << ".\n";
+ s << "// Multiple signatures have their index \"n:\" in front.\n";
+ s << "static const char *" << arrayName << "_SignatureStrings[] = {\n";
+ QString line;
+ while (signatureStream.readLineInto(&line)) {
+ // must anything be escaped?
+ if (line.contains(QLatin1Char('"')) || line.contains(QLatin1Char('\\')))
+ s << INDENT << "R\"CPP(" << line << ")CPP\",\n";
+ else
+ s << INDENT << '"' << line << "\",\n";
+ }
+ s << INDENT << NULL_PTR << "}; // Sentinel\n\n";
+}
+
void CppGenerator::writeClassRegister(QTextStream &s,
const AbstractMetaClass *metaClass,
- GeneratorContext &classContext,
+ const GeneratorContext &classContext,
QTextStream &signatureStream)
{
const ComplexTypeEntry *classTypeEntry = metaClass->typeEntry();
- const AbstractMetaClass *enc = metaClass->enclosingClass();
- bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass;
- QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module");
+ const AbstractMetaClass *enc = metaClass->targetLangEnclosingClass();
+ QString enclosingObjectVariable = enc ? QLatin1String("enclosingClass") : QLatin1String("module");
QString pyTypeName = cpythonTypeName(metaClass);
QString initFunctionName = getInitFunctionName(classContext);
// PYSIDE-510: Create a signatures string for the introspection feature.
- s << "// The signatures string for the functions." << endl;
- s << "// Multiple signatures have their index \"n:\" in front." << endl;
- s << "static const char *" << initFunctionName << "_SignatureStrings[] = {" << endl;
- QString line;
- while (signatureStream.readLineInto(&line))
- s << INDENT << '"' << line << "\"," << endl;
- s << INDENT << NULL_PTR << "}; // Sentinel" << endl << endl;
+ writeSignatureStrings(s, signatureStream, initFunctionName, "functions");
s << "void init_" << initFunctionName;
- s << "(PyObject *" << enclosingObjectVariable << ")" << endl;
- s << '{' << endl;
+ s << "(PyObject *" << enclosingObjectVariable << ")\n{\n";
// Multiple inheritance
QString pyTypeBasesVariable = chopType(pyTypeName) + QLatin1String("_Type_bases");
const AbstractMetaClassList baseClasses = getBaseClasses(metaClass);
if (metaClass->baseClassNames().size() > 1) {
s << INDENT << "PyObject *" << pyTypeBasesVariable
- << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl;
+ << " = PyTuple_Pack(" << baseClasses.size() << ',' << Qt::endl;
Indentation indent(INDENT);
for (int i = 0, size = baseClasses.size(); i < size; ++i) {
if (i)
- s << "," << endl;
+ s << ",\n";
s << INDENT << "reinterpret_cast<PyObject *>("
<< cpythonTypeNameExt(baseClasses.at(i)->typeEntry()) << ')';
}
- s << ");" << endl << endl;
+ s << ");\n\n";
}
// Create type and insert it in the module or enclosing class.
const QString typePtr = QLatin1String("_") + chopType(pyTypeName)
+ QLatin1String("_Type");
- s << INDENT << typePtr << " = Shiboken::ObjectType::introduceWrapperType(" << endl;
+ s << INDENT << typePtr << " = Shiboken::ObjectType::introduceWrapperType(\n";
{
Indentation indent(INDENT);
// 1:enclosingObject
- s << INDENT << enclosingObjectVariable << "," << endl;
+ s << INDENT << enclosingObjectVariable << ",\n";
QString typeName;
if (!classContext.forSmartPointer())
typeName = metaClass->name();
@@ -4976,7 +5353,7 @@ void CppGenerator::writeClassRegister(QTextStream &s,
typeName = classContext.preciseType()->cppSignature();
// 2:typeName
- s << INDENT << "\"" << typeName << "\"," << endl;
+ s << INDENT << "\"" << typeName << "\",\n";
// 3:originalName
s << INDENT << "\"";
@@ -4988,46 +5365,52 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << classContext.preciseType()->cppSignature();
}
- s << "\"," << endl;
+ s << "\",\n";
// 4:typeSpec
- s << INDENT << '&' << chopType(pyTypeName) << "_spec," << endl;
-
- // 5:signatureStrings
- s << INDENT << initFunctionName << "_SignatureStrings," << endl;
+ s << INDENT << '&' << chopType(pyTypeName) << "_spec,\n";
- // 6:cppObjDtor
+ // 5:cppObjDtor
s << INDENT;
if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) {
QString dtorClassName = metaClass->qualifiedCppName();
- if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue())
- dtorClassName = wrapperName(metaClass);
+ if (((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue())
+ && classContext.useWrapper()) {
+ dtorClassName = classContext.wrapperName();
+ }
if (classContext.forSmartPointer())
- dtorClassName = wrapperName(classContext.preciseType());
+ dtorClassName = classContext.smartPointerWrapperName();
- s << "&Shiboken::callCppDestructor< ::" << dtorClassName << " >," << endl;
+ s << "&Shiboken::callCppDestructor< ::" << dtorClassName << " >,\n";
} else {
- s << "0," << endl;
+ s << "0,\n";
}
- // 7:baseType
- const auto base = metaClass->isNamespace()
+ // 6:baseType: Find a type that is not disabled.
+ auto base = metaClass->isNamespace()
? metaClass->extendedNamespace() : metaClass->baseClass();
+ if (!metaClass->isNamespace()) {
+ for (; base != nullptr; base = base->baseClass()) {
+ const auto ct = base->typeEntry()->codeGeneration();
+ if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass)
+ break;
+ }
+ }
if (base) {
s << INDENT << "reinterpret_cast<SbkObjectType *>("
- << cpythonTypeNameExt(base->typeEntry()) << ")," << endl;
+ << cpythonTypeNameExt(base->typeEntry()) << "),\n";
} else {
- s << INDENT << "0," << endl;
+ s << INDENT << "0,\n";
}
- // 8:baseTypes
+ // 7:baseTypes
if (metaClass->baseClassNames().size() > 1)
- s << INDENT << pyTypeBasesVariable << ',' << endl;
+ s << INDENT << pyTypeBasesVariable << ',' << Qt::endl;
else
- s << INDENT << "0," << endl;
+ s << INDENT << "0,\n";
- // 9:wrapperflags
+ // 8:wrapperflags
QByteArrayList wrapperFlags;
- if (hasEnclosingClass)
+ if (enc)
wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::InnerClass"));
if (metaClass->deleteInMainThread())
wrapperFlags.append(QByteArrayLiteral("Shiboken::ObjectType::WrapperFlags::DeleteInMainThread"));
@@ -5036,24 +5419,33 @@ void CppGenerator::writeClassRegister(QTextStream &s,
else
s << INDENT << wrapperFlags.join(" | ");
}
- s << INDENT << ");" << endl;
- s << INDENT << endl;
+ s << INDENT << ");\n";
+ s << INDENT << Qt::endl;
+
+ s << INDENT << "auto pyType = reinterpret_cast<PyTypeObject *>(" << typePtr << ");\n";
+ s << INDENT << "InitSignatureStrings(pyType, " << initFunctionName << "_SignatureStrings);\n";
+
+ if (usePySideExtensions())
+ s << INDENT << "SbkObjectType_SetPropertyStrings(reinterpret_cast<PyTypeObject *>(" << typePtr << "), "
+ << chopType(pyTypeName) << "_PropertyStrings);\n";
if (!classContext.forSmartPointer())
- s << INDENT << cpythonTypeNameExt(classTypeEntry) << endl;
+ s << INDENT << cpythonTypeNameExt(classTypeEntry) << Qt::endl;
else
- s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << endl;
- s << INDENT << " = reinterpret_cast<PyTypeObject *>(" << pyTypeName << ");" << endl;
- s << endl;
+ s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << Qt::endl;
+ s << INDENT << " = reinterpret_cast<PyTypeObject *>(" << pyTypeName << ");\n";
+ s << Qt::endl;
// Register conversions for the type.
writeConverterRegister(s, metaClass, classContext);
- s << endl;
+ s << Qt::endl;
// class inject-code target/beginning
if (!classTypeEntry->codeSnips().isEmpty()) {
- writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, metaClass);
- s << endl;
+ writeClassCodeSnips(s, classTypeEntry->codeSnips(),
+ TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode,
+ classContext);
+ s << Qt::endl;
}
// Fill multiple inheritance data, if needed.
@@ -5061,27 +5453,25 @@ void CppGenerator::writeClassRegister(QTextStream &s,
if (miClass) {
s << INDENT << "MultipleInheritanceInitFunction func = ";
if (miClass == metaClass) {
- s << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl;
+ s << multipleInheritanceInitializerFunctionName(miClass) << ";\n";
} else {
s << "Shiboken::ObjectType::getMultipleInheritanceFunction(reinterpret_cast<SbkObjectType *>(";
- s << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl;
+ s << cpythonTypeNameExt(miClass->typeEntry()) << "));\n";
}
s << INDENT << "Shiboken::ObjectType::setMultipleInheritanceFunction(";
- s << cpythonTypeName(metaClass) << ", func);" << endl;
+ s << cpythonTypeName(metaClass) << ", func);\n";
s << INDENT << "Shiboken::ObjectType::setCastFunction(" << cpythonTypeName(metaClass);
- s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl;
+ s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");\n";
}
// Set typediscovery struct or fill the struct of another one
if (metaClass->isPolymorphic() && metaClass->baseClass()) {
s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(" << cpythonTypeName(metaClass);
- s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl << endl;
+ s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);\n\n";
}
AbstractMetaEnumList classEnums = metaClass->enums();
- const AbstractMetaClassList &innerClasses = metaClass->innerClasses();
- for (AbstractMetaClass *innerClass : innerClasses)
- lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+ metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
ErrorCode errorCode(QString::fromLatin1(""));
writeEnumsInitialization(s, classEnums);
@@ -5097,33 +5487,40 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << INDENT << QLatin1String("PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(") + cpythonTypeName(metaClass) + QLatin1String(")->tp_dict, \"");
s << field->name() << "\", ";
writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name());
- s << ");" << endl;
+ s << ");\n";
}
- s << endl;
+ s << Qt::endl;
// class inject-code target/end
if (!classTypeEntry->codeSnips().isEmpty()) {
- s << endl;
- writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, metaClass);
+ s << Qt::endl;
+ writeClassCodeSnips(s, classTypeEntry->codeSnips(),
+ TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode,
+ classContext);
}
if (usePySideExtensions()) {
- if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass))
- s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n";
+ if (avoidProtectedHack() && classContext.useWrapper())
+ s << INDENT << classContext.wrapperName() << "::pysideInitQtMetaTypes();\n";
else
writeInitQtMetaTypeFunctionBody(s, classContext);
}
if (usePySideExtensions() && metaClass->isQObject()) {
- s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(" << pyTypeName << ", &PySide::initQObjectSubType);" << endl;
+ s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(" << pyTypeName << ", &PySide::initQObjectSubType);\n";
s << INDENT << "PySide::initDynamicMetaObject(" << pyTypeName << ", &::" << metaClass->qualifiedCppName()
- << "::staticMetaObject, sizeof(::" << metaClass->qualifiedCppName() << "));" << endl;
+ << "::staticMetaObject, sizeof(";
+ if (shouldGenerateCppWrapper(metaClass))
+ s << wrapperName(metaClass);
+ else
+ s << "::" << metaClass->qualifiedCppName();
+ s << "));\n";
}
- s << '}' << endl;
+ s << "}\n";
}
-void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const
+void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, const GeneratorContext &context) const
{
const AbstractMetaClass *metaClass = context.metaClass();
// Gets all class name variants used on different possible scopes
@@ -5170,20 +5567,19 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorCont
.arg(QFile::decodeName(__FILE__)).arg(__LINE__);
continue;
}
- s << INDENT << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");" << endl;
+ s << INDENT << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");\n";
}
}
}
- const AbstractMetaEnumList &enums = metaClass->enums();
- for (AbstractMetaEnum *metaEnum : enums) {
+ for (AbstractMetaEnum *metaEnum : metaClass->enums()) {
if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) {
for (const QString &name : qAsConst(nameVariants))
- s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");" << endl;
+ s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");\n";
if (metaEnum->typeEntry()->flags()) {
QString n = metaEnum->typeEntry()->flags()->originalName();
- s << INDENT << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");" << endl;
+ s << INDENT << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");\n";
}
}
}
@@ -5193,17 +5589,17 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream &s, const AbstractMeta
{
QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue();
- s << "static void *" << cpythonBaseName(metaClass) << "_typeDiscovery(void *cptr, SbkObjectType *instanceType)\n{" << endl;
+ s << "static void *" << cpythonBaseName(metaClass) << "_typeDiscovery(void *cptr, SbkObjectType *instanceType)\n{\n";
if (!polymorphicExpr.isEmpty()) {
polymorphicExpr = polymorphicExpr.replace(QLatin1String("%1"),
QLatin1String(" reinterpret_cast< ::")
+ metaClass->qualifiedCppName()
+ QLatin1String(" *>(cptr)"));
- s << INDENT << " if (" << polymorphicExpr << ")" << endl;
+ s << INDENT << " if (" << polymorphicExpr << ")\n";
{
Indentation indent(INDENT);
- s << INDENT << "return cptr;" << endl;
+ s << INDENT << "return cptr;\n";
}
} else if (metaClass->isPolymorphic()) {
const AbstractMetaClassList &ancestors = getAllAncestors(metaClass);
@@ -5212,10 +5608,10 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream &s, const AbstractMeta
continue;
if (ancestor->isPolymorphic()) {
s << INDENT << "if (instanceType == reinterpret_cast<SbkObjectType *>(Shiboken::SbkType< ::"
- << ancestor->qualifiedCppName() << " >()))" << endl;
+ << ancestor->qualifiedCppName() << " >()))\n";
Indentation indent(INDENT);
s << INDENT << "return dynamic_cast< ::" << metaClass->qualifiedCppName()
- << " *>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << " *>(cptr));" << endl;
+ << " *>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << " *>(cptr));\n";
} else {
qCWarning(lcShiboken).noquote().nospace()
<< metaClass->qualifiedCppName() << " inherits from a non polymorphic type ("
@@ -5225,7 +5621,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream &s, const AbstractMeta
}
}
- s << INDENT << "return {};" << endl;
+ s << INDENT << "return {};\n";
s << "}\n\n";
}
@@ -5235,168 +5631,250 @@ QString CppGenerator::writeSmartPointerGetterCast()
+ QLatin1String(SMART_POINTER_GETTER) + QLatin1Char(')');
}
-void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeSetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass) const
{
+ s << "static int " << ShibokenGenerator::cpythonSetattroFunctionName(metaClass)
+ << "(PyObject *self, PyObject *name, PyObject *value)\n{\n";
+ if (wrapperDiagnostics()) {
+ s << INDENT << R"(std::cerr << __FUNCTION__ << ' ' << Shiboken::debugPyObject(name)
+ << ' ' << Shiboken::debugPyObject(value) << '\n';)" << '\n';
+ }
+}
+
+inline void CppGenerator::writeSetattroDefaultReturn(QTextStream &s) const
+{
+ s << INDENT << "return PyObject_GenericSetAttr(self, name, value);\n}\n\n";
+}
+
+void CppGenerator::writeSetattroFunction(QTextStream &s, AttroCheck attroCheck,
+ const GeneratorContext &context)
+{
+ Q_ASSERT(!context.forSmartPointer());
const AbstractMetaClass *metaClass = context.metaClass();
- s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject *self, PyObject *name, PyObject *value)" << endl;
- s << '{' << endl;
- if (usePySideExtensions()) {
- s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject *>(PySide::Property::getObject(self, name)));" << endl;
- s << INDENT << "if (!pp.isNull())" << endl;
+ writeSetattroDefinition(s, metaClass);
+
+ // PYSIDE-1019: Switch tp_dict before doing tp_setattro.
+ if (usePySideExtensions())
+ s << INDENT << "PySide::Feature::Select(self);\n";
+
+ // PYSIDE-803: Detect duck-punching; clear cache if a method is set.
+ if (attroCheck.testFlag(AttroCheckFlag::SetattroMethodOverride)
+ && context.useWrapper()) {
+ s << INDENT << "if (value && PyCallable_Check(value)) {\n";
+ s << INDENT << " auto plain_inst = " << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n";
+ s << INDENT << " auto inst = dynamic_cast<" << context.wrapperName() << " *>(plain_inst);\n";
+ s << INDENT << " if (inst)\n";
+ s << INDENT << " inst->resetPyMethodCache();\n";
+ s << INDENT << "}\n";
+ }
+ if (attroCheck.testFlag(AttroCheckFlag::SetattroQObject)) {
+ s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast<PyObject *>(PySide::Property::getObject(self, name)));\n";
+ s << INDENT << "if (!pp.isNull())\n";
Indentation indent(INDENT);
- s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);" << endl;
+ s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty *>(pp.object()), self, value);\n";
}
- if (context.forSmartPointer()) {
- s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer." << endl;
- s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, "
- << writeSmartPointerGetterCast() << ", 0);" << endl;
- s << INDENT << "if (rawObj) {" << endl;
+ if (attroCheck.testFlag(AttroCheckFlag::SetattroUser)) {
+ auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::SetAttroFunction);
+ Q_ASSERT(func);
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
- s << INDENT << "int hasAttribute = PyObject_HasAttr(rawObj, name);" << endl;
- s << INDENT << "if (hasAttribute) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return PyObject_GenericSetAttr(rawObj, name, value);" << endl;
- }
- s << INDENT << '}' << endl;
- s << INDENT << "Py_DECREF(rawObj);" << endl;
+ s << INDENT << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n";
+ writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, context);
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
+ }
+
+ writeSetattroDefaultReturn(s);
+}
+void CppGenerator::writeSmartPointerSetattroFunction(QTextStream &s, const GeneratorContext &context)
+{
+ Q_ASSERT(context.forSmartPointer());
+ writeSetattroDefinition(s, context.metaClass());
+ s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer.\n";
+ s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, "
+ << writeSmartPointerGetterCast() << ", 0);\n";
+ s << INDENT << "if (rawObj) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "int hasAttribute = PyObject_HasAttr(rawObj, name);\n";
+ s << INDENT << "if (hasAttribute) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return PyObject_GenericSetAttr(rawObj, name, value);\n";
+ }
+ s << INDENT << "}\n";
+ s << INDENT << "Py_DECREF(rawObj);\n";
}
+ s << INDENT << "}\n";
+ writeSetattroDefaultReturn(s);
+}
- s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl;
- s << '}' << endl;
+void CppGenerator::writeGetattroDefinition(QTextStream &s, const AbstractMetaClass *metaClass)
+{
+ s << "static PyObject *" << cpythonGetattroFunctionName(metaClass)
+ << "(PyObject *self, PyObject *name)\n{\n";
}
-static inline QString qObjectClassName() { return QStringLiteral("QObject"); }
-static inline QString qMetaObjectClassName() { return QStringLiteral("QMetaObject"); }
+QString CppGenerator::qObjectGetAttroFunction() const
+{
+ static QString result;
+ if (result.isEmpty()) {
+ AbstractMetaClass *qobjectClass = AbstractMetaClass::findClass(classes(), qObjectT());
+ Q_ASSERT(qobjectClass);
+ result = QLatin1String("PySide::getMetaDataFromQObject(")
+ + cpythonWrapperCPtr(qobjectClass, QLatin1String("self"))
+ + QLatin1String(", self, name)");
+ }
+ return result;
+}
-void CppGenerator::writeGetattroFunction(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeGetattroFunction(QTextStream &s, AttroCheck attroCheck,
+ const GeneratorContext &context)
{
+ Q_ASSERT(!context.forSmartPointer());
const AbstractMetaClass *metaClass = context.metaClass();
- s << "static PyObject *" << cpythonGetattroFunctionName(metaClass) << "(PyObject *self, PyObject *name)" << endl;
- s << '{' << endl;
+ writeGetattroDefinition(s, metaClass);
- QString getattrFunc;
- if (usePySideExtensions() && metaClass->isQObject()) {
- AbstractMetaClass *qobjectClass = AbstractMetaClass::findClass(classes(), qObjectClassName());
- QTextStream(&getattrFunc) << "PySide::getMetaDataFromQObject("
- << cpythonWrapperCPtr(qobjectClass, QLatin1String("self"))
- << ", self, name)";
- } else {
- getattrFunc = QLatin1String("PyObject_GenericGetAttr(") + QLatin1String("self")
- + QLatin1String(", name)");
- }
+ // PYSIDE-1019: Switch tp_dict before doing tp_getattro.
+ if (usePySideExtensions())
+ s << INDENT << "PySide::Feature::Select(self);\n";
- if (classNeedsGetattroFunction(metaClass)) {
- s << INDENT << "if (self) {" << endl;
+ const QString getattrFunc = usePySideExtensions() && metaClass->isQObject()
+ ? qObjectGetAttroFunction() : QLatin1String("PyObject_GenericGetAttr(self, name)");
+
+ if (attroCheck.testFlag(AttroCheckFlag::GetattroOverloads)) {
+ s << INDENT << "// Search the method in the instance dict\n";
+ s << INDENT << "if (auto ob_dict = reinterpret_cast<SbkObject *>(self)->ob_dict) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "// Search the method in the instance dict" << endl;
- s << INDENT << "if (reinterpret_cast<SbkObject *>(self)->ob_dict) {" << endl;
+ s << INDENT << "if (auto meth = PyDict_GetItem(ob_dict, name)) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyObject *meth = PyDict_GetItem(reinterpret_cast<SbkObject *>(self)->ob_dict, name);" << endl;
- s << INDENT << "if (meth) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "Py_INCREF(meth);" << endl;
- s << INDENT << "return meth;" << endl;
- }
- s << INDENT << '}' << endl;
+ s << INDENT << "Py_INCREF(meth);\n";
+ s << INDENT << "return meth;\n";
}
- s << INDENT << '}' << endl;
- s << INDENT << "// Search the method in the type dict" << endl;
- s << INDENT << "if (Shiboken::Object::isUserType(self)) {" << endl;
+ s << INDENT << "}\n";
+ }
+ s << INDENT << "}\n";
+ s << INDENT << "// Search the method in the type dict\n";
+ s << INDENT << "if (Shiboken::Object::isUserType(self)) {\n";
+ {
+ Indentation indent(INDENT);
+ // PYSIDE-772: Perform optimized name mangling.
+ s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));\n";
+ s << INDENT << "if (auto meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp))\n";
{
Indentation indent(INDENT);
- // PYSIDE-772: Perform optimized name mangling.
- s << INDENT << "Shiboken::AutoDecRef tmp(_Pep_PrivateMangle(self, name));" << endl;
- s << INDENT << "PyObject *meth = PyDict_GetItem(Py_TYPE(self)->tp_dict, tmp);" << endl;
- s << INDENT << "if (meth)" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, self) : " << getattrFunc << ';' << endl;
- }
+ s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, self) : " << getattrFunc << ";\n";
}
- s << INDENT << '}' << endl;
+ }
+ s << INDENT << "}\n";
- const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass);
- for (const AbstractMetaFunction *func : funcs) {
- QString defName = cpythonMethodDefinitionName(func);
- s << INDENT << "static PyMethodDef non_static_" << defName << " = {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << defName << ".ml_name," << endl;
- s << INDENT << defName << ".ml_meth," << endl;
- s << INDENT << defName << ".ml_flags & (~METH_STATIC)," << endl;
- s << INDENT << defName << ".ml_doc," << endl;
- }
- s << INDENT << "};" << endl;
- s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)" << endl;
+ const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass);
+ for (const AbstractMetaFunction *func : funcs) {
+ QString defName = cpythonMethodDefinitionName(func);
+ s << INDENT << "static PyMethodDef non_static_" << defName << " = {\n";
+ {
Indentation indent(INDENT);
- s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);" << endl;
+ s << INDENT << defName << ".ml_name,\n";
+ s << INDENT << defName << ".ml_meth,\n";
+ s << INDENT << defName << ".ml_flags & (~METH_STATIC),\n";
+ s << INDENT << defName << ".ml_doc,\n";
}
+ s << INDENT << "};\n";
+ s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)\n";
+ Indentation indent(INDENT);
+ s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", self, 0);\n";
}
- s << INDENT << '}' << endl;
}
- if (context.forSmartPointer()) {
- s << INDENT << "PyObject *tmp = " << getattrFunc << ';' << endl;
- s << INDENT << "if (tmp) {" << endl;
+ if (attroCheck.testFlag(AttroCheckFlag::GetattroUser)) {
+ auto func = AbstractMetaClass::queryFirstFunction(metaClass->functions(),
+ AbstractMetaClass::GetAttroFunction);
+ Q_ASSERT(func);
+ s << INDENT << "{\n";
{
Indentation indent(INDENT);
- s << INDENT << "return tmp;" << endl;
+ s << INDENT << "auto " << CPP_SELF_VAR << " = "
+ << cpythonWrapperCPtr(metaClass, QLatin1String("self")) << ";\n";
+ writeClassCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionAny,
+ TypeSystem::TargetLangCode, context);
}
- s << INDENT << "} else {" << endl;
+ s << INDENT << "}\n";
+ }
+
+ s << INDENT << "return " << getattrFunc << ";\n}\n\n";
+}
+
+void CppGenerator::writeSmartPointerGetattroFunction(QTextStream &s, const GeneratorContext &context)
+{
+ Q_ASSERT(context.forSmartPointer());
+ const AbstractMetaClass *metaClass = context.metaClass();
+ writeGetattroDefinition(s, metaClass);
+ s << INDENT << "PyObject *tmp = PyObject_GenericGetAttr(self, name);\n";
+ s << INDENT << "if (tmp)\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return tmp;\n";
+ }
+ s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError))\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return nullptr;\n";
+ }
+ s << INDENT << "PyErr_Clear();\n";
+
+ // This generates the code which dispatches access to member functions
+ // and fields from the smart pointer to its pointee.
+ s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for "
+ "the corresponding C++ object held by the smart pointer.\n";
+ s << INDENT << "if (auto rawObj = PyObject_CallMethod(self, "
+ << writeSmartPointerGetterCast() << ", 0)) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "if (auto attribute = PyObject_GetAttr(rawObj, name))\n";
{
Indentation indent(INDENT);
- s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return nullptr;" << endl;
- s << INDENT << "PyErr_Clear();" << endl;
-
- s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for "
- "the corresponding C++ object held by the smart pointer." << endl;
- s << INDENT << "PyObject *rawObj = PyObject_CallMethod(self, "
- << writeSmartPointerGetterCast() << ", 0);" << endl;
- s << INDENT << "if (rawObj) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyObject *attribute = PyObject_GetAttr(rawObj, name);" << endl;
- s << INDENT << "if (attribute) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "tmp = attribute;" << endl;
- }
- s << INDENT << '}' << endl;
- s << INDENT << "Py_DECREF(rawObj);" << endl;
- }
- s << INDENT << '}' << endl;
- s << INDENT << "if (!tmp) {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl;
- s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl;
- s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl;
- s << INDENT << " tp->tp_name, Shiboken::String::toCString(name));" << endl;
- s << INDENT << "return nullptr;" << endl;
- }
- s << INDENT << "} else {" << endl;
- {
- Indentation indent(INDENT);
- s << INDENT << "return tmp;" << endl;
- }
- s << INDENT << '}' << endl;
-
+ s << INDENT << "tmp = attribute;\n";
}
- s << INDENT << '}' << endl;
-
+ s << INDENT << "Py_DECREF(rawObj);\n";
+ }
+ s << INDENT << "}\n";
+ s << INDENT << "if (!tmp) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "PyTypeObject *tp = Py_TYPE(self);\n";
+ s << INDENT << "PyErr_Format(PyExc_AttributeError,\n";
+ s << INDENT << " \"'%.50s' object has no attribute '%.400s'\",\n";
+ s << INDENT << " tp->tp_name, Shiboken::String::toCString(name));\n";
+ }
+ s << INDENT << "}\n";
+ s << INDENT << "return tmp;\n}\n\n";
+}
+
+// Write declaration and invocation of the init function for the module init
+// function.
+void CppGenerator::writeInitFunc(QTextStream &declStr, QTextStream &callStr,
+ const Indentor &indent, const QString &initFunctionName,
+ const TypeEntry *enclosingEntry)
+{
+ const bool hasParent =
+ enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType;
+ declStr << "void init_" << initFunctionName << "(PyObject *"
+ << (hasParent ? "enclosingClass" : "module") << ");\n";
+ callStr << indent << "init_" << initFunctionName;
+ if (hasParent) {
+ callStr << "(reinterpret_cast<PyTypeObject *>("
+ << cpythonTypeNameExt(enclosingEntry) << ")->tp_dict);\n";
} else {
- s << INDENT << "return " << getattrFunc << ';' << endl;
+ callStr << "(module);\n";
}
- s << '}' << endl;
}
bool CppGenerator::finishGeneration()
@@ -5415,7 +5893,7 @@ bool CppGenerator::finishGeneration()
QString signaturesString;
QTextStream signatureStream(&signaturesString);
- Indentation indent(INDENT);
+ Indentation indentation(INDENT);
const auto functionGroups = getGlobalFunctionGroups();
for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
@@ -5442,8 +5920,8 @@ bool CppGenerator::finishGeneration()
//We need move QMetaObject register before QObject
Dependencies additionalDependencies;
const AbstractMetaClassList &allClasses = classes();
- if (auto qObjectClass = AbstractMetaClass::findClass(allClasses, qObjectClassName())) {
- if (auto qMetaObjectClass = AbstractMetaClass::findClass(allClasses, qMetaObjectClassName())) {
+ if (auto qObjectClass = AbstractMetaClass::findClass(allClasses, qObjectT())) {
+ if (auto qMetaObjectClass = AbstractMetaClass::findClass(allClasses, qMetaObjectT())) {
Dependency dependency;
dependency.parent = qMetaObjectClass;
dependency.child = qObjectClass;
@@ -5453,33 +5931,20 @@ bool CppGenerator::finishGeneration()
const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies);
for (const AbstractMetaClass *cls : lst){
- if (!shouldGenerate(cls))
- continue;
-
- const QString initFunctionName = QLatin1String("init_") + getSimpleClassInitFunctionName(cls);
-
- s_classInitDecl << "void " << initFunctionName << "(PyObject *module);" << endl;
-
- s_classPythonDefines << INDENT << initFunctionName;
- if (cls->enclosingClass()
- && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) {
- s_classPythonDefines << "(reinterpret_cast<PyTypeObject *>("
- << cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) << ")->tp_dict);";
- } else {
- s_classPythonDefines << "(module);";
+ if (shouldGenerate(cls)) {
+ writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT,
+ getSimpleClassInitFunctionName(cls),
+ cls->typeEntry()->targetLangEnclosingEntry());
}
- s_classPythonDefines << endl;
}
// Initialize smart pointer types.
const QVector<const AbstractMetaType *> &smartPtrs = instantiatedSmartPointers();
for (const AbstractMetaType *metaType : smartPtrs) {
- GeneratorContext context(nullptr, metaType, true);
- QString initFunctionName = getInitFunctionName(context);
- s_classInitDecl << "void init_" << initFunctionName << "(PyObject *module);" << endl;
- QString defineStr = QLatin1String("init_") + initFunctionName;
- defineStr += QLatin1String("(module);");
- s_classPythonDefines << INDENT << defineStr << endl;
+ GeneratorContext context = contextForSmartPointer(nullptr, metaType);
+ writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT,
+ getInitFunctionName(context),
+ metaType->typeEntry()->targetLangEnclosingEntry());
}
QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName()));
@@ -5492,135 +5957,126 @@ bool CppGenerator::finishGeneration()
QTextStream &s = file.stream;
// write license comment
- s << licenseComment() << endl;
+ s << licenseComment() << Qt::endl;
- s << "#include <sbkpython.h>" << endl;
- s << "#include <shiboken.h>" << endl;
- s << "#include <algorithm>" << endl;
- s << "#include <signature.h>" << endl;
+ s << "#include <sbkpython.h>\n";
+ s << "#include <shiboken.h>\n";
+ s << "#include <algorithm>\n";
+ s << "#include <signature.h>\n";
if (usePySideExtensions()) {
s << includeQDebug;
- s << "#include <pyside.h>" << endl;
- s << "#include <qapp_macro.h>" << endl;
+ s << "#include <pyside.h>\n";
+ s << "#include <pysideqenum.h>\n";
+ s << "#include <feature_select.h>\n";
}
- s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl;
+ s << "#include \"" << getModuleHeaderFileName() << '"' << Qt::endl << Qt::endl;
for (const Include &include : qAsConst(includes))
s << include;
- s << endl;
+ s << Qt::endl;
// Global enums
AbstractMetaEnumList globalEnums = this->globalEnums();
- const AbstractMetaClassList &classList = classes();
- for (const AbstractMetaClass *metaClass : classList) {
- const AbstractMetaClass *encClass = metaClass->enclosingClass();
- if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)
- continue;
- lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
- }
+ for (const AbstractMetaClass *nsp : invisibleTopNamespaces())
+ nsp->getEnumsToBeGenerated(&globalEnums);
TypeDatabase *typeDb = TypeDatabase::instance();
const TypeSystemTypeEntry *moduleEntry = typeDb->defaultTypeSystemType();
Q_ASSERT(moduleEntry);
//Extra includes
- s << endl << "// Extra includes" << endl;
+ s << Qt::endl << "// Extra includes\n";
QVector<Include> extraIncludes = moduleEntry->extraIncludes();
for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums))
extraIncludes.append(cppEnum->typeEntry()->extraIncludes());
std::sort(extraIncludes.begin(), extraIncludes.end());
for (const Include &inc : qAsConst(extraIncludes))
s << inc;
- s << endl;
+ s << Qt::endl;
- s << "// Current module's type array." << endl;
- s << "PyTypeObject **" << cppApiVariableName() << " = nullptr;" << endl;
+ s << "// Current module's type array.\n";
+ s << "PyTypeObject **" << cppApiVariableName() << " = nullptr;\n";
- s << "// Current module's PyObject pointer." << endl;
- s << "PyObject *" << pythonModuleObjectName() << " = nullptr;" << endl;
+ s << "// Current module's PyObject pointer.\n";
+ s << "PyObject *" << pythonModuleObjectName() << " = nullptr;\n";
- s << "// Current module's converter array." << endl;
- s << "SbkConverter **" << convertersVariableName() << " = nullptr;" << endl;
+ s << "// Current module's converter array.\n";
+ s << "SbkConverter **" << convertersVariableName() << " = nullptr;\n";
const CodeSnipList snips = moduleEntry->codeSnips();
// module inject-code native/beginning
- if (!snips.isEmpty()) {
+ if (!snips.isEmpty())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode);
- s << endl;
- }
// cleanup staticMetaObject attribute
if (usePySideExtensions()) {
- s << "void cleanTypesAttributes(void) {" << endl;
- s << INDENT << "if (PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03060000)" << endl;
- s << INDENT << " return; // PYSIDE-953: testbinding crashes in Python 3.5 when hasattr touches types!" << endl;
- s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject *pyType = reinterpret_cast<PyObject *>(" << cppApiVariableName() << "[i]);" << endl;
- s << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"staticMetaObject\"));" << endl;
- s << INDENT << "if (pyType && PyObject_HasAttr(pyType, attrName))"<< endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyObject_SetAttr(pyType, attrName, Py_None);" << endl;
- }
- }
- s << INDENT << "}" << endl;
- s << "}" << endl;
+ s << "void cleanTypesAttributes(void) {\n";
+ s << INDENT << "if (PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03060000)\n";
+ s << INDENT << " return; // PYSIDE-953: testbinding crashes in Python 3.5 when hasattr touches types!\n";
+ s << INDENT << "for (int i = 0, imax = SBK_" << moduleName()
+ << "_IDX_COUNT; i < imax; i++) {\n" << indent(INDENT)
+ << INDENT << "PyObject *pyType = reinterpret_cast<PyObject *>(" << cppApiVariableName() << "[i]);\n"
+ << INDENT << "Shiboken::AutoDecRef attrName(Py_BuildValue(\"s\", \"staticMetaObject\"));\n"
+ << INDENT << "if (pyType && PyObject_HasAttr(pyType, attrName))\n" << indent(INDENT)
+ << INDENT << "PyObject_SetAttr(pyType, attrName, Py_None);\n" << outdent(INDENT)
+ << outdent(INDENT) << INDENT << "}\n" << "}\n";
}
s << "// Global functions ";
- s << "------------------------------------------------------------" << endl;
- s << globalFunctionImpl << endl;
+ s << "------------------------------------------------------------\n";
+ s << globalFunctionImpl << Qt::endl;
- s << "static PyMethodDef " << moduleName() << "_methods[] = {" << endl;
+ s << "static PyMethodDef " << moduleName() << "_methods[] = {\n";
s << globalFunctionDecl;
- s << INDENT << "{0} // Sentinel" << endl << "};" << endl << endl;
+ s << INDENT << "{0} // Sentinel\n" << "};\n\n";
s << "// Classes initialization functions ";
- s << "------------------------------------------------------------" << endl;
- s << classInitDecl << endl;
+ s << "------------------------------------------------------------\n";
+ s << classInitDecl << Qt::endl;
if (!globalEnums.isEmpty()) {
QString converterImpl;
QTextStream convImpl(&converterImpl);
s << "// Enum definitions ";
- s << "------------------------------------------------------------" << endl;
+ s << "------------------------------------------------------------\n";
for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) {
if (cppEnum->isAnonymous() || cppEnum->isPrivate())
continue;
writeEnumConverterFunctions(s, cppEnum);
- s << endl;
+ s << Qt::endl;
}
if (!converterImpl.isEmpty()) {
s << "// Enum converters ";
- s << "------------------------------------------------------------" << endl;
- s << "namespace Shiboken" << endl << '{' << endl;
- s << converterImpl << endl;
- s << "} // namespace Shiboken" << endl << endl;
+ s << "------------------------------------------------------------\n";
+ s << "namespace Shiboken\n{\n";
+ s << converterImpl << Qt::endl;
+ s << "} // namespace Shiboken\n\n";
}
+
+ writeFlagsNumberMethodsDefinitions(s, globalEnums);
+ s << '\n';
}
const QStringList &requiredModules = typeDb->requiredTargetImports();
if (!requiredModules.isEmpty())
- s << "// Required modules' type and converter arrays." << endl;
+ s << "// Required modules' type and converter arrays.\n";
for (const QString &requiredModule : requiredModules) {
- s << "PyTypeObject **" << cppApiVariableName(requiredModule) << ';' << endl;
- s << "SbkConverter **" << convertersVariableName(requiredModule) << ';' << endl;
+ s << "PyTypeObject **" << cppApiVariableName(requiredModule) << ";\n";
+ s << "SbkConverter **" << convertersVariableName(requiredModule) << ";\n";
}
- s << endl;
+ s << Qt::endl;
s << "// Module initialization ";
- s << "------------------------------------------------------------" << endl;
+ s << "------------------------------------------------------------\n";
ExtendedConverterData extendedConverters = getExtendedConverters();
if (!extendedConverters.isEmpty()) {
- s << endl << "// Extended Converters." << endl << endl;
+ s << Qt::endl << "// Extended Converters.\n\n";
for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) {
const TypeEntry *externalType = it.key();
- s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl;
+ s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << Qt::endl;
for (const AbstractMetaClass *sourceClass : it.value()) {
AbstractMetaType *sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass);
AbstractMetaType *targetType = buildAbstractMetaTypeFromTypeEntry(externalType);
@@ -5631,135 +6087,134 @@ bool CppGenerator::finishGeneration()
const QVector<const CustomConversion *> &typeConversions = getPrimitiveCustomConversions();
if (!typeConversions.isEmpty()) {
- s << endl << "// Primitive Type converters." << endl << endl;
+ s << Qt::endl << "// Primitive Type converters.\n\n";
for (const CustomConversion *conversion : typeConversions) {
- s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl;
+ s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'.\n";
writeCppToPythonFunction(s, conversion);
writeCustomConverterFunctions(s, conversion);
}
- s << endl;
+ s << Qt::endl;
}
const QVector<const AbstractMetaType *> &containers = instantiatedContainers();
if (!containers.isEmpty()) {
- s << "// Container Type converters." << endl << endl;
+ s << "// Container Type converters.\n\n";
for (const AbstractMetaType *container : containers) {
- s << "// C++ to Python conversion for type '" << container->cppSignature() << "'." << endl;
+ s << "// C++ to Python conversion for type '" << container->cppSignature() << "'.\n";
writeContainerConverterFunctions(s, container);
}
- s << endl;
- }
-
- s << "#if defined _WIN32 || defined __CYGWIN__" << endl;
- s << " #define SBK_EXPORT_MODULE __declspec(dllexport)" << endl;
- s << "#elif __GNUC__ >= 4" << endl;
- s << " #define SBK_EXPORT_MODULE __attribute__ ((visibility(\"default\")))" << endl;
- s << "#else" << endl;
- s << " #define SBK_EXPORT_MODULE" << endl;
- s << "#endif" << endl << endl;
-
- s << "#ifdef IS_PY3K" << endl;
- s << "static struct PyModuleDef moduledef = {" << endl;
- s << " /* m_base */ PyModuleDef_HEAD_INIT," << endl;
- s << " /* m_name */ \"" << moduleName() << "\"," << endl;
- s << " /* m_doc */ nullptr," << endl;
- s << " /* m_size */ -1," << endl;
- s << " /* m_methods */ " << moduleName() << "_methods," << endl;
- s << " /* m_reload */ nullptr," << endl;
- s << " /* m_traverse */ nullptr," << endl;
- s << " /* m_clear */ nullptr," << endl;
- s << " /* m_free */ nullptr" << endl;
- s << "};" << endl << endl;
- s << "#endif" << endl << endl;
+ s << Qt::endl;
+ }
+
+ // Implicit smart pointers conversions
+ const auto smartPointersList = instantiatedSmartPointers();
+ if (!smartPointersList.isEmpty()) {
+ s << "// SmartPointers converters.\n\n";
+ for (const AbstractMetaType *smartPointer : smartPointersList) {
+ s << "// C++ to Python conversion for type '" << smartPointer->cppSignature() << "'.\n";
+ writeSmartPointerConverterFunctions(s, smartPointer);
+ }
+ s << Qt::endl;
+ }
+
+ s << "#ifdef IS_PY3K\n";
+ s << "static struct PyModuleDef moduledef = {\n";
+ s << " /* m_base */ PyModuleDef_HEAD_INIT,\n";
+ s << " /* m_name */ \"" << moduleName() << "\",\n";
+ s << " /* m_doc */ nullptr,\n";
+ s << " /* m_size */ -1,\n";
+ s << " /* m_methods */ " << moduleName() << "_methods,\n";
+ s << " /* m_reload */ nullptr,\n";
+ s << " /* m_traverse */ nullptr,\n";
+ s << " /* m_clear */ nullptr,\n";
+ s << " /* m_free */ nullptr\n";
+ s << "};\n\n";
+ s << "#endif\n\n";
// PYSIDE-510: Create a signatures string for the introspection feature.
- s << "// The signatures string for the global functions." << endl;
- s << "// Multiple signatures have their index \"n:\" in front." << endl;
- s << "static const char *" << moduleName() << "_SignatureStrings[] = {" << endl;
- QString line;
- while (signatureStream.readLineInto(&line))
- s << INDENT << '"' << line << "\"," << endl;
- s << INDENT << NULL_PTR << "}; // Sentinel" << endl << endl;
+ writeSignatureStrings(s, signatureStream, moduleName(), "global functions");
- s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")" << endl;
+ s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")\n";
ErrorCode errorCode(QLatin1String("SBK_MODULE_INIT_ERROR"));
// module inject-code target/beginning
- if (!snips.isEmpty()) {
+ if (!snips.isEmpty())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode);
- s << endl;
- }
for (const QString &requiredModule : requiredModules) {
- s << INDENT << "{" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));" << endl;
- s << INDENT << "if (requiredModule.isNull())" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "return SBK_MODULE_INIT_ERROR;" << endl;
- }
- s << INDENT << cppApiVariableName(requiredModule) << " = Shiboken::Module::getTypes(requiredModule);" << endl;
- s << INDENT << convertersVariableName(requiredModule) << " = Shiboken::Module::getTypeConverters(requiredModule);" << endl;
- }
- s << INDENT << "}" << endl << endl;
+ s << INDENT << "{\n" << indent(INDENT)
+ << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));\n"
+ << INDENT << "if (requiredModule.isNull())\n" << indent(INDENT)
+ << INDENT << "return SBK_MODULE_INIT_ERROR;\n" << outdent(INDENT)
+ << INDENT << cppApiVariableName(requiredModule)
+ << " = Shiboken::Module::getTypes(requiredModule);\n"
+ << INDENT << convertersVariableName(requiredModule)
+ << " = Shiboken::Module::getTypeConverters(requiredModule);\n" << outdent(INDENT)
+ << INDENT << "}\n\n";
}
int maxTypeIndex = getMaxTypeIndex() + instantiatedSmartPointers().size();
if (maxTypeIndex) {
- s << INDENT << "// Create an array of wrapper types for the current module." << endl;
- s << INDENT << "static PyTypeObject *cppApi[SBK_" << moduleName() << "_IDX_COUNT];" << endl;
- s << INDENT << cppApiVariableName() << " = cppApi;" << endl << endl;
+ s << INDENT << "// Create an array of wrapper types for the current module.\n";
+ s << INDENT << "static PyTypeObject *cppApi[SBK_" << moduleName() << "_IDX_COUNT];\n";
+ s << INDENT << cppApiVariableName() << " = cppApi;\n\n";
}
- s << INDENT << "// Create an array of primitive type converters for the current module." << endl;
- s << INDENT << "static SbkConverter *sbkConverters[SBK_" << moduleName() << "_CONVERTERS_IDX_COUNT" << "];" << endl;
- s << INDENT << convertersVariableName() << " = sbkConverters;" << endl << endl;
+ s << INDENT << "// Create an array of primitive type converters for the current module.\n";
+ s << INDENT << "static SbkConverter *sbkConverters[SBK_" << moduleName() << "_CONVERTERS_IDX_COUNT" << "];\n";
+ s << INDENT << convertersVariableName() << " = sbkConverters;\n\n";
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << "PyObject *module = Shiboken::Module::create(\"" << moduleName() << "\", &moduledef);" << endl;
- s << "#else" << endl;
+ s << "#ifdef IS_PY3K\n";
+ s << INDENT << "PyObject *module = Shiboken::Module::create(\"" << moduleName() << "\", &moduledef);\n";
+ s << "#else\n";
s << INDENT << "PyObject *module = Shiboken::Module::create(\"" << moduleName() << "\", ";
- s << moduleName() << "_methods);" << endl;
- s << "#endif" << endl << endl;
+ s << moduleName() << "_methods);\n";
+ s << "#endif\n\n";
- s << INDENT << "// Make module available from global scope" << endl;
- s << INDENT << pythonModuleObjectName() << " = module;" << endl << endl;
+ s << INDENT << "// Make module available from global scope\n";
+ s << INDENT << pythonModuleObjectName() << " = module;\n\n";
- //s << INDENT << "// Initialize converters for primitive types." << endl;
- //s << INDENT << "initConverters();" << endl << endl;
+ //s << INDENT << "// Initialize converters for primitive types.\n";
+ //s << INDENT << "initConverters();\n\n";
- s << INDENT << "// Initialize classes in the type system" << endl;
+ s << INDENT << "// Initialize classes in the type system\n";
s << classPythonDefines;
if (!typeConversions.isEmpty()) {
- s << endl;
+ s << Qt::endl;
for (const CustomConversion *conversion : typeConversions) {
writePrimitiveConverterInitialization(s, conversion);
- s << endl;
+ s << Qt::endl;
}
}
if (!containers.isEmpty()) {
- s << endl;
+ s << Qt::endl;
for (const AbstractMetaType *container : containers) {
writeContainerConverterInitialization(s, container);
- s << endl;
+ s << Qt::endl;
+ }
+ }
+
+ if (!smartPointersList.isEmpty()) {
+ s << Qt::endl;
+ for (const AbstractMetaType *smartPointer : smartPointersList) {
+ writeSmartPointerConverterInitialization(s, smartPointer);
+ s << Qt::endl;
}
}
if (!extendedConverters.isEmpty()) {
- s << endl;
+ s << Qt::endl;
for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) {
writeExtendedConverterInitialization(s, it.key(), it.value());
- s << endl;
+ s << Qt::endl;
}
}
writeEnumsInitialization(s, globalEnums);
- s << INDENT << "// Register primitive types converters." << endl;
+ s << INDENT << "// Register primitive types converters.\n";
const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes();
for (const PrimitiveTypeEntry *pte : primitiveTypeList) {
if (!pte->generateCode() || !pte->isCppPrimitive())
@@ -5768,59 +6223,48 @@ bool CppGenerator::finishGeneration()
if (!referencedType)
continue;
QString converter = converterObject(referencedType);
- QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts);
+ QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts);
while (!cppSignature.isEmpty()) {
QString signature = cppSignature.join(QLatin1String("::"));
- s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");" << endl;
+ s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");\n";
cppSignature.removeFirst();
}
}
- s << endl;
+ s << Qt::endl;
if (maxTypeIndex)
- s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");" << endl;
- s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");" << endl;
+ s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n";
+ s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n";
- s << endl << INDENT << "if (PyErr_Occurred()) {" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyErr_Print();" << endl;
- s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");" << endl;
- }
- s << INDENT << '}' << endl;
+ s << '\n' << INDENT << "if (PyErr_Occurred()) {\n" << indent(INDENT)
+ << INDENT << "PyErr_Print();\n"
+ << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n"
+ << outdent(INDENT) << INDENT << "}\n";
// module inject-code target/end
- if (!snips.isEmpty()) {
+ if (!snips.isEmpty())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode);
- s << endl;
- }
// module inject-code native/end
- if (!snips.isEmpty()) {
+ if (!snips.isEmpty())
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode);
- s << endl;
- }
if (usePySideExtensions()) {
for (AbstractMetaEnum *metaEnum : qAsConst(globalEnums))
if (!metaEnum->isAnonymous()) {
- s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");" << endl;
+ s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");\n";
}
// cleanup staticMetaObject attribute
- s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl << endl;
+ s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);\n\n";
}
// finish the rest of __signature__ initialization.
s << INDENT << "FinishSignatureInitialization(module, " << moduleName()
- << "_SignatureStrings);" << endl;
+ << "_SignatureStrings);\n";
- if (usePySideExtensions()) {
- // initialize the qApp module.
- s << INDENT << "NotifyModuleForQApp(module, qApp);" << endl;
- }
- s << endl;
- s << "SBK_MODULE_INIT_FUNCTION_END" << endl;
+ s << Qt::endl;
+ s << "SBK_MODULE_INIT_FUNCTION_END\n";
return file.done() != FileOut::Failure;
}
@@ -5906,12 +6350,12 @@ void CppGenerator::writeParentChildManagement(QTextStream &s, const AbstractMeta
writeReturnValueHeuristics(s, func);
}
-void CppGenerator::writeReturnValueHeuristics(QTextStream &s, const AbstractMetaFunction *func, const QString &self)
+void CppGenerator::writeReturnValueHeuristics(QTextStream &s, const AbstractMetaFunction *func)
{
AbstractMetaType *type = func->type();
if (!useReturnValueHeuristic()
|| !func->ownerClass()
- || !type
+ || type->isVoid()
|| func->isStatic()
|| func->isConstructor()
|| !func->typeReplaced(0).isEmpty()) {
@@ -5921,126 +6365,136 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream &s, const AbstractMeta
ArgumentOwner argOwner = getArgumentOwner(func, ArgumentOwner::ReturnIndex);
if (argOwner.action == ArgumentOwner::Invalid || argOwner.index != ArgumentOwner::ThisIndex) {
if (isPointerToWrapperType(type))
- s << INDENT << "Shiboken::Object::setParent(self, " << PYTHON_RETURN_VAR << ");" << endl;
+ s << INDENT << "Shiboken::Object::setParent(self, " << PYTHON_RETURN_VAR << ");\n";
}
}
-void CppGenerator::writeHashFunction(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeHashFunction(QTextStream &s, const GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
- s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject *self) {" << endl;
+ const char hashType[] = "Py_hash_t";
+ s << "static " << hashType << ' ' << cpythonBaseName(metaClass)
+ << "_HashFunc(PyObject *self) {\n";
writeCppSelfDefinition(s, context);
- s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '(';
- s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");" << endl;
- s << '}' << endl << endl;
+ s << INDENT << "return " << hashType << '('
+ << metaClass->typeEntry()->hashFunction() << '('
+ << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << "));\n";
+ s<< "}\n\n";
}
-void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context)
+void CppGenerator::writeDefaultSequenceMethods(QTextStream &s, const GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
ErrorCode errorCode(0);
// __len__
- s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject *self)" << endl;
- s << '{' << endl;
+ s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry())
+ << "__len__(PyObject *self)\n{\n";
writeCppSelfDefinition(s, context);
- s << INDENT << "return " << CPP_SELF_VAR << "->size();" << endl;
- s << '}' << endl;
+ s << INDENT << "return " << CPP_SELF_VAR << "->size();\n";
+ s << "}\n";
// __getitem__
- s << "PyObject *" << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject *self, Py_ssize_t _i)" << endl;
- s << '{' << endl;
+ s << "PyObject *" << cpythonBaseName(metaClass->typeEntry())
+ << "__getitem__(PyObject *self, Py_ssize_t _i)\n{\n";
writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("index out of bounds"));
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();" << endl;
- s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
+ QString value;
+ s << INDENT << metaClass->qualifiedCppName() << "::const_iterator _item = "
+ << CPP_SELF_VAR << "->begin();\n"
+ << INDENT << "std::advance(_item, _i);\n";
- const AbstractMetaType *itemType = metaClass->templateBaseClassInstantiations().constFirst();
+ const AbstractMetaTypeList &instantiations = metaClass->templateBaseClassInstantiations();
+ if (instantiations.isEmpty()) {
+ qFatal("shiboken: %s: Internal error, no instantiations of \"%s\" were found.",
+ __FUNCTION__, qPrintable(metaClass->qualifiedCppName()));
+ }
+ const AbstractMetaType *itemType = instantiations.constFirst();
s << INDENT << "return ";
writeToPythonConversion(s, itemType, metaClass, QLatin1String("*_item"));
- s << ';' << endl;
- s << '}' << endl;
+ s << ";\n";
+ s << "}\n";
// __setitem__
ErrorCode errorCode2(-1);
- s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject *self, Py_ssize_t _i, PyObject *pyArg)" << endl;
- s << '{' << endl;
+ s << "int " << cpythonBaseName(metaClass->typeEntry())
+ << "__setitem__(PyObject *self, Py_ssize_t _i, PyObject *pyArg)\n{\n";
writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("list assignment index out of range"));
- s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
+ s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ";\n";
s << INDENT << "if (!";
writeTypeCheck(s, itemType, QLatin1String("pyArg"), isNumber(itemType->typeEntry()));
- s << ") {" << endl;
+ s << ") {\n";
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_TypeError, \"attributed value with wrong type, '";
- s << itemType->name() << "' or other convertible type expected\");" << endl;
- s << INDENT << "return -1;" << endl;
+ s << itemType->name() << "' or other convertible type expected\");\n";
+ s << INDENT << "return -1;\n";
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
writeArgumentConversion(s, itemType, QLatin1String("cppValue"), QLatin1String("pyArg"), metaClass);
- s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " << CPP_SELF_VAR << "->begin();" << endl;
- s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl;
- s << INDENT << "*_item = cppValue;" << endl;
- s << INDENT << "return {};" << endl;
- s << '}' << endl;
+ s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = "
+ << CPP_SELF_VAR << "->begin();\n"
+ << INDENT << "std::advance(_item, _i);\n"
+ << INDENT << "*_item = cppValue;\n";
+
+ s << INDENT << "return {};\n";
+ s << "}\n";
}
void CppGenerator::writeIndexError(QTextStream &s, const QString &errorMsg)
{
- s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " << CPP_SELF_VAR << "->size()) {" << endl;
+ s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " << CPP_SELF_VAR << "->size()) {\n";
{
Indentation indent(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");" << endl;
- s << INDENT << returnStatement(m_currentErrorCode) << endl;
+ s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");\n";
+ s << INDENT << returnStatement(m_currentErrorCode) << Qt::endl;
}
- s << INDENT << '}' << endl;
+ s << INDENT << "}\n";
}
QString CppGenerator::writeReprFunction(QTextStream &s,
- GeneratorContext &context,
+ const GeneratorContext &context,
uint indirections)
{
const AbstractMetaClass *metaClass = context.metaClass();
QString funcName = cpythonBaseName(metaClass) + QLatin1String("__repr__");
- s << "extern \"C\"" << endl;
- s << '{' << endl;
- s << "static PyObject *" << funcName << "(PyObject *self)" << endl;
- s << '{' << endl;
+ s << "extern \"C\"\n{\n";
+ s << "static PyObject *" << funcName << "(PyObject *self)\n{\n";
writeCppSelfDefinition(s, context);
- s << INDENT << "QBuffer buffer;" << endl;
- s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl;
- s << INDENT << "QDebug dbg(&buffer);" << endl;
+ s << INDENT << "QBuffer buffer;\n";
+ s << INDENT << "buffer.open(QBuffer::ReadWrite);\n";
+ s << INDENT << "QDebug dbg(&buffer);\n";
s << INDENT << "dbg << ";
if (metaClass->typeEntry()->isValue() || indirections == 0)
s << '*';
- s << CPP_SELF_VAR << ';' << endl;
- s << INDENT << "buffer.close();" << endl;
- s << INDENT << "QByteArray str = buffer.data();" << endl;
- s << INDENT << "int idx = str.indexOf('(');" << endl;
- s << INDENT << "if (idx >= 0)" << endl;
+ s << CPP_SELF_VAR << ";\n";
+ s << INDENT << "buffer.close();\n";
+ s << INDENT << "QByteArray str = buffer.data();\n";
+ s << INDENT << "int idx = str.indexOf('(');\n";
+ s << INDENT << "if (idx >= 0)\n";
{
Indentation indent(INDENT);
- s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl;
+ s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);\n";
}
- s << INDENT << "str = str.trimmed();" << endl;
- s << INDENT << "PyObject *mod = PyDict_GetItem(Py_TYPE(self)->tp_dict, Shiboken::PyMagicName::module());" << endl;
+ s << INDENT << "str = str.trimmed();\n";
+ s << INDENT << "PyObject *mod = PyDict_GetItem(Py_TYPE(self)->tp_dict, Shiboken::PyMagicName::module());\n";
// PYSIDE-595: The introduction of heap types has the side effect that the module name
// is always prepended to the type name. Therefore the strchr check:
- s << INDENT << "if (mod && !strchr(str, '.'))" << endl;
+ s << INDENT << "if (mod && !strchr(str, '.'))\n";
{
Indentation indent(INDENT);
- s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);" << endl;
+ s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);\n";
}
- s << INDENT << "else" << endl;
+ s << INDENT << "else\n";
{
Indentation indent(INDENT);
- s << INDENT << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);" << endl;
+ s << INDENT << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);\n";
}
- s << '}' << endl;
- s << "} // extern C" << endl << endl;;
+ s << "}\n";
+ s << "} // extern C\n\n";
return funcName;
}