aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/generator
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-24 11:10:24 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-28 11:19:29 +0200
commitcb073f6eee9e21b62d7c14e0357beb6cecf33e31 (patch)
tree36a32fae9cf3f9c8d505a8dbaf31b228b08844f9 /sources/shiboken2/generator
parent5a7429cc895824a4eafd27e1a5c95b40bba86bdf (diff)
shiboken2: Generate properties as fields
- Add an XML attribute specifying whether code is to be generated to the XML properties. - Split the generator functions for field setters and getters apart so that they can be used for generating property setters and getters. - Generate code for all properties from XML when the PySide extension is not used, otherwise only for those with the attribute set. Task-number: PYSIDE-1019 Change-Id: Iab2ba38b90038edc667a233c23c7113fdc6fb438 Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken2/generator')
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp130
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h11
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp29
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h20
4 files changed, 162 insertions, 28 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 32b9cf24f..6d9884d39 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -317,6 +317,13 @@ static QString buildPropertyString(QPropertySpec *spec)
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
@@ -590,8 +597,10 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo
// PYSIDE-1019: Write a compressed list of all properties `name:getter[:setter]`.
// Default values are suppressed.
QStringList sorter;
- for (const auto spec : metaClass->propertySpecs())
- sorter.append(buildPropertyString(spec));
+ for (const auto spec : metaClass->propertySpecs()) {
+ if (!spec->generateGetSetDef())
+ sorter.append(buildPropertyString(spec));
+ }
sorter.sort();
s << '\n';
@@ -689,19 +698,34 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo
s << Qt::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 << "},\n";
+ 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\n";
s << "};\n\n";
@@ -3976,6 +4000,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;
}
@@ -4416,13 +4447,18 @@ void CppGenerator::writeCopyFunction(QTextStream &s, const GeneratorContext &con
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,
const GeneratorContext &context)
{
ErrorCode errorCode(QString::fromLatin1(NULL_PTR));
- s << "static PyObject *" << cpythonGetterFunctionName(metaField) << "(PyObject *self, void *)\n";
- s << "{\n";
+ writeGetterFunctionStart(s, cpythonGetterFunctionName(metaField));
writeCppSelfDefinition(s, context);
@@ -4503,12 +4539,35 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
s << "}\n";
}
-void CppGenerator::writeSetterFunction(QTextStream &s,
- const AbstractMetaField *metaField,
+// 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 *)\n";
+ writeGetterFunctionStart(s, cpythonGetterFunctionName(property, context.metaClass()));
+ writeCppSelfDefinition(s, context);
+ 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 << "Py_XDECREF(pyResult);\n"
+ << INDENT << " return {};\n";
+ }
+ s << INDENT << "}\n"
+ << INDENT << "return pyResult;\n}\n\n";
+}
+
+// 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);
@@ -4517,24 +4576,33 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'";
- s << metaField->name() << "' may not be deleted\");\n";
+ s << name << "' may not be deleted\");\n";
s << INDENT << "return -1;\n";
}
s << INDENT << "}\n";
- AbstractMetaType *fieldType = metaField->type();
-
s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};\n";
s << INDENT << "if (!";
- writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry()));
+ writeTypeCheck(s, type, QLatin1String("pyIn"), isNumber(type->typeEntry()));
s << ") {\n";
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '";
- s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");\n";
+ s << name << "', '" << type->name() << "' or convertible type expected\");\n";
s << INDENT << "return -1;\n";
}
s << 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;
@@ -4568,6 +4636,26 @@ void CppGenerator::writeSetterFunction(QTextStream &s,
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, const GeneratorContext &context)
{
const AbstractMetaClass *metaClass = context.metaClass();
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h
index 1cc6c1ca0..8c56dd758 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.h
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h
@@ -290,9 +290,20 @@ private:
void writeGetterFunction(QTextStream &s,
const AbstractMetaField *metaField,
const GeneratorContext &context);
+ void writeGetterFunction(QTextStream &s,
+ const QPropertySpec *property,
+ const GeneratorContext &context);
+ void writeSetterFunctionPreamble(QTextStream &s,
+ const QString &name,
+ const QString &funcName,
+ const AbstractMetaType *type,
+ const GeneratorContext &context);
void writeSetterFunction(QTextStream &s,
const AbstractMetaField *metaField,
const GeneratorContext &context);
+ void writeSetterFunction(QTextStream &s,
+ const QPropertySpec *property,
+ const GeneratorContext &context);
void writeRichCompareFunction(QTextStream &s, const GeneratorContext &context);
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index ff1478d58..df8bf392a 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -31,6 +31,7 @@
#include <abstractmetalang.h>
#include <messages.h>
#include "overloaddata.h"
+#include "propertyspec.h"
#include <reporthandler.h>
#include <typedatabase.h>
#include <abstractmetabuilder.h>
@@ -452,14 +453,38 @@ QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass *
return cpythonBaseName(metaClass) + QLatin1String("_getattro");
}
+QString ShibokenGenerator::cpythonGetterFunctionName(const QString &name,
+ const AbstractMetaClass *enclosingClass)
+{
+ return cpythonBaseName(enclosingClass) + QStringLiteral("_get_") + name;
+}
+
+QString ShibokenGenerator::cpythonSetterFunctionName(const QString &name,
+ const AbstractMetaClass *enclosingClass)
+{
+ return cpythonBaseName(enclosingClass) + QStringLiteral("_set_") + name;
+}
+
QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField *metaField)
{
- return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name());
+ return cpythonGetterFunctionName(metaField->name(), metaField->enclosingClass());
}
QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField *metaField)
{
- return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name());
+ return cpythonSetterFunctionName(metaField->name(), metaField->enclosingClass());
+}
+
+QString ShibokenGenerator::cpythonGetterFunctionName(const QPropertySpec *property,
+ const AbstractMetaClass *metaClass)
+{
+ return cpythonGetterFunctionName(property->name(), metaClass);
+}
+
+QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec *property,
+ const AbstractMetaClass *metaClass)
+{
+ return cpythonSetterFunctionName(property->name(), metaClass);
}
static QString cpythonEnumFlagsName(const QString &moduleName,
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
index da0c16851..83e7cf5b9 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -53,6 +53,7 @@ extern const char *END_ALLOW_THREADS;
class DocParser;
class CodeSnip;
+class QPropertySpec;
class OverloadData;
struct GeneratorClassInfoCacheEntry;
@@ -308,9 +309,9 @@ protected:
static QString cpythonBaseName(const AbstractMetaClass *metaClass);
static QString cpythonBaseName(const TypeEntry *type);
- QString cpythonBaseName(const AbstractMetaType *type);
- QString cpythonTypeName(const AbstractMetaClass *metaClass);
- QString cpythonTypeName(const TypeEntry *type);
+ static QString cpythonBaseName(const AbstractMetaType *type);
+ static QString cpythonTypeName(const AbstractMetaClass *metaClass);
+ static QString cpythonTypeName(const TypeEntry *type);
QString cpythonTypeNameExt(const TypeEntry *type) const;
QString cpythonTypeNameExt(const AbstractMetaType *type) const;
QString cpythonCheckFunction(const TypeEntry *type, bool genericNumberType = false);
@@ -341,8 +342,12 @@ protected:
QString cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass);
static QString cpythonGetattroFunctionName(const AbstractMetaClass *metaClass);
static QString cpythonSetattroFunctionName(const AbstractMetaClass *metaClass);
- QString cpythonGetterFunctionName(const AbstractMetaField *metaField);
- QString cpythonSetterFunctionName(const AbstractMetaField *metaField);
+ static QString cpythonGetterFunctionName(const AbstractMetaField *metaField);
+ static QString cpythonSetterFunctionName(const AbstractMetaField *metaField);
+ static QString cpythonGetterFunctionName(const QPropertySpec *property,
+ const AbstractMetaClass *metaClass);
+ static QString cpythonSetterFunctionName(const QPropertySpec *property,
+ const AbstractMetaClass *metaClass);
QString cpythonWrapperCPtr(const AbstractMetaClass *metaClass,
const QString &argName = QLatin1String("self")) const;
QString cpythonWrapperCPtr(const AbstractMetaType *metaType, const QString &argName) const;
@@ -461,6 +466,11 @@ protected:
static QStringList m_knownPythonTypes;
private:
+ static QString cpythonGetterFunctionName(const QString &name,
+ const AbstractMetaClass *enclosingClass);
+ static QString cpythonSetterFunctionName(const QString &name,
+ const AbstractMetaClass *enclosingClass);
+
static const GeneratorClassInfoCacheEntry &getGeneratorClassInfo(const AbstractMetaClass *scope);
static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClass *scope);
static bool classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass);