aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2017-04-06 00:37:36 +0200
committerChristian Tismer <tismer@stackless.com>2017-04-13 08:24:50 +0000
commit47676b56243f8bee39acd1658e1df2920cc23e42 (patch)
treedc153e2fe5225c1e2951a167a93ccb262dafdfd5
parent20cc149d52d13721e9465c3c8a3fbc523b328b46 (diff)
Fix Inheritance of PySide
This patch is the third stab at fixing the inheritance of PySide. The problem is now solved. Inheritance was already correct when the functions were disjoint. But as soon as a function existed in both a class and a sub-class, only the class has won, and the sub-class was ignored. This patch fixes that problem. There are 49 new functions, and of course there is QApplication.palette() without an argument. Function ‘searchForEnumScope’ was now corrected, so that the work-around no longer was needed. I had to extend its search. It turned out that the same fix for inheritance was also needed for a correct listing of the allowed function signatures. I finally factored out a new function that is used twice. Exhaustive tests can be found in PySide with the same name. Task-number: PYSIDE-331 Change-Id: If3d7d94f6ed351b5de03e26c9e3e65cf4a5f8ed7 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--generator/shiboken2/cppgenerator.cpp18
-rw-r--r--generator/shiboken2/shibokengenerator.cpp51
-rw-r--r--generator/shiboken2/shibokengenerator.h21
3 files changed, 74 insertions, 16 deletions
diff --git a/generator/shiboken2/cppgenerator.cpp b/generator/shiboken2/cppgenerator.cpp
index f5bcdce..49d2161 100644
--- a/generator/shiboken2/cppgenerator.cpp
+++ b/generator/shiboken2/cppgenerator.cpp
@@ -352,6 +352,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass);
for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
+ QSet<QString> seenSignatures;
foreach (AbstractMetaFunction* func, it.value()) {
if (!func->isAssignmentOperator()
&& !func->usesRValueReferences()
@@ -359,8 +360,12 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
&& !func->isModifiedRemoved()
&& (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction)
&& func->ownerClass() == func->implementingClass()
- && (func->name() != QLatin1String("qt_metacall")))
- overloads.append(func);
+ && (func->name() != QLatin1String("qt_metacall"))) {
+ // PYSIDE-331: Inheritance works correctly when there are disjoint functions.
+ // But when a function is both in a class and inherited in a subclass,
+ // then we need to search through all subclasses and collect the new signatures.
+ overloads << getFunctionAndInheritedOverloads(func, &seenSignatures);
+ }
}
if (overloads.isEmpty())
@@ -3114,6 +3119,9 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
if (func->isStatic()) {
mc << "::" << methodCallClassName << "::";
} else {
+ const QString selfVarCast = func->ownerClass() == func->implementingClass()
+ ? QLatin1String(CPP_SELF_VAR)
+ : QLatin1String("reinterpret_cast<") + methodCallClassName + QLatin1String(" *>(" CPP_SELF_VAR ")");
if (func->isConstant()) {
if (avoidProtectedHack()) {
mc << "const_cast<const ::";
@@ -3121,13 +3129,13 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f
mc << wrapperName(func->ownerClass());
else
mc << methodCallClassName;
- mc << "*>(" CPP_SELF_VAR ")->";
+ mc << "*>(" << selfVarCast << ")->";
} else {
mc << "const_cast<const ::" << methodCallClassName;
- mc << "*>(" CPP_SELF_VAR ")->";
+ mc << "*>(" << selfVarCast << ")->";
}
} else {
- mc << CPP_SELF_VAR "->";
+ mc << selfVarCast << "->";
}
}
diff --git a/generator/shiboken2/shibokengenerator.cpp b/generator/shiboken2/shibokengenerator.cpp
index be39143..dadc46e 100644
--- a/generator/shiboken2/shibokengenerator.cpp
+++ b/generator/shiboken2/shibokengenerator.cpp
@@ -346,8 +346,10 @@ QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func)
{
QString result;
- if (func->ownerClass()) {
- result = cpythonBaseName(func->ownerClass()->typeEntry());
+ // PYSIDE-331: For inherited functions, we need to find the same labels.
+ // Therefore we use the implementing class.
+ if (func->implementingClass()) {
+ result = cpythonBaseName(func->implementingClass()->typeEntry());
if (func->isConstructor()) {
result += QLatin1String("_Init");
} else {
@@ -417,8 +419,11 @@ static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QStr
return metaClass->qualifiedCppName();
}
}
-
- return searchForEnumScope(metaClass->enclosingClass(), enumValueName);
+ // PYSIDE-331: We need to also search the base classes.
+ QString ret = searchForEnumScope(metaClass->enclosingClass(), enumValueName);
+ if (ret.isEmpty())
+ ret = searchForEnumScope(metaClass->baseClass(), enumValueName);
+ return ret;
}
/*
@@ -763,12 +768,12 @@ QString ShibokenGenerator::converterObject(const TypeEntry* type)
return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
if (isWrapperType(type) || type->isEnum() || type->isFlags())
return QString::fromLatin1("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type));
-
+
if (type->isArray()) {
qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName();
return QString::null;
}
-
+
/* the typedef'd primitive types case */
const PrimitiveTypeEntry* pte = dynamic_cast<const PrimitiveTypeEntry*>(type);
if (!pte) {
@@ -2330,19 +2335,47 @@ QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(c
return results;
}
+AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen)
+{
+ AbstractMetaFunctionList results;
+ AbstractMetaClass* basis;
+ if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) {
+ for (; basis; basis = basis->baseClass()) {
+ const AbstractMetaFunction* inFunc = basis->findFunction(func->name());
+ if (inFunc && !seen->contains(inFunc->minimalSignature())) {
+ seen->insert(inFunc->minimalSignature());
+ AbstractMetaFunction* newFunc = inFunc->copy();
+ newFunc->setImplementingClass(func->implementingClass());
+ results << newFunc;
+ }
+ }
+ }
+ return results;
+}
+
+AbstractMetaFunctionList ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen)
+{
+ AbstractMetaFunctionList results;
+ seen->insert(func->minimalSignature());
+ results << const_cast<AbstractMetaFunction *>(func) << getInheritedOverloads(func, seen);
+ return results;
+}
+
AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName)
{
AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
AbstractMetaFunctionList results;
+ QSet<QString> seenSignatures;
foreach (AbstractMetaFunction* func, lst) {
if (func->name() != functionName)
continue;
- if (isGroupable(func))
- results << func;
+ if (isGroupable(func)) {
+ // PYSIDE-331: look also into base classes.
+ results << getFunctionAndInheritedOverloads(func, &seenSignatures);
+ }
}
return results;
-
}
QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction)
diff --git a/generator/shiboken2/shibokengenerator.h b/generator/shiboken2/shibokengenerator.h
index 327ca12..2a75a21 100644
--- a/generator/shiboken2/shibokengenerator.h
+++ b/generator/shiboken2/shibokengenerator.h
@@ -78,10 +78,27 @@ public:
/**
* Returns a map with all functions grouped, the function name is used as key.
- * Example ofg return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
- * \param scope Where to search for functions, null means all global functions.
+ * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
+ * \param scope Where to search for functions, null means all global functions.
*/
QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0);
+
+ /**
+ * Returns all different inherited overloads of func.
+ * The function can be called multiple times without duplication.
+ * \param func the metafunction to be searched in subclasses.
+ * \param seen the function's minimal signatures already seen.
+ */
+ AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen);
+
+ /**
+ * Returns all different inherited overloads of func, and includes func as well.
+ * The function can be called multiple times without duplication.
+ * \param func the metafunction to be searched in subclasses.
+ * \param seen the function's minimal signatures already seen.
+ */
+ AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen);
+
/**
* Returns all overloads for a function named \p functionName.
* \param scope scope used to search for overloads.