diff options
3 files changed, 89 insertions, 30 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 29220c739..67f8f1a7b 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -453,8 +453,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << endl << "// Target ---------------------------------------------------------" << endl << endl; s << "extern \"C\" {" << endl; - const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + const auto &functionGroups = getFunctionGroups(metaClass); + for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; QSet<QString> seenSignatures; bool staticEncountered = false; @@ -5404,8 +5404,8 @@ bool CppGenerator::finishGeneration() Indentation indent(INDENT); - const FunctionGroupMap &functionGroups = getFunctionGroups(); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + const auto functionGroups = getGlobalFunctionGroups(); + for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; for (AbstractMetaFunction *func : it.value()) { if (!func->isModifiedRemoved()) { @@ -5824,7 +5824,10 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta const int numArgs = func->arguments().count(); bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy; - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this)); + const auto &groups = func->implementingClass() + ? getFunctionGroups(func->implementingClass()) + : getGlobalFunctionGroups(); + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(groups[func->name()], this)); ArgumentOwner argOwner = getArgumentOwner(func, argIndex); ArgumentOwner::Action action = argOwner.action; diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 002ab8cfb..12efb68c3 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -118,6 +118,16 @@ static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum, return resolveScopePrefix(parts, value); } +struct GeneratorClassInfoCacheEntry +{ + ShibokenGenerator::FunctionGroups functionGroups; + bool needsGetattroFunction = false; +}; + +using GeneratorClassInfoCache = QHash<const AbstractMetaClass *, GeneratorClassInfoCacheEntry>; + +Q_GLOBAL_STATIC(GeneratorClassInfoCache, generatorClassInfoCache) + ShibokenGenerator::ShibokenGenerator() { if (m_pythonPrimitiveTypeName.isEmpty()) @@ -1739,7 +1749,10 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, argsRemoved++; } - OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this); + const auto &groups = func->implementingClass() + ? getFunctionGroups(func->implementingClass()) + : getGlobalFunctionGroups(); + OverloadData od(groups[func->name()], this); bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od); // Replace %PYARG_# variables. @@ -2174,17 +2187,19 @@ bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass return hasMultipleInheritanceInAncestry(metaClass->baseClass()); } -typedef QMap<QString, AbstractMetaFunctionList> FunctionGroupMap; -typedef FunctionGroupMap::const_iterator FunctionGroupMapIt; - bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* metaClass) { + return getGeneratorClassInfo(metaClass).needsGetattroFunction; +} + +bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass* metaClass) +{ if (!metaClass) return false; if (metaClass->typeEntry()->isSmartPointer()) return true; - const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { + const auto &functionGroup = getFunctionGroups(metaClass); + for (auto it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() @@ -2212,8 +2227,8 @@ AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStatic { AbstractMetaFunctionList methods; if (metaClass) { - const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + const auto &functionGroups = getFunctionGroups(metaClass); + for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() @@ -2358,23 +2373,56 @@ static bool isGroupable(const AbstractMetaFunction* func) return true; } -QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(const AbstractMetaClass* scope) +ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const { - AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); + const AbstractMetaFunctionList &lst = globalFunctions(); + FunctionGroups results; + for (AbstractMetaFunction *func : lst) { + if (isGroupable(func)) + results[func->name()].append(func); + } + return results; +} - QMap<QString, AbstractMetaFunctionList> results; - for (AbstractMetaFunction *func : qAsConst(lst)) { +const GeneratorClassInfoCacheEntry &ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClass *scope) +{ + auto cache = generatorClassInfoCache(); + auto it = cache->find(scope); + if (it == cache->end()) { + it = cache->insert(scope, {}); + it.value().functionGroups = getFunctionGroupsImpl(scope); + it.value().needsGetattroFunction = classNeedsGetattroFunctionImpl(scope); + } + return it.value(); +} + +ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const AbstractMetaClass *scope) +{ + Q_ASSERT(scope); + return getGeneratorClassInfo(scope).functionGroups; +} + +ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope) +{ + const AbstractMetaFunctionList &lst = scope->functions(); + + FunctionGroups results; + for (AbstractMetaFunction *func : lst) { if (isGroupable(func)) { - AbstractMetaFunctionList &list = results[func->name()]; - // If there are virtuals methods in the mix (PYSIDE-570, - // QFileSystemModel::index(QString,int) and - // QFileSystemModel::index(int,int,QModelIndex)) override, make sure - // the overriding method of the most-derived class is seen first - // and inserted into the "seenSignatures" set. - if (func->isVirtual()) - list.prepend(func); - else - list.append(func); + auto it = results.find(func->name()); + if (it == results.end()) { + results.insert(func->name(), AbstractMetaFunctionList(1, func)); + } else { + // If there are virtuals methods in the mix (PYSIDE-570, + // QFileSystemModel::index(QString,int) and + // QFileSystemModel::index(int,int,QModelIndex)) override, make sure + // the overriding method of the most-derived class is seen first + // and inserted into the "seenSignatures" set. + if (func->isVirtual()) + it.value().prepend(func); + else + it.value().append(func); + } } } return results; @@ -2503,8 +2551,8 @@ bool ShibokenGenerator::doSetup() Q_ASSERT(moduleEntry); getCode(snips, moduleEntry); - const FunctionGroupMap &functionGroups = getFunctionGroups(); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + const auto &functionGroups = getGlobalFunctionGroups(); + for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { for (AbstractMetaFunction *func : it.value()) getCode(snips, func->injectedCodeSnips()); } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index 80b172778..ebfc059de 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -54,6 +54,7 @@ extern const char *END_ALLOW_THREADS; class DocParser; class CodeSnip; class OverloadData; +struct GeneratorClassInfoCacheEntry; QT_FORWARD_DECLARE_CLASS(QTextStream) @@ -63,6 +64,8 @@ QT_FORWARD_DECLARE_CLASS(QTextStream) class ShibokenGenerator : public Generator { public: + using FunctionGroups = QMap<QString, AbstractMetaFunctionList>; // Sorted + ShibokenGenerator(); ~ShibokenGenerator() override; @@ -99,7 +102,8 @@ protected: * 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); + FunctionGroups getGlobalFunctionGroups() const; + static FunctionGroups getFunctionGroups(const AbstractMetaClass *scope); /** * Returns all different inherited overloads of func, and includes func as well. @@ -440,6 +444,10 @@ protected: static QStringList m_knownPythonTypes; private: + static const GeneratorClassInfoCacheEntry &getGeneratorClassInfo(const AbstractMetaClass *scope); + static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClass *scope); + static bool classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass); + QString translateTypeForWrapperMethod(const AbstractMetaType* cType, const AbstractMetaClass* context, Options opt = NoOption) const; |