diff options
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/shibokengenerator.cpp')
-rw-r--r-- | sources/shiboken2/generator/shiboken2/shibokengenerator.cpp | 377 |
1 files changed, 242 insertions, 135 deletions
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index fd75c620e..0f5f09d60 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -27,9 +27,11 @@ ****************************************************************************/ #include "shibokengenerator.h" +#include "ctypenames.h" #include <abstractmetalang.h> #include <messages.h> #include "overloaddata.h" +#include "propertyspec.h" #include <reporthandler.h> #include <typedatabase.h> #include <abstractmetabuilder.h> @@ -47,6 +49,7 @@ static const char RETURN_VALUE_HEURISTIC[] = "enable-return-value-heuristic"; static const char ENABLE_PYSIDE_EXTENSIONS[] = "enable-pyside-extensions"; static const char DISABLE_VERBOSE_ERROR_MESSAGES[] = "disable-verbose-error-messages"; static const char USE_ISNULL_AS_NB_NONZERO[] = "use-isnull-as-nb_nonzero"; +static const char WRAPPER_DIAGNOSTICS[] = "wrapper-diagnostics"; const char *CPP_ARG = "cppArg"; const char *CPP_ARG_REMOVED = "removed_cppArg"; @@ -96,7 +99,7 @@ static QString resolveScopePrefix(const QStringList &scopeList, const QString &v static inline QStringList splitClassScope(const AbstractMetaClass *scope) { - return scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + return scope->qualifiedCppName().split(QLatin1String("::"), Qt::SkipEmptyParts); } static QString resolveScopePrefix(const AbstractMetaClass *scope, const QString &value) @@ -194,8 +197,8 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences() m_pythonPrimitiveTypeName.insert(QLatin1String(intType), QStringLiteral("PyInt")); // PyFloat - m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat")); - m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat")); + m_pythonPrimitiveTypeName.insert(doubleT(), QLatin1String("PyFloat")); + m_pythonPrimitiveTypeName.insert(floatT(), QLatin1String("PyFloat")); // PyLong const char *longTypes[] = { @@ -255,18 +258,18 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences() m_formatUnits.clear(); m_formatUnits.insert(QLatin1String("char"), QLatin1String("b")); m_formatUnits.insert(QLatin1String("unsigned char"), QLatin1String("B")); - m_formatUnits.insert(QLatin1String("int"), QLatin1String("i")); + m_formatUnits.insert(intT(), QLatin1String("i")); m_formatUnits.insert(QLatin1String("unsigned int"), QLatin1String("I")); - m_formatUnits.insert(QLatin1String("short"), QLatin1String("h")); - m_formatUnits.insert(QLatin1String("unsigned short"), QLatin1String("H")); - m_formatUnits.insert(QLatin1String("long"), QLatin1String("l")); - m_formatUnits.insert(QLatin1String("unsigned long"), QLatin1String("k")); - m_formatUnits.insert(QLatin1String("long long"), QLatin1String("L")); + m_formatUnits.insert(shortT(), QLatin1String("h")); + m_formatUnits.insert(unsignedShortT(), QLatin1String("H")); + m_formatUnits.insert(longT(), QLatin1String("l")); + m_formatUnits.insert(unsignedLongLongT(), QLatin1String("k")); + m_formatUnits.insert(longLongT(), QLatin1String("L")); m_formatUnits.insert(QLatin1String("__int64"), QLatin1String("L")); - m_formatUnits.insert(QLatin1String("unsigned long long"), QLatin1String("K")); + m_formatUnits.insert(unsignedLongLongT(), QLatin1String("K")); m_formatUnits.insert(QLatin1String("unsigned __int64"), QLatin1String("K")); - m_formatUnits.insert(QLatin1String("double"), QLatin1String("d")); - m_formatUnits.insert(QLatin1String("float"), QLatin1String("f")); + m_formatUnits.insert(doubleT(), QLatin1String("d")); + m_formatUnits.insert(floatT(), QLatin1String("f")); } void ShibokenGenerator::initKnownPythonTypes() @@ -322,53 +325,22 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass *metaCl return result; } -void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass) +bool ShibokenGenerator::shouldWriteVirtualMethodNative(const AbstractMetaFunction *func) { - Q_ASSERT(metaClass); - // if a scope is not to be generated, collect its enums into the parent scope - if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum *metaEnum : enums) { - if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode() - && !enumList.contains(metaEnum)) { - enumList.append(metaEnum); - } - } - } -} - -static const AbstractMetaClass *getProperEnclosingClass(const AbstractMetaClass *metaClass) -{ - if (!metaClass) - return nullptr; - - if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - return metaClass; - - return getProperEnclosingClass(metaClass->enclosingClass()); -} - -const AbstractMetaClass *ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum *metaEnum) -{ - return getProperEnclosingClass(metaEnum->enclosingClass()); + // PYSIDE-803: Extracted this because it is used multiple times. + const AbstractMetaClass *metaClass = func->ownerClass(); + return (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) + && ((func->isVirtual() || func->isAbstract()) + && (func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0); } QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const { - if (shouldGenerateCppWrapper(metaClass)) { - QString result = metaClass->name(); - if (metaClass->enclosingClass()) // is a inner class - result.replace(QLatin1String("::"), QLatin1String("_")); - - result += QLatin1String("Wrapper"); - return result; - } - return metaClass->qualifiedCppName(); -} - -QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const -{ - return metaType->cppSignature(); + Q_ASSERT(shouldGenerateCppWrapper(metaClass)); + QString result = metaClass->name(); + if (metaClass->enclosingClass()) // is a inner class + result.replace(QLatin1String("::"), QLatin1String("_")); + return result + QLatin1String("Wrapper"); } QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass) @@ -376,14 +348,15 @@ QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClas QString fullClassName = metaClass->name(); const AbstractMetaClass *enclosing = metaClass->enclosingClass(); while (enclosing) { - fullClassName.prepend(enclosing->name() + QLatin1Char('.')); + if (NamespaceTypeEntry::isVisibleScope(enclosing->typeEntry())) + fullClassName.prepend(enclosing->name() + QLatin1Char('.')); enclosing = enclosing->enclosingClass(); } fullClassName.prepend(packageName() + QLatin1Char('.')); return fullClassName; } -QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func) +QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func, bool forceFunc) { QString funcName; if (func->isOperatorOverload()) @@ -392,10 +365,14 @@ QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *fu funcName = func->name(); if (func->ownerClass()) { QString fullClassName = fullPythonClassName(func->ownerClass()); - if (func->isConstructor()) + if (func->isConstructor()) { funcName = fullClassName; - else + if (forceFunc) + funcName.append(QLatin1String(".__init__")); + } + else { funcName.prepend(fullClassName + QLatin1Char('.')); + } } else { funcName = packageName() + QLatin1Char('.') + func->name(); @@ -465,14 +442,38 @@ QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass * return cpythonBaseName(metaClass) + QLatin1String("_getattro"); } +QString ShibokenGenerator::cpythonGetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass) +{ + return cpythonBaseName(enclosingClass) + QStringLiteral("_get_") + name; +} + +QString ShibokenGenerator::cpythonSetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass) +{ + return cpythonBaseName(enclosingClass) + QStringLiteral("_set_") + name; +} + QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField *metaField) { - return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); + return cpythonGetterFunctionName(metaField->name(), metaField->enclosingClass()); } QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField *metaField) { - return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); + return cpythonSetterFunctionName(metaField->name(), metaField->enclosingClass()); +} + +QString ShibokenGenerator::cpythonGetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass) +{ + return cpythonGetterFunctionName(property->name(), metaClass); +} + +QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass) +{ + return cpythonSetterFunctionName(property->name(), metaClass); } static QString cpythonEnumFlagsName(const QString &moduleName, @@ -571,7 +572,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction { QString value = arg->defaultValueExpression(); - if (value.isEmpty() + if (value.isEmpty() || value == QLatin1String("{}") || arg->hasModifiedDefaultValueExpression() || isPointer(arg->type())) { return value; @@ -595,7 +596,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry()); if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL")) prefix = resolveScopePrefix(metaClass, value); - } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) { + } else if (arg->type()->isPrimitive() && arg->type()->name() == intT()) { if (enumValueRegEx.match(value).hasMatch() && func->implementingClass()) prefix = resolveScopePrefix(func->implementingClass(), value); } else if(arg->type()->isPrimitive()) { @@ -659,13 +660,13 @@ QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClas } QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass *metaClass, - const QString &argName) + const QString &argName) const { return cpythonWrapperCPtr(metaClass->typeEntry(), argName); } QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, - const QString &argName) + const QString &argName) const { if (!ShibokenGenerator::isWrapperType(metaType->typeEntry())) return QString(); @@ -675,7 +676,7 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, } QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry *type, - const QString &argName) + const QString &argName) const { if (!ShibokenGenerator::isWrapperType(type)) return QString(); @@ -803,7 +804,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry *type) baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type)); } else if (type->isContainer()) { const auto *ctype = static_cast<const ContainerTypeEntry *>(type); - switch (ctype->type()) { + switch (ctype->containerKind()) { case ContainerTypeEntry::ListContainer: case ContainerTypeEntry::StringListContainer: case ContainerTypeEntry::LinkedListContainer: @@ -844,7 +845,7 @@ QString ShibokenGenerator::cpythonTypeName(const TypeEntry *type) return cpythonBaseName(type) + QLatin1String("_TypeF()"); } -QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry *type) +QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry *type) const { return cppApiVariableName(type->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); @@ -863,7 +864,7 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType *type) + QLatin1String(">(") + QString::number(nestedArrayTypes.size()) + QLatin1Char(')'); } - if (type->typeEntry()->isContainer()) { + if (type->typeEntry()->isContainer() || type->typeEntry()->isSmartPointer()) { return convertersVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); } @@ -897,7 +898,7 @@ QString ShibokenGenerator::converterObject(const TypeEntry *type) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); } -QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType *type) +QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType *type) const { return cppApiVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); @@ -932,7 +933,7 @@ QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeN { if (typeName.isEmpty()) typeName = type->qualifiedCppName(); - if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang)) { + if (!type->generateCode()) { typeName.prepend(QLatin1Char('_')); typeName.prepend(type->targetLangPackage()); } @@ -1159,6 +1160,12 @@ bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction * return false; } +bool ShibokenGenerator::isNullPtr(const QString &value) +{ + return value == QLatin1String("0") || value == QLatin1String("nullptr") + || value == QLatin1String("NULLPTR") || value == QLatin1String("{}"); +} + QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType, bool genericNumberType) { QString customCheck; @@ -1178,10 +1185,11 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType return QLatin1String("PyObject_Check"); return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); } - if (metaType->typeEntry()->isContainer()) { + auto typeEntry = metaType->typeEntry(); + if (typeEntry->isContainer()) { QString typeCheck = QLatin1String("Shiboken::Conversions::"); - ContainerTypeEntry::Type type = - static_cast<const ContainerTypeEntry *>(metaType->typeEntry())->type(); + ContainerTypeEntry::ContainerKind type = + static_cast<const ContainerTypeEntry *>(typeEntry)->containerKind(); if (type == ContainerTypeEntry::ListContainer || type == ContainerTypeEntry::StringListContainer || type == ContainerTypeEntry::LinkedListContainer @@ -1220,7 +1228,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType *metaType } return typeCheck; } - return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); + return cpythonCheckFunction(typeEntry, genericNumberType); } QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type, bool genericNumberType) @@ -1468,6 +1476,16 @@ void ShibokenGenerator::writeFunctionArguments(QTextStream &s, } } +GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c) const +{ + GeneratorContext result = Generator::contextForClass(c); + if (shouldGenerateCppWrapper(c)) { + result.m_type = GeneratorContext::WrappedClass; + result.m_wrappername = wrapperName(c); + } + return result; +} + QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction *func, Options options) const { QString modifiedReturnType = QString(func->typeReplaced(0)); @@ -1548,19 +1566,37 @@ void ShibokenGenerator::writeFunctionCall(QTextStream &s, void ShibokenGenerator::writeUnusedVariableCast(QTextStream &s, const QString &variableName) { - s << INDENT << "SBK_UNUSED(" << variableName<< ')' << endl; + s << INDENT << "SBK_UNUSED(" << variableName<< ")\n"; +} + +static bool filterFunction(const AbstractMetaFunction *func, bool avoidProtectedHack) +{ + switch (func->functionType()) { + case AbstractMetaFunction::DestructorFunction: + case AbstractMetaFunction::SignalFunction: + case AbstractMetaFunction::GetAttroFunction: + case AbstractMetaFunction::SetAttroFunction: + return false; + default: + break; + } + if (func->usesRValueReferences()) + return false; + if (func->isModifiedRemoved() && !func->isAbstract() + && (!avoidProtectedHack || !func->isProtected())) { + return false; + } + return true; } AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass *metaClass) { AbstractMetaFunctionList result; const AbstractMetaFunctionList &funcs = metaClass->functions(); + result.reserve(funcs.size()); for (AbstractMetaFunction *func : funcs) { - if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() - || (func->isModifiedRemoved() && !func->isAbstract() - && (!avoidProtectedHack() || !func->isProtected()))) - continue; - result << func; + if (filterFunction(func, avoidProtectedHack())) + result.append(func); } return result; } @@ -1568,8 +1604,7 @@ AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaCl ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const { ExtendedConverterData extConvs; - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) { + for (const AbstractMetaClass *metaClass : classes()) { // Use only the classes for the current module. if (!shouldGenerate(metaClass)) continue; @@ -1578,8 +1613,7 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter // Get only the conversion operators that return a type from another module, // that are value-types and were not removed in the type system. const TypeEntry *convType = convOp->type()->typeEntry(); - if ((convType->codeGeneration() & TypeEntry::GenerateTargetLang) - || !convType->isValue() + if (convType->generateCode() || !convType->isValue() || convOp->isModifiedRemoved()) continue; extConvs[convType].append(convOp->ownerClass()); @@ -1645,17 +1679,24 @@ QString ShibokenGenerator::getCodeSnippets(const CodeSnipList &codeSnips, } return code; } -void ShibokenGenerator::processCodeSnip(QString &code, const AbstractMetaClass *context) + +void ShibokenGenerator::processClassCodeSnip(QString &code, const GeneratorContext &context) { - if (context) { - // Replace template variable by the Python Type object - // for the class context in which the variable is used. - code.replace(QLatin1String("%PYTHONTYPEOBJECT"), - cpythonTypeName(context) + QLatin1String("->type")); - code.replace(QLatin1String("%TYPE"), wrapperName(context)); - code.replace(QLatin1String("%CPPTYPE"), context->name()); - } + auto metaClass = context.metaClass(); + // Replace template variable by the Python Type object + // for the class context in which the variable is used. + code.replace(QLatin1String("%PYTHONTYPEOBJECT"), + cpythonTypeName(metaClass) + QLatin1String("->type")); + const QString className = context.useWrapper() + ? context.wrapperName() : metaClass->qualifiedCppName(); + code.replace(QLatin1String("%TYPE"), className); + code.replace(QLatin1String("%CPPTYPE"), metaClass->name()); + processCodeSnip(code); +} + +void ShibokenGenerator::processCodeSnip(QString &code) +{ // replace "toPython" converters replaceConvertToPythonTypeSystemVariable(code); @@ -1721,19 +1762,33 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl return argReplacements; } -void ShibokenGenerator::writeCodeSnips(QTextStream &s, +void ShibokenGenerator::writeClassCodeSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language, - const AbstractMetaClass *context) + const GeneratorContext &context) { QString code = getCodeSnippets(codeSnips, position, language); if (code.isEmpty()) return; - processCodeSnip(code, context); - s << INDENT << "// Begin code injection" << endl; + processClassCodeSnip(code, context); + s << INDENT << "// Begin code injection\n"; s << code; - s << INDENT << "// End of code injection" << endl; + s << INDENT << "// End of code injection\n\n"; +} + +void ShibokenGenerator::writeCodeSnips(QTextStream &s, + const CodeSnipList &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language) +{ + QString code = getCodeSnippets(codeSnips, position, language); + if (code.isEmpty()) + return; + processCodeSnip(code); + s << INDENT << "// Begin code injection\n"; + s << code; + s << INDENT << "// End of code injection\n\n"; } void ShibokenGenerator::writeCodeSnips(QTextStream &s, @@ -1811,7 +1866,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream &s, if (func->isConstructor()) { code.replace(QLatin1String("%0."), QLatin1String("cptr->")); code.replace(QLatin1String("%0"), QLatin1String("cptr")); - } else if (func->type()) { + } else if (!func->isVoid()) { QString returnValueOp = isPointerToWrapperType(func->type()) ? QLatin1String("%1->") : QLatin1String("%1."); if (ShibokenGenerator::isWrapperType(func->type())) @@ -1958,9 +2013,9 @@ void ShibokenGenerator::writeCodeSnips(QTextStream &s, replaceTemplateVariables(code, func); processCodeSnip(code); - s << INDENT << "// Begin code injection" << endl; + s << INDENT << "// Begin code injection\n"; s << code; - s << INDENT << "// End of code injection" << endl; + s << INDENT << "// End of code injection\n\n"; } // Returns true if the string is an expression, @@ -2054,7 +2109,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa qFatal("%s", qPrintable(msgConversionTypesDiffer(varType, conversionSignature))); c << getFullTypeName(conversionType) << ' ' << varName; writeMinimalConstructorExpression(c, conversionType); - c << ';' << endl; + c << ";\n"; Indentation indent(INDENT); c << INDENT; } @@ -2119,13 +2174,17 @@ bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction *func) return false; } -bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction *func) +bool ShibokenGenerator::injectedCodeCallsCppFunction(const GeneratorContext &context, + const AbstractMetaFunction *func) { QString funcCall = func->originalName() + QLatin1Char('('); QString wrappedCtorCall; if (func->isConstructor()) { funcCall.prepend(QLatin1String("new ")); - wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); + const auto owner = func->ownerClass(); + const QString className = context.useWrapper() + ? context.wrapperName() : owner->qualifiedCppName(); + wrappedCtorCall = QLatin1String("new ") + className + QLatin1Char('('); } CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); for (const CodeSnip &snip : qAsConst(snips)) { @@ -2182,9 +2241,40 @@ bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction *fun return false; } -bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass *metaClass) +bool ShibokenGenerator::useOverrideCaching(const AbstractMetaClass *metaClass) { - return getGeneratorClassInfo(metaClass).needsGetattroFunction; + return metaClass->isPolymorphic(); +} + +ShibokenGenerator::AttroCheck ShibokenGenerator::checkAttroFunctionNeeds(const AbstractMetaClass *metaClass) const +{ + AttroCheck result; + if (metaClass->typeEntry()->isSmartPointer()) { + result |= AttroCheckFlag::GetattroSmartPointer | AttroCheckFlag::SetattroSmartPointer; + } else { + if (getGeneratorClassInfo(metaClass).needsGetattroFunction) + result |= AttroCheckFlag::GetattroOverloads; + if (metaClass->queryFirstFunction(metaClass->functions(), + AbstractMetaClass::GetAttroFunction)) { + result |= AttroCheckFlag::GetattroUser; + } + if (usePySideExtensions() && metaClass->qualifiedCppName() == qObjectT()) + result |= AttroCheckFlag::SetattroQObject; + if (useOverrideCaching(metaClass)) + result |= AttroCheckFlag::SetattroMethodOverride; + if (metaClass->queryFirstFunction(metaClass->functions(), + AbstractMetaClass::SetAttroFunction)) { + result |= AttroCheckFlag::SetattroUser; + } + // PYSIDE-1255: If setattro is generated for a class inheriting + // QObject, the property code needs to be generated, too. + if ((result & AttroCheckFlag::SetattroMask) != 0 + && !result.testFlag(AttroCheckFlag::SetattroQObject) + && metaClass->isQObject()) { + result |= AttroCheckFlag::SetattroQObject; + } + } + return result; } bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass) @@ -2211,13 +2301,6 @@ bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass * return false; } -bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *metaClass) -{ - if (!metaClass) - return false; - return metaClass->typeEntry()->isSmartPointer(); -} - AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass *metaClass) { AbstractMetaFunctionList methods; @@ -2327,8 +2410,7 @@ AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const Ty typeName.remove(0, 2); if (m_metaTypeFromStringCache.contains(typeName)) return m_metaTypeFromStringCache.value(typeName); - auto *metaType = new AbstractMetaType; - metaType->setTypeEntry(typeEntry); + auto *metaType = new AbstractMetaType(typeEntry); metaType->clearIndirections(); metaType->setReferenceType(NoReference); metaType->setConstant(false); @@ -2360,22 +2442,38 @@ static void dumpFunction(AbstractMetaFunctionList lst) static bool isGroupable(const AbstractMetaFunction *func) { - if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract())) + switch (func->functionType()) { + case AbstractMetaFunction::DestructorFunction: + case AbstractMetaFunction::SignalFunction: + case AbstractMetaFunction::GetAttroFunction: + case AbstractMetaFunction::SetAttroFunction: + return false; + default: + break; + } + if (func->isModifiedRemoved() && !func->isAbstract()) return false; // weird operator overloads if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? - return false;; + return false; return true; } -ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const +static void insertIntoFunctionGroups(const AbstractMetaFunctionList &lst, + ShibokenGenerator::FunctionGroups *results) { - const AbstractMetaFunctionList &lst = globalFunctions(); - FunctionGroups results; for (AbstractMetaFunction *func : lst) { if (isGroupable(func)) - results[func->name()].append(func); + (*results)[func->name()].append(func); } +} + +ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const +{ + FunctionGroups results; + insertIntoFunctionGroups(globalFunctions(), &results); + for (auto nsp : invisibleTopNamespaces()) + insertIntoFunctionGroups(nsp->functions(), &results); return results; } @@ -2399,7 +2497,8 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const Abs ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope) { - const AbstractMetaFunctionList &lst = scope->functions(); + AbstractMetaFunctionList lst = scope->functions(); + scope->getFunctionsFromInvisibleNamespacesToBeGenerated(&lst); FunctionGroups results; for (AbstractMetaFunction *func : lst) { @@ -2484,7 +2583,9 @@ Generator::OptionDescriptions ShibokenGenerator::options() const "(USE WITH CAUTION!)")) << qMakePair(QLatin1String(USE_ISNULL_AS_NB_NONZERO), QLatin1String("If a class have an isNull() const method, it will be used to compute\n" - "the value of boolean casts")); + "the value of boolean casts")) + << qMakePair(QLatin1String(WRAPPER_DIAGNOSTICS), + QLatin1String("Generate diagnostic code around wrappers")); } bool ShibokenGenerator::handleOption(const QString &key, const QString & /* value */) @@ -2501,6 +2602,8 @@ bool ShibokenGenerator::handleOption(const QString &key, const QString & /* valu return (m_useIsNullAsNbNonZero = true); if (key == QLatin1String(AVOID_PROTECTED_HACK)) return (m_avoidProtectedHack = true); + if (key == QLatin1String(WRAPPER_DIAGNOSTICS)) + return (m_wrapperDiagnostics = true); return false; } @@ -2538,8 +2641,7 @@ bool ShibokenGenerator::doSetup() const ContainerTypeEntryList &containerTypeList = containerTypes(); for (const ContainerTypeEntry *type : containerTypeList) getCode(snips, type); - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) + for (const AbstractMetaClass *metaClass : classes()) getCode(snips, metaClass->typeEntry()); const TypeSystemTypeEntry *moduleEntry = TypeDatabase::instance()->defaultTypeSystemType(); @@ -2565,13 +2667,19 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString & QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP["); int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); int start = 0; + QString errorMessage; while ((start = code.indexOf(convMacro, start)) != -1) { int end = code.indexOf(QLatin1Char(']'), start); start += offset; if (code.at(start) != QLatin1Char('%')) { QString typeString = code.mid(start, end - start); - AbstractMetaType *type = buildAbstractMetaTypeFromString(typeString); - addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + if (AbstractMetaType *type = + buildAbstractMetaTypeFromString(typeString, &errorMessage)) { + addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + } else { + qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__, + qPrintable(typeString), qPrintable(errorMessage)); + } } start = end; } @@ -2632,8 +2740,7 @@ QString ShibokenGenerator::convertersVariableName(const QString &moduleName) con static QString processInstantiationsVariableName(const AbstractMetaType *type) { QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper(); - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) { + for (const auto *instantiation : type->instantiations()) { res += instantiation->isContainer() ? processInstantiationsVariableName(instantiation) : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper(); @@ -2648,7 +2755,8 @@ static void appendIndexSuffix(QString *s) s->append(QStringLiteral("IDX")); } -QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *metaClass, bool alternativeTemplateName) +QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *metaClass, + bool alternativeTemplateName) const { if (alternativeTemplateName) { const AbstractMetaClass *templateBaseClass = metaClass->templateBaseClass(); @@ -2656,15 +2764,14 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass *met return QString(); QString result = QLatin1String("SBK_") + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); - const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); - for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) + for (const auto *instantiation : metaClass->templateBaseClassInstantiations()) result += processInstantiationsVariableName(instantiation); appendIndexSuffix(&result); return result; } return getTypeIndexVariableName(metaClass->typeEntry()); } -QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type) +QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type) const { if (type->isCppPrimitive()) { const auto *trueType = static_cast<const PrimitiveTypeEntry *>(type); @@ -2682,7 +2789,7 @@ QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry *type) appendIndexSuffix(&result); return result; } -QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType *type) +QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType *type) const { QString result = QLatin1String("SBK"); if (type->typeEntry()->isContainer()) @@ -2743,7 +2850,7 @@ void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream &s, const } else { const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); qCWarning(lcShiboken()).noquote() << message; - s << ";\n#error " << message << endl; + s << ";\n#error " << message << Qt::endl; } } |