diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-06-25 10:25:09 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-06-26 14:35:37 +0200 |
| commit | 16098891ad21c2ba984582a1de770e49f961f22b (patch) | |
| tree | 731ad7fe95611e904706631f0193ae90f208791c | |
| parent | 5bf6334c1b5e821598ddf3964010a07c520a5b1f (diff) | |
shiboken6: Refactor registerConverterName() streamable helper
Move the functionality to register partially qualified names
(previously in helper registerConverterInScopes() and elsewhere), to
register names with indirections, and to use typeid() into the
streamable class controlled by flags. Simplify the code accordingly.
This requires adding indexOf() to the helpers for QAnyStringView.
Task-number: PYSIDE-2792
Change-Id: I7af0d8333e3c417e03f6615b471dc7220c95d388
Reviewed-by: Christian Tismer <tismer@stackless.com>
3 files changed, 111 insertions, 58 deletions
diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp index 35d2d535a..c7a224533 100644 --- a/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.cpp @@ -54,3 +54,25 @@ bool asv_contains(QAnyStringView asv, const char *needle) { return asv.visit([needle](auto s) { return asv_containsImpl(s, needle); }); } + +static qsizetype asv_indexOfImpl(QLatin1StringView v, const char *needle) +{ + return v.indexOf(QLatin1StringView(needle)); +} + +static qsizetype asv_indexOfImpl(QUtf8StringView v, const char *needle) +{ + const char *data = v.data(); + const char *match = std::strstr(data, needle); + return match != nullptr ? qsizetype(match - data) : qsizetype(-1); +} + +static qsizetype asv_indexOfImpl(QStringView v, const char *needle) +{ + return v.indexOf(QLatin1StringView(needle)); +} + +qsizetype asv_indexOf(QAnyStringView asv, const char *needle) +{ + return asv.visit([needle](auto s) { return asv_indexOfImpl(s, needle); }); +} diff --git a/sources/shiboken6/ApiExtractor/anystringview_helpers.h b/sources/shiboken6/ApiExtractor/anystringview_helpers.h index e1e6ab7f0..8c25cffb4 100644 --- a/sources/shiboken6/ApiExtractor/anystringview_helpers.h +++ b/sources/shiboken6/ApiExtractor/anystringview_helpers.h @@ -14,5 +14,6 @@ QTextStream &operator<<(QTextStream &str, QAnyStringView asv); bool asv_contains(QAnyStringView asv, char needle); bool asv_contains(QAnyStringView asv, const char *needle); +qsizetype asv_indexOf(QAnyStringView asv, const char *needle); #endif // ANYSTRINGVIEW_STREAM_H diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 904fc4445..e83d6d1ed 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "cppgenerator.h" +#include "anystringview_helpers.h" #include "configurablescope.h" #include "generatorargument.h" #include "generatorstrings.h" @@ -124,21 +125,76 @@ TextStream &operator<<(TextStream &s, CppGenerator::ErrorReturn r) static constexpr auto converterVar = "converter"_L1; -struct registerConverterName +// Helper streamable class for generating code registering converters +class registerConverterName { +public: + enum Flag + { + Indirections = 0x1, // Also register "Type*", "Type&" + PartiallyQualifiedAliases = 0x2, // Also register "B" when passed "A::B" + TypeId = 0x4 // Use typeid().name() for the string passed in + }; + Q_DECLARE_FLAGS(Flags, Flag) + explicit registerConverterName(QAnyStringView typeName, - QAnyStringView varName = converterVar) : - m_typeName(typeName), m_varName(varName) {} + QAnyStringView varName = {}, + Flags flags = {}) noexcept: + m_typeName(typeName), m_varName(varName), m_flags(flags) {} + + void format(TextStream &s) const; + + inline friend TextStream &operator<<(TextStream &s, const registerConverterName &r) + { + r.format(s); + return s; + } + +private: + static void formatEntry(TextStream &s, QAnyStringView typeName, + QAnyStringView varName, Flags flags, + const char *indirection = ""); QAnyStringView m_typeName; QAnyStringView m_varName; + Flags m_flags; }; -TextStream &operator<<(TextStream &s, const registerConverterName &r) +Q_DECLARE_OPERATORS_FOR_FLAGS(registerConverterName::Flags) + +void registerConverterName::formatEntry(TextStream &s, QAnyStringView typeName, + QAnyStringView varName, Flags flags, + const char *indirection) { - s << "Shiboken::Conversions::registerConverterName(" << r.m_varName - << ", \"" << r.m_typeName << "\");\n"; - return s; + s << "Shiboken::Conversions::registerConverterName(" + << varName << ", "; + if (flags.testFlag(TypeId)) + s << "typeid(" << typeName << indirection << ").name()"; + else + s << '"' << typeName << indirection << '"'; + s << ");\n"; +} + +void registerConverterName::format(TextStream &s) const +{ + QAnyStringView typeName = m_typeName; + const QAnyStringView varName = m_varName.isEmpty() ? converterVar : m_varName; + auto flags = m_flags; + + while (true) { + formatEntry(s, typeName, varName, flags); + if (flags.testFlag(Indirections)) { + formatEntry(s, typeName, varName, flags, "*"); + formatEntry(s, typeName, varName, flags, "&"); + } + + if (!flags.testFlag(PartiallyQualifiedAliases)) + break; + auto pos = asv_indexOf(typeName, "::"); + if (pos < 0) + break; + typeName = typeName.sliced(pos + 2); + } } // Protocol function name / function parameters / return type @@ -1844,51 +1900,35 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass } s << outdent << ");\n\n"; - auto writeConversions = [&s](const QString &signature) - { - s << registerConverterName(signature) << registerConverterName(signature + u'*') - << registerConverterName(signature + u'&'); - }; - - auto writeConversionsForType = [writeConversions](const QString &fullTypeName) - { - QStringList lst = fullTypeName.split(u"::"_s, - Qt::SkipEmptyParts); - while (!lst.isEmpty()) { - QString signature = lst.join(u"::"_s); - writeConversions(signature); - lst.removeFirst(); - } - }; - - if (!classContext.forSmartPointer()) { - writeConversionsForType(metaClass->qualifiedCppName()); + s << registerConverterName(metaClass->qualifiedCppName(), {}, + registerConverterName::Indirections + | registerConverterName::PartiallyQualifiedAliases); } else { - const QString &smartPointerType = classContext.preciseType().instantiations().at(0).cppSignature(); + QString pointeeType = classContext.preciseType().instantiations().at(0).cppSignature(); const QString &smartPointerName = classContext.preciseType().typeEntry()->name(); - QStringList lst = smartPointerType.split(u"::"_s, - Qt::SkipEmptyParts); - while (!lst.isEmpty()) { - QString signature = lst.join(u"::"_s); - writeConversions(smartPointerName + u'<' + signature + u'>'); - lst.removeFirst(); + registerConverterName::Flags flags = registerConverterName::Indirections; + while (true) { + s << registerConverterName(smartPointerName + u'<' + pointeeType + u'>', {}, flags); + auto pos = pointeeType.indexOf("::"_L1); + if (pos < 0) + break; + pointeeType.remove(0, pos + 2); } } - s << "Shiboken::Conversions::registerConverterName(converter, typeid(" << m_gsp; - QString qualifiedCppNameInvocation; + QString qualifiedCppNameInvocation = m_gsp; if (!classContext.forSmartPointer()) - qualifiedCppNameInvocation = metaClass->qualifiedCppName(); + qualifiedCppNameInvocation += metaClass->qualifiedCppName(); else - qualifiedCppNameInvocation = classContext.preciseType().cppSignature(); - - s << qualifiedCppNameInvocation << ").name());\n"; + qualifiedCppNameInvocation += classContext.preciseType().cppSignature(); + s << registerConverterName(qualifiedCppNameInvocation, {}, + registerConverterName::TypeId); if (classContext.useWrapper()) { - s << "Shiboken::Conversions::registerConverterName(converter, typeid(" - << classContext.wrapperName() << ").name());\n"; + s << registerConverterName(classContext.wrapperName(), {}, + registerConverterName::TypeId); } if (!typeEntry->isValue() && !typeEntry->isSmartPointer()) @@ -1900,7 +1940,7 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass targetTypeName = sourceTypeName + u"_COPY"_s; QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName); QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName); - writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv); + writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); // User provided implicit conversions. @@ -1926,7 +1966,7 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass } QString toCpp = pythonToCppFunctionName(sourceType, targetType); QString isConv = convertibleToCppFunctionName(sourceType, targetType); - writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv); + writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); } if (typeEntry->isValue()) { @@ -4170,18 +4210,6 @@ void CppGenerator::writePrimitiveConverterInitialization(TextStream &s, writeCustomConverterRegister(s, customConversion, converter); } -static void registerConverterInScopes(TextStream &s, QStringView signature, - QAnyStringView varName = converterVar) -{ - while (true) { - s << registerConverterName(signature, varName); - const auto qualifierPos = signature.indexOf("::"_L1); - if (qualifierPos == -1) - break; - signature = signature.sliced(qualifierPos + 2); - } -} - void CppGenerator::writeEnumConverterInitialization(TextStream &s, const AbstractMetaEnum &metaEnum) { if (metaEnum.isPrivate() || metaEnum.isAnonymous()) @@ -4203,9 +4231,10 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const Abstrac const QString isConv = convertibleToCppFunctionName(typeName, typeName); writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv); s << "Shiboken::Enum::setTypeConverter(" << enumPythonVar - << ", converter);\n"; + << ", converter);\n" + << registerConverterName(enumType->qualifiedCppName(), {}, + registerConverterName::PartiallyQualifiedAliases); - registerConverterInScopes(s, enumType->qualifiedCppName()); if (auto flags = enumType->flags()) s << "// Register converter for flag '" << flags->qualifiedCppName() << "'.\n" << registerConverterName(flags->name()) // QMetaType @@ -6490,7 +6519,8 @@ bool CppGenerator::finishGeneration() if (!pte->referencesType()) continue; TypeEntryCPtr referencedType = basicReferencedTypeEntry(pte); - registerConverterInScopes(s, pte->qualifiedCppName(), converterObject(referencedType)); + s << registerConverterName(pte->qualifiedCppName(), converterObject(referencedType), + registerConverterName::PartiallyQualifiedAliases); } s << '\n'; |
