diff options
Diffstat (limited to 'sources')
6 files changed, 86 insertions, 86 deletions
diff --git a/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py b/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py index 77efbcb5f..95bf0615f 100644 --- a/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py +++ b/sources/pyside6/tests/pysidetest/new_inherited_functions_test.py @@ -79,21 +79,14 @@ new_functions += """ PySide6.QtWidgets.QGestureEvent([]).setAccepted(bool) # PySide6.QtWidgets.QGraphicsView().render(qPaintDevice,qPoint,qRegion,renderFlags) # QPaintDevice: NotImplementedError PySide6.QtWidgets.QGridLayout().addWidget(qWidget) - PySide6.QtWidgets.QHeaderView(orientation).initStyleOption(qStyleOptionFrame) PySide6.QtWidgets.QInputDialog().open() PySide6.QtWidgets.QLineEdit().addAction(qAction) - PySide6.QtWidgets.QListWidget().closePersistentEditor(qModelIndex) - PySide6.QtWidgets.QListWidget().openPersistentEditor(qModelIndex) PySide6.QtWidgets.QMessageBox().open() PySide6.QtWidgets.QPlainTextEdit().find(findStr) PySide6.QtWidgets.QProgressDialog().open() PySide6.QtWidgets.QStackedLayout().widget() # PySide6.QtWidgets.QStylePainter().begin(qPaintDevice) # QPaintDevice: NotImplementedError - PySide6.QtWidgets.QTableWidget().closePersistentEditor(qModelIndex) - PySide6.QtWidgets.QTableWidget().openPersistentEditor(qModelIndex) PySide6.QtWidgets.QTextEdit().find(findStr) - PySide6.QtWidgets.QTreeWidget().closePersistentEditor(qModelIndex) - PySide6.QtWidgets.QTreeWidget().openPersistentEditor(qModelIndex) PySide6.QtWidgets.QWidget.find(quintptr) """ if "PySide6.QtWidgets" in sys.modules else "" diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index c2d9bfcf6..91da71cb9 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -1087,6 +1087,14 @@ bool AbstractMetaClass::isUsingMember(const AbstractMetaClass *c, return d->isUsingMember(c, memberName, minimumAccess); } +bool AbstractMetaClass::hasUsingMemberFor(const QString &memberName) const +{ + return std::any_of(d->m_usingMembers.cbegin(), d->m_usingMembers.cend(), + [&memberName](const UsingMember &um) { + return um.memberName == memberName; + }); +} + /* Goes through the list of functions and returns a list of all functions matching all of the criteria in \a query. */ diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index 39d5a4a8e..f08ed2039 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -146,6 +146,7 @@ public: void addUsingMember(const UsingMember &um); bool isUsingMember(const AbstractMetaClass *c, const QString &memberName, Access minimumAccess) const; + bool hasUsingMemberFor(const QString &memberName) const; AbstractMetaFunctionCList queryFunctionsByName(const QString &name) const; static bool queryFunction(const AbstractMetaFunction *f, FunctionQueryOptions query); diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 557324ceb..941603ea9 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -534,32 +534,7 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon << "extern \"C\" {\n"; const auto &functionGroups = getFunctionGroups(metaClass); for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - AbstractMetaFunctionCList overloads; - QSet<QString> seenSignatures; - bool staticEncountered = false; - for (const auto &func : it.value()) { - if (func->ownerClass() == func->implementingClass() - && func->generateBinding()) { - // 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 (func->isStatic()) - staticEncountered = true; - } - } - // PYSIDE-886: If the method does not have any static overloads declared - // in the class in question, remove all inherited static methods as setting - // METH_STATIC in that case can cause crashes for the instance methods. - // Manifested as crash when calling QPlainTextEdit::find() (clash with - // static QWidget::find(WId)). - if (!staticEncountered) { - for (qsizetype i = overloads.size() - 1; i >= 0; --i) { - if (overloads.at(i)->isStatic()) - overloads.removeAt(i); - } - } - + const AbstractMetaFunctionCList &overloads = it.value(); if (overloads.isEmpty()) continue; diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index c443b0208..6672fb64c 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -33,6 +33,8 @@ #include <abstractmetafield.h> #include <abstractmetafunction.h> #include <abstractmetalang.h> +#include <abstractmetalang_helpers.h> +#include <usingmember.h> #include <exception.h> #include <messages.h> #include <modifications.h> @@ -1840,7 +1842,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s, bool isProtected = func->isProtected(); auto owner = func->ownerClass(); if (!isProtected && func->isUserAdded() && owner != nullptr) { - const auto &funcs = getMethodOverloads(owner, func->name()); + const auto &funcs = getFunctionGroups(owner).value(func->name()); isProtected = std::any_of(funcs.cbegin(), funcs.cend(), [](const AbstractMetaFunctionCPtr &f) { return f->isProtected(); @@ -2288,10 +2290,12 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const FunctionGroups results; for (const auto &func : lst) { - if (isGroupable(func)) { + if (isGroupable(func) + && func->ownerClass() == func->implementingClass() + && func->generateBinding()) { auto it = results.find(func->name()); if (it == results.end()) { - results.insert(func->name(), AbstractMetaFunctionCList(1, func)); + it = results.insert(func->name(), AbstractMetaFunctionCList(1, func)); } else { // If there are virtuals methods in the mix (PYSIDE-570, // QFileSystemModel::index(QString,int) and @@ -2303,60 +2307,85 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const else it.value().append(func); } + getInheritedOverloads(scope, &it.value()); } } return results; } -AbstractMetaFunctionCList - ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunctionCPtr &func, QSet<QString> *seen) -{ - AbstractMetaFunctionCList results; - AbstractMetaClass *basis; - if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) { - for (; basis; basis = basis->baseClass()) { - const auto inFunctions = basis->findFunctions(func->name()); - for (const auto &inFunc : inFunctions) { - if (inFunc->generateBinding() - && !seen->contains(inFunc->minimalSignature())) { - seen->insert(inFunc->minimalSignature()); - AbstractMetaFunction *newFunc = inFunc->copy(); - newFunc->setImplementingClass(func->implementingClass()); - results << AbstractMetaFunctionCPtr(newFunc); - } - } - } - } - return results; -} - -AbstractMetaFunctionCList - ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunctionCPtr &func, - QSet<QString> *seen) +static bool hidesBaseClassFunctions(const AbstractMetaFunctionCPtr &f) { - AbstractMetaFunctionCList results; - seen->insert(func->minimalSignature()); - results << func << getInheritedOverloads(func, seen); - return results; + return 0 == (f->attributes() + & (AbstractMetaFunction::OverriddenCppMethod | AbstractMetaFunction::FinalCppMethod)); } -AbstractMetaFunctionCList ShibokenGenerator::getMethodOverloads(const AbstractMetaClass *scope, - const QString &functionName) const +void ShibokenGenerator::getInheritedOverloads(const AbstractMetaClass *scope, + AbstractMetaFunctionCList *overloads) { - Q_ASSERT(scope); - const auto &lst = scope->functions(); + if (overloads->isEmpty() || scope->isNamespace() || scope->baseClasses().isEmpty()) + return; + + // PYSIDE-331: look also into base classes. Check for any non-overriding + // function hiding the base class functions. + const bool hideBaseClassFunctions = + std::any_of(overloads->cbegin(), overloads->cend(), hidesBaseClassFunctions); + + const QString &functionName = overloads->constFirst()->name(); + const bool hasUsingDeclarations = scope->hasUsingMemberFor(functionName); + if (hideBaseClassFunctions && !hasUsingDeclarations) + return; // No base function is visible - AbstractMetaFunctionCList results; + // Collect base candidates by name and signature + bool staticEncountered = false; QSet<QString> seenSignatures; - for (const auto &func : qAsConst(lst)) { - if (func->name() != functionName) - continue; - if (isGroupable(func)) { - // PYSIDE-331: look also into base classes. - results << getFunctionAndInheritedOverloads(func, &seenSignatures); + for (const auto &func : *overloads) { + seenSignatures.insert(func->minimalSignature()); + staticEncountered |= func->isStatic(); + } + + AbstractMetaFunctionCList baseCandidates; + + auto basePredicate = [&functionName, &seenSignatures, &baseCandidates](const AbstractMetaClass *b) { + for (const auto &f : b->functions()) { + if (f->generateBinding() && f->name() == functionName) { + const QString signature = f->minimalSignature(); + if (!seenSignatures.contains(signature)) { + seenSignatures.insert(signature); + baseCandidates.append(f); + } + } } + return false; // Keep going + }; + + for (const auto *baseClass : scope->baseClasses()) + recurseClassHierarchy(baseClass, basePredicate); + + // Remove the ones that are not made visible with using declarations + if (hideBaseClassFunctions && hasUsingDeclarations) { + const auto pred = [scope](const AbstractMetaFunctionCPtr &f) { + return !scope->isUsingMember(f->ownerClass(), f->name(), f->access()); + }; + auto end = std::remove_if(baseCandidates.begin(), baseCandidates.end(), pred); + baseCandidates.erase(end, baseCandidates.end()); + } + + // PYSIDE-886: If the method does not have any static overloads declared + // in the class in question, remove all inherited static methods as setting + // METH_STATIC in that case can cause crashes for the instance methods. + // Manifested as crash when calling QPlainTextEdit::find() (clash with + // static QWidget::find(WId)). + if (!staticEncountered) { + auto end = std::remove_if(baseCandidates.begin(), baseCandidates.end(), + [](const AbstractMetaFunctionCPtr &f) { return f->isStatic(); }); + baseCandidates.erase(end, baseCandidates.end()); + } + + for (const auto &baseCandidate : baseCandidates) { + AbstractMetaFunction *newFunc = baseCandidate->copy(); + newFunc->setImplementingClass(scope); + overloads->append(AbstractMetaFunctionCPtr(newFunc)); } - return results; } Generator::OptionDescriptions ShibokenGenerator::options() const diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h index fd492842e..ad80e14a3 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.h +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h @@ -417,16 +417,10 @@ private: * \param func the metafunction to be searched in subclasses. * \param seen the function's minimal signatures already seen. */ - static AbstractMetaFunctionCList getInheritedOverloads(const AbstractMetaFunctionCPtr & func, - QSet<QString> *seen); + static void getInheritedOverloads(const AbstractMetaClass *scope, + AbstractMetaFunctionCList *overloads); + - /** - * Returns all overloads for a function named \p functionName. - * \param scope scope used to search for overloads. - * \param functionName the function name. - */ - AbstractMetaFunctionCList getMethodOverloads(const AbstractMetaClass *scope, - const QString &functionName) const; /** * Write a function argument in the C++ in the text stream \p s. * This function just call \code s << argumentString(); \endcode |