diff options
15 files changed, 199 insertions, 120 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp index 366fc00a1..539234249 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp @@ -39,6 +39,7 @@ public: QString m_name; AbstractMetaType m_type; + AbstractMetaType m_modifiedType; bool m_hasName = false; Documentation m_doc; QString m_expression; @@ -68,7 +69,18 @@ const AbstractMetaType &AbstractMetaArgument::type() const void AbstractMetaArgument::setType(const AbstractMetaType &type) { if (d->m_type != type) - d->m_type = type; + d->m_type = d->m_modifiedType = type; +} + +const AbstractMetaType &AbstractMetaArgument::modifiedType() const +{ + return d->m_modifiedType; +} + +void AbstractMetaArgument::setModifiedType(const AbstractMetaType &type) +{ + if (d->m_modifiedType != type) + d->m_modifiedType = type; } QString AbstractMetaArgument::name() const diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.h b/sources/shiboken6/ApiExtractor/abstractmetaargument.h index b5fe22db7..93dab6f79 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetaargument.h +++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.h @@ -54,6 +54,9 @@ public: const AbstractMetaType &type() const; void setType(const AbstractMetaType &type); + void setModifiedType(const AbstractMetaType &type); + const AbstractMetaType &modifiedType() const; + bool isTypeModified() const { return modifiedType() != type(); } QString name() const; void setName(const QString &name, bool realName = true); diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 32c7e99fd..d27dc4abb 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -506,6 +506,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) metaFunc->setTypeEntry(funcEntry); applyFunctionModifications(metaFunc); + metaFunc->applyTypeModifications(); setInclude(funcEntry, func->fileName()); diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp index 2d9ee3dcb..05b598811 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp @@ -33,6 +33,7 @@ #include "abstractmetatype.h" #include <codemodel.h> #include "documentation.h" +#include "exception.h" #include "messages.h" #include "modifications.h" #include "propertyspec.h" @@ -75,6 +76,9 @@ public: const FunctionModificationList &modifications(const AbstractMetaFunction *q, const AbstractMetaClass *implementor) const; + bool applyTypeModification(const AbstractMetaFunction *q, + const QString &type, int number, QString *errorMessage); + QString m_name; QString m_originalName; Documentation m_doc; @@ -85,6 +89,7 @@ public: FunctionTypeEntry* m_typeEntry = nullptr; AbstractMetaFunction::FunctionType m_functionType = AbstractMetaFunction::NormalFunction; AbstractMetaType m_type; + QString m_modifiedTypeName; const AbstractMetaClass *m_class = nullptr; const AbstractMetaClass *m_implementingClass = nullptr; const AbstractMetaClass *m_declaringClass = nullptr; @@ -421,6 +426,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const cpy->setExceptionSpecification(d->m_exceptionSpecification); cpy->setAllowThreadModification(d->m_allowThreadModification); cpy->setExceptionHandlingModification(d->m_exceptionHandlingModification); + cpy->d->m_modifiedTypeName = d->m_modifiedTypeName; cpy->d->m_addedFunction = d->m_addedFunction; cpy->d->m_arguments = d->m_arguments; @@ -770,18 +776,9 @@ TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const Abstra return TypeSystem::UnspecifiedOwnership; } -QString AbstractMetaFunction::typeReplaced(int key) const +const QString &AbstractMetaFunction::modifiedTypeName() const { - for (const auto &modification : modifications(declaringClass())) { - for (const ArgumentModification &argumentModification : modification.argument_mods()) { - if (argumentModification.index() == key - && !argumentModification.modifiedType().isEmpty()) { - return argumentModification.modifiedType(); - } - } - } - - return QString(); + return d->m_modifiedTypeName; } bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const @@ -795,6 +792,48 @@ bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const return false; } +// Note: The declaring class must be correctly set for this to work. +bool AbstractMetaFunctionPrivate::applyTypeModification(const AbstractMetaFunction *q, + const QString &type, + int number, QString *errorMessage) +{ + if (number < 0 || number > m_arguments.size()) { + *errorMessage = + msgTypeModificationFailed(type, number, q, + msgArgumentOutOfRange(number, 0, m_arguments.size())); + return false; + } + + // Modified return types may have unparseable types like Python tuples + if (number == 0) { + m_modifiedTypeName = type; + return true; + } + + auto typeOpt = AbstractMetaType::fromString(type, errorMessage); + if (!typeOpt.has_value()) { + *errorMessage = msgTypeModificationFailed(type, number, q, *errorMessage); + return false; + } + m_arguments[number - 1].setModifiedType(typeOpt.value()); + return true; +} + +void AbstractMetaFunction::applyTypeModifications() +{ + QString errorMessage; + for (const auto &modification : modifications(declaringClass())) { + for (const ArgumentModification &am : modification.argument_mods()) { + const int n = am.index(); + if (am.isTypeModified() + && !d->applyTypeModification(this, am.modifiedType(), + n, &errorMessage)) { + throw Exception(errorMessage); + } + } + } +} + QString AbstractMetaFunction::pyiTypeReplaced(int argumentIndex) const { for (const auto &modification : modifications(declaringClass())) { @@ -822,12 +861,9 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu if (i > 0) result += QLatin1Char(','); - QString typeName; - if (comment) - typeName = q->typeReplaced(i + 1); - if (typeName.isEmpty()) - typeName = m_arguments.at(i).type().minimalSignature(); - result += typeName; + result += comment + ? m_arguments.at(i).modifiedType().minimalSignature() + : m_arguments.at(i).type().minimalSignature(); } result += QLatin1Char(')'); if (m_constant) @@ -835,10 +871,9 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu result = TypeDatabase::normalizedSignature(result); if (comment && !q->isVoid()) { - QString typeName = q->typeReplaced(0); - if (typeName.isEmpty()) - typeName = q->type().minimalSignature(); - result += QStringLiteral("->") + typeName; + result += u"->"_qs; + result += q->isTypeModified() + ? q->modifiedTypeName() : q->type().minimalSignature(); } return result; } diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h index 415fc4ae2..9bad1cd44 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h @@ -308,9 +308,13 @@ public: // Returns the ownership rules for the given argument (target lang). TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const; - QString typeReplaced(int argument_index) const; + const QString &modifiedTypeName() const; + bool isTypeModified() const { return !modifiedTypeName().isEmpty(); } + bool isModifiedToArray(int argumentIndex) const; + void applyTypeModifications(); + /// Return the (modified) type for the signature; modified-pyi-type, modified-type QString pyiTypeReplaced(int argumentIndex) const; diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index 3e42f40ac..9e6b3d44e 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -1562,11 +1562,14 @@ void AbstractMetaClass::fixFunctions() bool hasPrivateConstructors = false; bool hasPublicConstructors = false; + // Apply modifications after the declaring class has been set for (const auto &func : qAsConst(funcs)) { + auto ncFunc = qSharedPointerConstCast<AbstractMetaFunction>(func); for (const auto &mod : func->modifications(this)) { if (mod.isRenameModifier()) - qSharedPointerConstCast<AbstractMetaFunction>(func)->setName(mod.renamedToName()); + ncFunc->setName(mod.renamedToName()); } + ncFunc->applyTypeModifications(); // Make sure class is abstract if one of the functions is if (func->isAbstract()) { diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index ff4a9fa42..b7a1e9091 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -77,6 +77,33 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass, return result; } +QString msgTypeModificationFailed(const QString &type, int n, + const AbstractMetaFunction *func, + const QString &why) +{ + QString result; + QTextStream str(&result); + str << "Unable to modify the "; + if (n == 0) + str << "return type"; + else + str << "type of argument " << n; + + str << " of "; + if (auto *c = func->ownerClass()) + str << c->name() << "::"; + str << func->signature() << " to \"" << type << "\": " << why; + return result; +} + +QString msgArgumentOutOfRange(int number, int minValue, int maxValue) +{ + QString result; + QTextStream(&result) << "Argument number " << number + << " out of range " << minValue << ".." << maxValue << '.'; + return result; +} + template <class Stream> static void msgFormatEnumType(Stream &str, const EnumModelItem &enumItem, diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index fb4b28e26..0accbd449 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -66,6 +66,12 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass, const QStringList &possibleSignatures, const AbstractMetaFunctionCList &allFunctions); +QString msgTypeModificationFailed(const QString &type, int n, + const AbstractMetaFunction *func, + const QString &why); + +QString msgArgumentOutOfRange(int number, int minValue, int maxValue); + QString msgClassOfEnumNotFound(const EnumTypeEntry *entry); QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp index 8c6f31187..92b445791 100644 --- a/sources/shiboken6/ApiExtractor/modifications.cpp +++ b/sources/shiboken6/ApiExtractor/modifications.cpp @@ -481,7 +481,7 @@ ArgumentModification::ArgumentModification(ArgumentModification &&) = default; ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) = default; ArgumentModification::~ArgumentModification() = default; -QString ArgumentModification::modifiedType() const +const QString &ArgumentModification::modifiedType() const { return d->modified_type; } @@ -492,6 +492,11 @@ void ArgumentModification::setModifiedType(const QString &value) d->modified_type = value; } +bool ArgumentModification::isTypeModified() const +{ + return !d->modified_type.isEmpty(); +} + QString ArgumentModification::pyiType() const { return d->pyiType; diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h index 291f80545..917dd7459 100644 --- a/sources/shiboken6/ApiExtractor/modifications.h +++ b/sources/shiboken6/ApiExtractor/modifications.h @@ -190,8 +190,9 @@ public: void addReferenceCount(const ReferenceCount &value); // The text given for the new type of the argument - QString modifiedType() const; + const QString &modifiedType() const; void setModifiedType(const QString &value); + bool isTypeModified() const; QString pyiType() const; void setPyiType(const QString &value); diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 4fd5d4094..8aba8cd20 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -860,8 +860,8 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio if (func->type().isVoid()) return QLatin1String("\"\""); - if (!func->typeReplaced(0).isEmpty()) - return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"'); + if (func->isTypeModified()) + return u'"' + func->modifiedTypeName() + u'"'; // SbkType would return null when the type is a container. auto typeEntry = func->type().typeEntry(); @@ -1168,10 +1168,10 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s, if (invalidateReturn) s << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;\n"; - if (func->typeReplaced(0) != cPyObjectT()) { + if (func->modifiedTypeName() != cPyObjectT()) { s << "// Check return type\n"; - if (func->typeReplaced(0).isEmpty()) { + if (!func->isTypeModified()) { s << PYTHON_TO_CPPCONVERSION_STRUCT << ' ' << PYTHON_TO_CPP_VAR << " = " << cpythonIsConvertibleFunction(func->type()) @@ -1192,8 +1192,15 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s, s << "// Check return type\n" << "bool typeIsValid = "; - writeTypeCheck(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), - isNumber(func->type().typeEntry()), func->typeReplaced(0)); + if (func->isTypeModified()) { + writeTypeCheck(s, func->modifiedTypeName(), + QLatin1String(PYTHON_RETURN_VAR)); + } else { + const bool numberType = isNumber(func->type().typeEntry()); + writeTypeCheck(s, func->type(), + QLatin1String(PYTHON_RETURN_VAR), numberType); + } + s << ";\n"; s << "if (!typeIsValid"; if (func->type().isPointerToWrapperType()) @@ -1570,9 +1577,10 @@ return result;)"; toCppConv = QLatin1Char('*') + cpythonWrapperCPtr(sourceClass->typeEntry(), QLatin1String("pyIn")); } else { // Constructor that does implicit conversion. - if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1)) + const auto &firstArg = conv->arguments().constFirst(); + if (firstArg.isTypeModified() || conv->isModifiedToArray(1)) continue; - const AbstractMetaType sourceType = conv->arguments().constFirst().type(); + const AbstractMetaType &sourceType = firstArg.type(); typeCheck = cpythonCheckFunction(sourceType); bool isUserPrimitiveWithoutTargetLangName = sourceType.isUserPrimitive() && !sourceType.typeEntry()->hasTargetLangApiType(); @@ -1750,9 +1758,10 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass sourceType = AbstractMetaType::fromAbstractMetaClass(conv->ownerClass()); } else { // Constructor that does implicit conversion. - if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1)) + const auto &firstArg = conv->arguments().constFirst(); + if (firstArg.isTypeModified() || conv->isModifiedToArray(1)) continue; - sourceType = conv->arguments().constFirst().type(); + sourceType = firstArg.type(); } QString toCpp = pythonToCppFunctionName(sourceType, targetType); QString isConv = convertibleToCppFunctionName(sourceType, targetType); @@ -2383,18 +2392,21 @@ static QString pythonToCppConverterForArgumentName(const QString &argumentName) return result; } -void CppGenerator::writeTypeCheck(TextStream &s, AbstractMetaType argType, - const QString &argumentName, bool isNumber, - const QString &customType, bool rejectNull) const +void CppGenerator::writeTypeCheck(TextStream &s, const QString &customType, + const QString &argumentName) const { - if (!customType.isEmpty()) { - QString errorMessage; - const auto metaTypeOpt = AbstractMetaType::fromString(customType, &errorMessage); - if (!metaTypeOpt.has_value()) - throw Exception(errorMessage); - argType = metaTypeOpt.value(); - } + QString errorMessage; + const auto metaTypeOpt = AbstractMetaType::fromString(customType, &errorMessage); + if (!metaTypeOpt.has_value()) + throw Exception(errorMessage); + writeTypeCheck(s, metaTypeOpt.value(), argumentName, + ShibokenGenerator::isNumber(metaTypeOpt.value())); +} +void CppGenerator::writeTypeCheck(TextStream &s, const AbstractMetaType &argType, + const QString &argumentName, bool isNumber, + bool rejectNull) const +{ // TODO-CONVERTER: merge this with the code below. QString typeCheck = cpythonIsConvertibleFunction(argType); typeCheck.append(u'(' +argumentName + u')'); @@ -2419,13 +2431,16 @@ void CppGenerator::writeTypeCheck(TextStream &s, AbstractMetaType argType, static void checkTypeViability(const AbstractMetaFunctionCPtr &func, const AbstractMetaType &type, int argIdx) { + const bool modified = argIdx == 0 + ? func->isTypeModified() + : func->arguments().at(argIdx -1).isTypeModified(); if (type.isVoid() || !type.typeEntry()->isPrimitive() || type.indirections() == 0 || (type.indirections() == 1 && type.typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern) || type.isCString() || func->argumentRemoved(argIdx) - || !func->typeReplaced(argIdx).isEmpty() + || modified || !func->conversionRule(TypeSystem::All, argIdx).isEmpty() || func->hasInjectedCode()) return; @@ -2473,14 +2488,13 @@ void CppGenerator::writeTypeCheck(TextStream &s, // This condition trusts that the OverloadData object will arrange for // PyLong type to come after the more precise numeric types (e.g. float and bool) - AbstractMetaType argType = overloadData->argType(); + AbstractMetaType argType = overloadData->modifiedArgType(); if (auto viewOn = argType.viewOn()) argType = *viewOn; bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType); - QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : QString()); bool rejectNull = shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos()); - writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull); + writeTypeCheck(s, argType, argumentName, numberType, rejectNull); } void CppGenerator::writeArgumentConversion(TextStream &s, @@ -2508,16 +2522,8 @@ AbstractMetaType return {}; } - QString typeReplaced = func->typeReplaced(index + 1); - if (typeReplaced.isEmpty()) { - auto argType = func->arguments().at(index).type(); - return argType.viewOn() ? *argType.viewOn() : argType; - } - - auto argType = AbstractMetaType::fromString(typeReplaced); - if (!argType.has_value()) - throw Exception(msgUnknownTypeInArgumentTypeReplacement(typeReplaced, func.data())); - return argType.value(); + auto argType = func->arguments().at(index).modifiedType(); + return argType.viewOn() ? *argType.viewOn() : argType; } static inline QString arrayHandleType(const AbstractMetaTypeList &nestedArrayTypes) @@ -2870,7 +2876,8 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s, int startArg = od->argPos(); int sequenceArgCount = 0; while (od && !od->argType().isVarargs()) { - bool typeReplacedByPyObject = od->argumentTypeReplaced() == cPyObjectT(); + const bool typeReplacedByPyObject = od->isTypeModified() + && od->modifiedArgType().name() == cPyObjectT(); if (!typeReplacedByPyObject) { if (usePyArgs) pyArgName = pythonArgsAt(od->argPos()); @@ -3401,8 +3408,8 @@ void CppGenerator::writeNamedArgumentResolution(TextStream &s, const AbstractMet { Indentation indent(s); s << pyArgName << " = value;\nif (!"; - writeTypeCheck(s, arg.type(), pyArgName, isNumber(arg.type().typeEntry()), - func->typeReplaced(arg.argumentIndex() + 1)); + const auto &type = arg.modifiedType(); + writeTypeCheck(s, type, pyArgName, isNumber(type.typeEntry()), {}); s << ")\n"; { Indentation indent(s); @@ -6565,7 +6572,7 @@ void CppGenerator::writeReturnValueHeuristics(TextStream &s, const AbstractMetaF || type.isVoid() || func->isStatic() || func->isConstructor() - || !func->typeReplaced(0).isEmpty()) { + || func->isTypeModified()) { return; } diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 8181e5711..3e3e5a21d 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -142,9 +142,11 @@ private: /// Writes the check section for the validity of wrapped C++ objects. static void writeInvalidPyObjectCheck(TextStream &s, const QString &pyObj); - void writeTypeCheck(TextStream &s, AbstractMetaType argType, const QString &argumentName, - bool isNumber = false, const QString &customType = QString(), - bool rejectNull = false) const; + void writeTypeCheck(TextStream &s, const AbstractMetaType &argType, + const QString &argumentName, + bool isNumber = false, bool rejectNull = false) const; + void writeTypeCheck(TextStream &s, const QString &customType, + const QString &argumentName) const; void writeTypeCheck(TextStream& s, const QSharedPointer<OverloadDataNode> &overloadData, const QString &argumentName) const; diff --git a/sources/shiboken6/generator/shiboken/overloaddata.cpp b/sources/shiboken6/generator/shiboken/overloaddata.cpp index 46a2ee201..3f0e484e8 100644 --- a/sources/shiboken6/generator/shiboken/overloaddata.cpp +++ b/sources/shiboken6/generator/shiboken/overloaddata.cpp @@ -64,11 +64,6 @@ static QString getTypeName(const AbstractMetaType &type) return typeName; } -static QString getTypeName(const OverloadDataNodePtr &ov) -{ - return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType()); -} - static bool typesAreEqual(const AbstractMetaType &typeA, const AbstractMetaType &typeB) { if (typeA.typeEntry() == typeB.typeEntry()) { @@ -199,7 +194,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api) OverloadGraph graph; for (const auto &ov : qAsConst(m_children)) { - const QString typeName = getTypeName(ov); + const QString typeName = getTypeName(ov->modifiedArgType()); auto it = typeToOverloads.find(typeName); if (it == typeToOverloads.end()) { typeToOverloads.insert(typeName, {ov}); @@ -261,7 +256,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api) for (const auto &ov : qAsConst(m_children)) { const AbstractMetaType &targetType = ov->argType(); - const QString targetTypeEntryName = getTypeName(ov); + const QString targetTypeEntryName = getTypeName(ov->modifiedArgType()); // Process implicit conversions const auto &functions = api.implicitConversions(targetType); @@ -505,7 +500,6 @@ void OverloadDataNode::addOverload(const AbstractMetaFunctionCPtr &func) OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFunctionCPtr &func, const AbstractMetaArgument &arg) { - const AbstractMetaType &argType = arg.type(); OverloadDataNodePtr overloadData; if (!func->isOperatorOverload()) { for (const auto &tmp : qAsConst(m_children)) { @@ -513,10 +507,7 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu // If an argument have a type replacement, then we should create a new overloaddata // for it, unless the next argument also have a identical type replacement. - QString replacedArg = func->typeReplaced(tmp->argPos() + 1); - bool argsReplaced = !replacedArg.isEmpty() || tmp->hasArgumentTypeReplace(); - if ((!argsReplaced && typesAreEqual(tmp->argType(), argType)) - || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) { + if (typesAreEqual(tmp->modifiedArgType(), arg.modifiedType())) { tmp->addOverload(func); overloadData = tmp; } @@ -524,10 +515,8 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu } if (overloadData.isNull()) { - QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1); const int argpos = argPos() + 1; - overloadData.reset(new OverloadDataNode(func, this, arg, argpos, - typeReplaced)); + overloadData.reset(new OverloadDataNode(func, this, arg, argpos)); m_children.append(overloadData); } @@ -537,12 +526,11 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu bool OverloadData::hasNonVoidReturnType() const { for (const auto &func : m_overloads) { - const QString typeReplaced = func->typeReplaced(0); - if (typeReplaced.isEmpty()) { - if (!func->argumentRemoved(0) && !func->type().isVoid()) + if (func->isTypeModified()) { + if (func->modifiedTypeName() != u"void") return true; } else { - if (typeReplaced != u"void") + if (!func->argumentRemoved(0) && !func->type().isVoid()) return true; } } @@ -833,11 +821,11 @@ void OverloadDataRootNode::dumpRootGraph(QTextStream &s, int minArgs, int maxArg // Shows type changes for all function signatures for (const auto &func : m_overloads) { - if (func->typeReplaced(0).isEmpty()) + if (!func->isTypeModified()) continue; s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func); s << "-type</td><td bgcolor=\"gray\" align=\"left\">"; - s << toHtml(func->typeReplaced(0)) << "</td></tr>"; + s << toHtml(func->modifiedTypeName()) << "</td></tr>"; } // Minimum and maximum number of arguments @@ -882,10 +870,10 @@ void OverloadDataNode::dumpNodeGraph(QTextStream &s) const s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>"; // Argument type information - QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType().cppSignature(); + const QString type = modifiedArgType().cppSignature(); s << "<tr><td bgcolor=\"gray\" align=\"right\">type</td><td bgcolor=\"gray\" align=\"left\">"; s << toHtml(type) << "</td></tr>"; - if (hasArgumentTypeReplace()) { + if (isTypeModified()) { s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">"; s << toHtml(argType().cppSignature()) << "</td></tr>"; } @@ -1042,8 +1030,8 @@ void OverloadDataNode::formatDebug(QDebug &d) const if (m_argument.argumentIndex() != m_argPos) d << ", argIndex=" << m_argument.argumentIndex(); d << ", argType=\"" << m_argument.type().cppSignature() << '"'; - if (!m_argTypeReplaced.isEmpty()) - d << ", argTypeReplaced=\"" << m_argTypeReplaced << '"'; + if (isTypeModified()) + d << ", modifiedArgType=\"" << modifiedArgType().cppSignature() << '"'; formatOverloads(d); formatNextOverloadData(d); d << ')'; diff --git a/sources/shiboken6/generator/shiboken/overloaddata.h b/sources/shiboken6/generator/shiboken/overloaddata.h index e72b64778..cbf2470f6 100644 --- a/sources/shiboken6/generator/shiboken/overloaddata.h +++ b/sources/shiboken6/generator/shiboken/overloaddata.h @@ -116,9 +116,9 @@ public: const AbstractMetaArgument &argument() const { return m_argument; } const AbstractMetaType &argType() const { return m_argument.type(); } + const AbstractMetaType &modifiedArgType() const { return m_argument.modifiedType(); } - bool hasArgumentTypeReplace() const { return !m_argTypeReplaced.isEmpty(); } - const QString &argumentTypeReplaced() const { return m_argTypeReplaced; } + bool isTypeModified() const { return m_argument.isTypeModified(); } const AbstractMetaArgument *overloadArgument(const AbstractMetaFunctionCPtr &func) const; diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index c05ee2e25..0bf43482d 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -643,7 +643,7 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunctionCPtr &f continue; const auto &type = arg.type(); - if (!func->typeReplaced(arg.argumentIndex() + 1).isEmpty()) { + if (arg.isTypeModified()) { result += QLatin1Char(objType); } else if (arg.type().isObject() || type.isValue() @@ -1228,15 +1228,13 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunctionCPtr &func, const AbstractMetaArgument &argument, Options options) const { - QString modified_type; - if (!(options & OriginalTypeDescription)) - modified_type = func->typeReplaced(argument.argumentIndex() + 1); - QString arg; + auto type = options.testFlag(OriginalTypeDescription) + ? argument.type() : argument.modifiedType(); - if (modified_type.isEmpty()) - arg = translateType(argument.type(), func->implementingClass(), options); - else - arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.')); + QString arg = translateType(type, func->implementingClass(), options); + + if (argument.isTypeModified()) + arg.replace(QLatin1Char('$'), QLatin1Char('.')); // Haehh? // "int a", "int a[]" const int arrayPos = arg.indexOf(QLatin1Char('[')); @@ -1300,9 +1298,8 @@ GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) QString ShibokenGenerator::functionReturnType(const AbstractMetaFunctionCPtr &func, Options options) const { - QString modifiedReturnType = QString(func->typeReplaced(0)); - if (!modifiedReturnType.isEmpty() && !(options & OriginalTypeDescription)) - return modifiedReturnType; + if (func->isTypeModified() && !options.testFlag(OriginalTypeDescription)) + return func->modifiedTypeName(); return translateType(func->type(), func->implementingClass(), options); } @@ -1536,13 +1533,7 @@ ShibokenGenerator::ArgumentVarReplacementList argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(i); if (!argRemoved && argValue.isEmpty()) { int argPos = i - removed; - AbstractMetaType type = arg.type(); - QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1); - if (!typeReplaced.isEmpty()) { - auto builtType = AbstractMetaType::fromString(typeReplaced); - if (builtType.has_value()) - type = builtType.value(); - } + AbstractMetaType type = arg.modifiedType(); if (type.typeEntry()->isCustom()) { argValue = usePyArgs ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG); @@ -1768,13 +1759,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s, for (const ArgumentVarReplacementPair &pair : argReplacements) { const AbstractMetaArgument &arg = pair.first; int idx = arg.argumentIndex() + 1; - AbstractMetaType type = arg.type(); - QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1); - if (!typeReplaced.isEmpty()) { - auto builtType = AbstractMetaType::fromString(typeReplaced); - if (builtType.has_value()) - type = builtType.value(); - } + AbstractMetaType type = arg.modifiedType(); if (type.isWrapperType()) { QString replacement = pair.second; if (type.shouldDereferenceArgument()) |
