diff options
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/shibokengenerator.cpp')
-rw-r--r-- | sources/shiboken2/generator/shiboken2/shibokengenerator.cpp | 451 |
1 files changed, 208 insertions, 243 deletions
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 80096cbf2..b9eea7529 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -28,9 +28,11 @@ #include "shibokengenerator.h" #include <abstractmetalang.h> +#include <messages.h> #include "overloaddata.h" #include <reporthandler.h> #include <typedatabase.h> +#include <abstractmetabuilder.h> #include <iostream> #include <QtCore/QDir> @@ -39,13 +41,29 @@ #include <limits> #include <memory> -#define NULL_VALUE "NULL" -#define AVOID_PROTECTED_HACK "avoid-protected-hack" -#define PARENT_CTOR_HEURISTIC "enable-parent-ctor-heuristic" -#define RETURN_VALUE_HEURISTIC "enable-return-value-heuristic" -#define ENABLE_PYSIDE_EXTENSIONS "enable-pyside-extensions" -#define DISABLE_VERBOSE_ERROR_MESSAGES "disable-verbose-error-messages" -#define USE_ISNULL_AS_NB_NONZERO "use-isnull-as-nb_nonzero" +static const char NULL_VALUE[] = "NULL"; +static const char AVOID_PROTECTED_HACK[] = "avoid-protected-hack"; +static const char PARENT_CTOR_HEURISTIC[] = "enable-parent-ctor-heuristic"; +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"; + +const char *CPP_ARG = "cppArg"; +const char *CPP_ARG_REMOVED = "removed_cppArg"; +const char *CPP_RETURN_VAR = "cppResult"; +const char *CPP_SELF_VAR = "cppSelf"; +const char *PYTHON_ARG = "pyArg"; +const char *PYTHON_ARGS = "pyArgs"; +const char *PYTHON_OVERRIDE_VAR = "pyOverride"; +const char *PYTHON_RETURN_VAR = "pyResult"; +const char *PYTHON_TO_CPP_VAR = "pythonToCpp"; +const char *SMART_POINTER_GETTER = "kSmartPointerGetter"; + +const char *CONV_RULE_OUT_VAR_SUFFIX = "_out"; +const char *BEGIN_ALLOW_THREADS = + "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS"; +const char *END_ALLOW_THREADS = "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS"; //static void dumpFunction(AbstractMetaFunctionList lst); @@ -100,7 +118,7 @@ static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum, return resolveScopePrefix(parts, value); } -ShibokenGenerator::ShibokenGenerator() : Generator() +ShibokenGenerator::ShibokenGenerator() { if (m_pythonPrimitiveTypeName.isEmpty()) ShibokenGenerator::initPrimitiveTypesCorrespondences(); @@ -117,17 +135,19 @@ ShibokenGenerator::ShibokenGenerator() : Generator() m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible"); m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp"); m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython"); + + const char CHECKTYPE_REGEX[] = R"(%CHECKTYPE\[([^\[]*)\]\()"; + const char ISCONVERTIBLE_REGEX[] = R"(%ISCONVERTIBLE\[([^\[]*)\]\()"; + const char CONVERTTOPYTHON_REGEX[] = R"(%CONVERTTOPYTHON\[([^\[]*)\]\()"; + const char CONVERTTOCPP_REGEX[] = + R"((\*?%?[a-zA-Z_][\w\.]*(?:\[[^\[^<^>]+\])*)(?:\s+)=(?:\s+)%CONVERTTOCPP\[([^\[]*)\]\()"; m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX)); m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX)); m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX)); m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX)); } -ShibokenGenerator::~ShibokenGenerator() -{ - // TODO-CONVERTER: it must be caching types that were not created here. - //qDeleteAll(m_metaTypeFromStringCache.values()); -} +ShibokenGenerator::~ShibokenGenerator() = default; void ShibokenGenerator::clearTpFuncs() { @@ -277,7 +297,7 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaCl for (const AbstractMetaFunction *func : funcs) { if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved()) continue; - else if (func->isOperatorOverload()) + if (func->isOperatorOverload()) protectedOperators++; else protectedFunctions++; @@ -332,9 +352,8 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const result += QLatin1String("Wrapper"); return result; - } else { - return metaClass->qualifiedCppName(); } + return metaClass->qualifiedCppName(); } QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const @@ -342,7 +361,19 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const return metaType->cppSignature(); } -QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func) +QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClass) +{ + QString fullClassName = metaClass->name(); + const AbstractMetaClass *enclosing = metaClass->enclosingClass(); + while (enclosing) { + fullClassName.prepend(enclosing->name() + QLatin1Char('.')); + enclosing = enclosing->enclosingClass(); + } + fullClassName.prepend(packageName() + QLatin1Char('.')); + return fullClassName; +} + +QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func) //WS { QString funcName; if (func->isOperatorOverload()) @@ -350,11 +381,11 @@ QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* fu else funcName = func->name(); if (func->ownerClass()) { - QString fullName = func->ownerClass()->fullName(); + QString fullClassName = fullPythonClassName(func->ownerClass()); if (func->isConstructor()) - funcName = fullName; + funcName = fullClassName; else - funcName.prepend(fullName + QLatin1Char('.')); + funcName.prepend(fullClassName + QLatin1Char('.')); } else { funcName = packageName() + QLatin1Char('.') + func->name(); @@ -434,7 +465,8 @@ QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField* me return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); } -static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName) +static QString cpythonEnumFlagsName(const QString &moduleName, + const QString &qualifiedCppName) { QString result = QStringLiteral("Sbk%1_%2").arg(moduleName, qualifiedCppName); result.replace(QLatin1String("::"), QLatin1String("_")); @@ -570,7 +602,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction fieldName.prepend(prefix); prefix.clear(); } else { - fieldName.prepend(QLatin1String(CPP_SELF_VAR "->")); + fieldName.prepend(QLatin1String(CPP_SELF_VAR) + QLatin1String("->")); } value.replace(match.captured(1), fieldName); break; @@ -616,12 +648,14 @@ QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClas return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction"); } -QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName) +QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, + const QString &argName) { return cpythonWrapperCPtr(metaClass->typeEntry(), argName); } -QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName) +QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, + const QString &argName) { if (!ShibokenGenerator::isWrapperType(metaType->typeEntry())) return QString(); @@ -630,7 +664,8 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, + QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))"); } -QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName) +QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, + const QString &argName) { if (!ShibokenGenerator::isWrapperType(type)) return QString(); @@ -706,7 +741,8 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, || arg->type()->referenceType() == LValueReference) { result += QLatin1Char(objType); } else if (arg->type()->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); + const PrimitiveTypeEntry *ptype = + static_cast<const PrimitiveTypeEntry *>(arg->type()->typeEntry()); if (ptype->basicReferencedTypeEntry()) ptype = ptype->basicReferencedTypeEntry(); if (m_formatUnits.contains(ptype->name())) @@ -745,7 +781,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && type->referenceType() == NoReference) { baseName = QLatin1String("Sbk_") + type->name(); } else if (type->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *ptype = static_cast<const PrimitiveTypeEntry *>(type); while (ptype->basicReferencedTypeEntry()) ptype = ptype->basicReferencedTypeEntry(); if (ptype->targetLangApiName() == ptype->name()) @@ -753,11 +789,11 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) else baseName = ptype->targetLangApiName(); } else if (type->isEnum()) { - baseName = cpythonEnumName((const EnumTypeEntry*) type); + baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type)); } else if (type->isFlags()) { - baseName = cpythonFlagsName((const FlagsTypeEntry*) type); + baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type)); } else if (type->isContainer()) { - const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type; + const ContainerTypeEntry *ctype = static_cast<const ContainerTypeEntry *>(type); switch (ctype->type()) { case ContainerTypeEntry::ListContainer: case ContainerTypeEntry::StringListContainer: @@ -858,14 +894,6 @@ QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type) + getTypeIndexVariableName(type) + QLatin1Char(']'); } -static QString msgUnknownOperator(const AbstractMetaFunction* func) -{ - QString result = QLatin1String("Unknown operator: \"") + func->originalName() + QLatin1Char('"'); - if (const AbstractMetaClass *c = func->implementingClass()) - result += QLatin1String(" in class: ") + c->name(); - return result; -} - static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); } QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative) @@ -925,7 +953,7 @@ QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* typ return pythonPrimitiveTypeName(type->name()); } -QString ShibokenGenerator::pythonOperatorFunctionName(QString cppOpFuncName) +QString ShibokenGenerator::pythonOperatorFunctionName(const QString &cppOpFuncName) { QString value = m_pythonOperators.value(cppOpFuncName); if (value.isEmpty()) @@ -953,7 +981,7 @@ QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction return op; } -QString ShibokenGenerator::pythonRichCompareOperatorId(QString cppOpFuncName) +QString ShibokenGenerator::pythonRichCompareOperatorId(const QString &cppOpFuncName) { return QLatin1String("Py_") + m_pythonOperators.value(cppOpFuncName).toUpper(); } @@ -963,7 +991,7 @@ QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunctio return pythonRichCompareOperatorId(func->originalName()); } -bool ShibokenGenerator::isNumber(QString cpythonApiName) +bool ShibokenGenerator::isNumber(const QString &cpythonApiName) { return cpythonApiName == QLatin1String("PyInt") || cpythonApiName == QLatin1String("PyFloat") @@ -975,7 +1003,7 @@ bool ShibokenGenerator::isNumber(const TypeEntry* type) { if (!type->isPrimitive()) return false; - return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type)); + return isNumber(pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))); } bool ShibokenGenerator::isNumber(const AbstractMetaType* type) @@ -987,7 +1015,8 @@ bool ShibokenGenerator::isPyInt(const TypeEntry* type) { if (!type->isPrimitive()) return false; - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == QLatin1String("PyInt"); + return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)) + == QLatin1String("PyInt"); } bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) @@ -998,7 +1027,7 @@ bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) bool ShibokenGenerator::isWrapperType(const TypeEntry* type) { if (type->isComplex()) - return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type); + return ShibokenGenerator::isWrapperType(static_cast<const ComplexTypeEntry *>(type)); return type->isObject() || type->isValue() || type->isSmartPointer(); } bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type) @@ -1052,7 +1081,7 @@ bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type) { if (!type->isPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); return trueType->isPrimitive() && !trueType->isCppPrimitive() @@ -1072,7 +1101,7 @@ bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type) return true; if (!type->isPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); return trueType->qualifiedCppName() == QLatin1String("std::string"); @@ -1125,9 +1154,11 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType if (isVoidPointer(metaType)) return QLatin1String("PyObject_Check"); return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); - } else if (metaType->typeEntry()->isContainer()) { + } + if (metaType->typeEntry()->isContainer()) { QString typeCheck = QLatin1String("Shiboken::Conversions::"); - ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type(); + ContainerTypeEntry::Type type = + static_cast<const ContainerTypeEntry *>(metaType->typeEntry())->type(); if (type == ContainerTypeEntry::ListContainer || type == ContainerTypeEntry::StringListContainer || type == ContainerTypeEntry::LinkedListContainer @@ -1154,8 +1185,8 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType const AbstractMetaType* firstType = metaType->instantiations().constFirst(); const AbstractMetaType* secondType = metaType->instantiations().constLast(); if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) { - typeCheck += QString::fromLatin1("check%1Types(%2, %3, ").arg(pyType) - .arg(cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType)); + typeCheck += QString::fromLatin1("check%1Types(%2, %3, ") + .arg(pyType, cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType)); } else { typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ") .arg(pyType, converterObject(firstType), @@ -1182,8 +1213,10 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool gene if (type->isEnum() || type->isFlags() || isWrapperType(type)) return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type)); - else if (isCppPrimitive(type)) - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type) + QLatin1String("_Check"); + if (isCppPrimitive(type)) { + return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)) + + QLatin1String("_Check"); + } QString typeCheck; if (type->targetLangApiName() == type->name()) typeCheck = cpythonIsConvertibleFunction(type); @@ -1392,7 +1425,7 @@ void ShibokenGenerator::writeFunctionArguments(QTextStream &s, if (options & Generator::WriteSelf) { s << func->implementingClass()->name() << '&'; if (!(options & SkipName)) - s << " " PYTHON_SELF_VAR; + s << " self"; } int argUsed = 0; @@ -1412,13 +1445,12 @@ QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, QString modifiedReturnType = QString(func->typeReplaced(0)); if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription)) return modifiedReturnType; - else - return translateType(func->type(), func->implementingClass(), options); + return translateType(func->type(), func->implementingClass(), options); } QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, - QString prepend, - QString append, + const QString &prepend, + const QString &append, Options options, int /* argCount */) const { @@ -1619,8 +1651,9 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl QString argValue; if (language == TypeSystem::TargetLangCode) { bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty(); - bool argRemoved = func->argumentRemoved(i+1); - removed = removed + (int) argRemoved; + const bool argRemoved = func->argumentRemoved(i+1); + if (argRemoved) + ++removed; if (argRemoved && hasConversionRule) argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex())) @@ -1636,8 +1669,7 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl } if (type->typeEntry()->isCustom()) { argValue = usePyArgs - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) - : QLatin1String(PYTHON_ARG); + ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG); } else { argValue = hasConversionRule ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX) @@ -1673,17 +1705,6 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, s << INDENT << "// End of code injection" << endl; } -static QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func) -{ - QString result; - QTextStream str(&result); - str << "Wrong index for " << varName << " variable (" << capture << ") on "; - if (const AbstractMetaClass *c = func->implementingClass()) - str << c->name() << "::"; - str << func->signature(); - return result; -} - void ShibokenGenerator::writeCodeSnips(QTextStream& s, const CodeSnipList& codeSnips, TypeSystem::CodeSnipPosition position, @@ -1712,7 +1733,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, Q_ASSERT(pyArgsRegex.isValid()); if (language == TypeSystem::TargetLangCode) { if (usePyArgs) { - code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]")); + code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS) + QLatin1String("[\\1-1]")); } else { static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)")); Q_ASSERT(pyArgsRegexCheck.isValid()); @@ -1729,8 +1750,10 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // Python argument on the binding virtual method. static const QRegularExpression pyArgsAttributionRegex(QStringLiteral("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)")); Q_ASSERT(pyArgsAttributionRegex.isValid()); - code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)")); - code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)")); + code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(") + + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1, \\2)")); + code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(") + + QLatin1String(PYTHON_ARGS) + QLatin1String(", \\1-1)")); } // Replace %ARG#_TYPE variables. @@ -1763,7 +1786,8 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, } // Replace template variable for self Python object. - QString pySelf = (language == TypeSystem::NativeCode) ? QLatin1String("pySelf") : QLatin1String(PYTHON_SELF_VAR); + QString pySelf = language == TypeSystem::NativeCode + ? QLatin1String("pySelf") : QLatin1String("self"); code.replace(QLatin1String("%PYSELF"), pySelf); // Replace template variable for a pointer to C++ of this object. @@ -1960,16 +1984,6 @@ static QString getConverterTypeSystemVariableArgument(const QString& code, int p } typedef QPair<QString, QString> StringPair; -static QString msgCannotFindType(const QString &type, const QString &variable, - const QString &why) -{ - QString result; - QTextStream(&result) << "Could not find type '" - << type << "' for use in '" << variable << "' conversion: " << why - << "\nMake sure to use the full C++ name, e.g. 'Namespace::Class'."; - return result; -} - void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code) { QVector<StringPair> replacements; @@ -1978,7 +1992,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa const QRegularExpressionMatch match = rit.next(); const QStringList list = match.capturedTexts(); QString conversionString = list.constFirst(); - QString conversionTypeName = list.constLast(); + const QString &conversionTypeName = list.constLast(); QString message; const AbstractMetaType *conversionType = buildAbstractMetaTypeFromString(conversionTypeName, &message); if (!conversionType) { @@ -2002,8 +2016,8 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa QString varName = list.at(1).trimmed(); if (!varType.isEmpty()) { if (varType != conversionType->cppSignature()) { - qFatal(qPrintable(QString::fromLatin1("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.") - .arg(varType, conversionType->cppSignature())), NULL); + qFatal("Types of receiver variable ('%s') and %%CONVERTTOCPP type system variable ('%s') differ.", + qPrintable(varType), qPrintable(conversionType->cppSignature())); } c << getFullTypeName(conversionType) << ' ' << varName; writeMinimalConstructorExpression(c, conversionType); @@ -2032,18 +2046,21 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa c << '('; break; } + Q_FALLTHROUGH(); case TypeSystemIsConvertibleFunction: if (conversion.isEmpty()) conversion = cpythonIsConvertibleFunction(conversionType); + Q_FALLTHROUGH(); case TypeSystemToPythonFunction: if (conversion.isEmpty()) conversion = cpythonToPythonConversionFunction(conversionType); + Q_FALLTHROUGH(); default: { QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); conversionString += arg; if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) { - qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'") - .arg(code)), NULL); + qFatal("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%s'", + qPrintable(code)); } if (conversion.contains(QLatin1String("%in"))) { conversion.prepend(QLatin1Char('(')); @@ -2172,9 +2189,7 @@ bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *meta { if (!metaClass) return false; - if (metaClass->typeEntry()->isSmartPointer()) - return true; - return false; + return metaClass->typeEntry()->isSmartPointer(); } AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass) @@ -2244,9 +2259,7 @@ AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) const { - QString result = moduleName.isEmpty() ? packageName() : moduleName; - result.replace(QLatin1Char('.'), QLatin1Char('_')); - return result.toLower() + QLatin1String("_python.h"); + return moduleCppPrefix(moduleName).toLower() + QLatin1String("_python.h"); } bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) @@ -2254,12 +2267,10 @@ bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) { if (metaClass->isNamespace() || isObjectType(metaClass)) return false; - else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) + if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) return metaClass->hasCloneOperator(); - else - return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet); - return false; + return metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet; } AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature, @@ -2269,110 +2280,18 @@ AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typ if (typeSignature.startsWith(QLatin1String("::"))) typeSignature.remove(0, 2); - if (m_metaTypeFromStringCache.contains(typeSignature)) - return m_metaTypeFromStringCache.value(typeSignature); - - QString typeString = typeSignature; - bool isConst = typeString.startsWith(QLatin1String("const ")); - if (isConst) - typeString.remove(0, sizeof("const ") / sizeof(char) - 1); - - ReferenceType refType = NoReference; - if (typeString.endsWith(QLatin1String("&&"))) { - refType = RValueReference; - typeString.chop(2); - typeString = typeString.trimmed(); - } else if (typeString.endsWith(QLatin1Char('&'))) { - refType = LValueReference; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - int indirections = 0; - while (typeString.endsWith(QLatin1Char('*'))) { - ++indirections; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - if (typeString.startsWith(QLatin1String("::"))) - typeString.remove(0, 2); - - QString adjustedTypeName = typeString; - AbstractMetaTypeList instantiations; - int lpos = typeString.indexOf(QLatin1Char('<')); - if (lpos > -1) { - QStringList instantiatedTypes; - int rpos = typeString.lastIndexOf(QLatin1Char('>')); - if ((lpos != -1) && (rpos != -1)) { - QString type = typeString.mid(lpos + 1, rpos - lpos - 1); - int depth = 0; - int start = 0; - for (int i = 0; i < type.count(); ++i) { - if (type.at(i) == QLatin1Char('<')) { - ++depth; - } else if (type.at(i) == QLatin1Char('>')) { - --depth; - } else if (type.at(i) == QLatin1Char(',') && depth == 0) { - instantiatedTypes << type.mid(start, i - start).trimmed(); - start = i + 1; - } - } - instantiatedTypes << type.mid(start).trimmed(); - adjustedTypeName.truncate(lpos); - } - for (const QString &instantiatedType : qAsConst(instantiatedTypes)) { - AbstractMetaType *tmplArgType = buildAbstractMetaTypeFromString(instantiatedType); - if (!tmplArgType) { - if (errorMessage) { - QTextStream(errorMessage) << "Cannot find template type \"" - << instantiatedType << "\" for \"" << typeSignature << "\"."; - } - return nullptr; - } - instantiations.append(tmplArgType); - } - } - - TypeEntry *typeEntry = nullptr; - AbstractMetaType::TypeUsagePattern pattern = AbstractMetaType::InvalidPattern; - - if (instantiations.size() == 1 - && instantiations.at(0)->typeUsagePattern() == AbstractMetaType::EnumPattern - && adjustedTypeName == QLatin1String("QFlags")) { - pattern = AbstractMetaType::FlagsPattern; - typeEntry = TypeDatabase::instance()->findType(typeSignature); - } else { - typeEntry = TypeDatabase::instance()->findType(adjustedTypeName); - } - - if (!typeEntry) { - if (errorMessage) { - QTextStream(errorMessage) << "Cannot find type \"" << adjustedTypeName - << "\" for \"" << typeSignature << "\"."; + auto it = m_metaTypeFromStringCache.find(typeSignature); + if (it == m_metaTypeFromStringCache.end()) { + AbstractMetaType *metaType = + AbstractMetaBuilder::translateType(typeSignature, nullptr, true, errorMessage); + if (Q_UNLIKELY(!metaType)) { + if (errorMessage) + errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); + return nullptr; } - return nullptr; + it = m_metaTypeFromStringCache.insert(typeSignature, metaType); } - - AbstractMetaType *metaType = new AbstractMetaType(); - metaType->setTypeEntry(typeEntry); - metaType->setIndirections(indirections); - metaType->setReferenceType(refType); - metaType->setConstant(isConst); - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - switch (pattern) { - case AbstractMetaType::FlagsPattern: - metaType->setTypeUsagePattern(pattern); - break; - default: - metaType->setInstantiations(instantiations); - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - metaType->decideUsagePattern(); - break; - } - - m_metaTypeFromStringCache.insert(typeSignature, metaType); - return metaType; + return it.value(); } AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry) @@ -2384,7 +2303,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const Ty return m_metaTypeFromStringCache.value(typeName); AbstractMetaType* metaType = new AbstractMetaType; metaType->setTypeEntry(typeEntry); - metaType->setIndirections(0); + metaType->clearIndirections(); metaType->setReferenceType(NoReference); metaType->setConstant(false); metaType->decideUsagePattern(); @@ -2449,7 +2368,7 @@ AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const Abstract { AbstractMetaFunctionList results; AbstractMetaClass* basis; - if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) { + if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) { for (; basis; basis = basis->baseClass()) { const AbstractMetaFunction* inFunc = basis->findFunction(func->name()); if (inFunc && !seen->contains(inFunc->minimalSignature())) { @@ -2509,6 +2428,23 @@ Generator::OptionDescriptions ShibokenGenerator::options() const "the value of boolean casts")); } +bool ShibokenGenerator::handleOption(const QString &key, const QString & /* value */) +{ + if (key == QLatin1String(PARENT_CTOR_HEURISTIC)) + return (m_useCtorHeuristic = true); + if (key == QLatin1String(ENABLE_PYSIDE_EXTENSIONS)) + return (m_usePySideExtensions = true); + if (key == QLatin1String(RETURN_VALUE_HEURISTIC)) + return (m_userReturnValueHeuristic = true); + if (key == QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES)) + return (m_verboseErrorMessagesDisabled = true); + if (key == QLatin1String(USE_ISNULL_AS_NB_NONZERO)) + return (m_useIsNullAsNbNonZero = true); + if (key == QLatin1String(AVOID_PROTECTED_HACK)) + return (m_avoidProtectedHack = true); + return false; +} + static void getCode(QStringList& code, const CodeSnipList& codeSnips) { for (const CodeSnip &snip : qAsConst(codeSnips)) @@ -2534,15 +2470,8 @@ static void getCode(QStringList& code, const TypeEntry* type) code.append(toNative->conversion()); } -bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args) +bool ShibokenGenerator::doSetup() { - m_useCtorHeuristic = args.contains(QLatin1String(PARENT_CTOR_HEURISTIC)); - m_usePySideExtensions = args.contains(QLatin1String(ENABLE_PYSIDE_EXTENSIONS)); - m_userReturnValueHeuristic = args.contains(QLatin1String(RETURN_VALUE_HEURISTIC)); - m_verboseErrorMessagesDisabled = args.contains(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES)); - m_useIsNullAsNbNonZero = args.contains(QLatin1String(USE_ISNULL_AS_NB_NONZERO)); - m_avoidProtectedHack = args.contains(QLatin1String(AVOID_PROTECTED_HACK)); - TypeDatabase* td = TypeDatabase::instance(); QStringList snips; const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); @@ -2554,7 +2483,11 @@ bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args) const AbstractMetaClassList &classList = classes(); for (const AbstractMetaClass *metaClass : classList) getCode(snips, metaClass->typeEntry()); - getCode(snips, td->findType(packageName())); + + const TypeSystemTypeEntry *moduleEntry = td->findTypeSystemType(packageName()); + Q_ASSERT(moduleEntry); + getCode(snips, moduleEntry); + const FunctionGroupMap &functionGroups = getFunctionGroups(); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { for (AbstractMetaFunction *func : it.value()) @@ -2611,15 +2544,25 @@ bool ShibokenGenerator::avoidProtectedHack() const return m_avoidProtectedHack; } -QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const -{ - QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName; +QString ShibokenGenerator::moduleCppPrefix(const QString& moduleName) const + { + QString result = moduleName.isEmpty() ? packageName() : moduleName; result.replace(QLatin1Char('.'), QLatin1Char('_')); - result.prepend(QLatin1String("Sbk")); - result.append(QLatin1String("Types")); return result; } +QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const +{ + return QLatin1String("Sbk") + moduleCppPrefix(moduleName) + + QLatin1String("Types"); +} + +QString ShibokenGenerator::pythonModuleObjectName(const QString& moduleName) const +{ + return QLatin1String("Sbk") + moduleCppPrefix(moduleName) + + QLatin1String("ModuleObject"); +} + QString ShibokenGenerator::convertersVariableName(const QString& moduleName) const { QString result = cppApiVariableName(moduleName); @@ -2639,35 +2582,50 @@ static QString processInstantiationsVariableName(const AbstractMetaType* type) } return res; } + +static void appendIndexSuffix(QString *s) +{ + if (!s->endsWith(QLatin1Char('_'))) + s->append(QLatin1Char('_')); + s->append(QStringLiteral("IDX")); +} + QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName) { if (alternativeTemplateName) { const AbstractMetaClass* templateBaseClass = metaClass->templateBaseClass(); if (!templateBaseClass) return QString(); - QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); - QString instantiations; + QString result = QLatin1String("SBK_") + + _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) - instantiations += processInstantiationsVariableName(instantiation); - return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations); + result += processInstantiationsVariableName(instantiation); + appendIndexSuffix(&result); + return result; } return getTypeIndexVariableName(metaClass->typeEntry()); } QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type) { if (type->isCppPrimitive()) { - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry*>(type); if (trueType->basicReferencedTypeEntry()) type = trueType->basicReferencedTypeEntry(); } - return QString::fromLatin1("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper()); + QString result = QLatin1String("SBK_") + + _fixedCppTypeName(type->qualifiedCppName()).toUpper(); + appendIndexSuffix(&result); + return result; } QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type) { - return QString::fromLatin1("SBK%1%2_IDX") - .arg(type->typeEntry()->isContainer() ? QLatin1Char('_') + moduleName().toUpper() : QString(), - processInstantiationsVariableName(type)); + QString result = QLatin1String("SBK"); + if (type->typeEntry()->isContainer()) + result += QLatin1Char('_') + moduleName().toUpper(); + result += processInstantiationsVariableName(type); + appendIndexSuffix(&result); + return result; } bool ShibokenGenerator::verboseErrorMessagesDisabled() const @@ -2707,30 +2665,37 @@ QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, co void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor) { - if (defaultCtor.isEmpty() && isCppPrimitive(type)) + if (!defaultCtor.isEmpty()) { + s << " = " << defaultCtor; + return; + } + if (isCppPrimitive(type)) return; - QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; - if (ctor.isEmpty()) { + const auto ctor = minimalConstructor(type); + if (ctor.isValid()) { + s << ctor.initialization(); + } else { const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->cppSignature()); qCWarning(lcShiboken()).noquote() << message; s << ";\n#error " << message << '\n'; - } else { - s << " = " << ctor; } } void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor) { - if (defaultCtor.isEmpty() && isCppPrimitive(type)) + if (!defaultCtor.isEmpty()) { + s << " = " << defaultCtor; + return; + } + if (isCppPrimitive(type)) return; - QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; - - if (ctor.isEmpty()) { + const auto ctor = minimalConstructor(type); + if (ctor.isValid()) { + s << ctor.initialization(); + } else { const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); qCWarning(lcShiboken()).noquote() << message; s << ";\n#error " << message << endl; - } else { - s << " = " << ctor; } } @@ -2738,7 +2703,7 @@ bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type) { if (!type->isCppPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); QString typeName = trueType->qualifiedCppName(); @@ -2751,8 +2716,8 @@ bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type) return isCppIntegralPrimitive(type->typeEntry()); } -QString ShibokenGenerator::msgCouldNotFindMinimalConstructor(const QString &where, const QString &type) +QString ShibokenGenerator::pythonArgsAt(int i) { - return where + QLatin1String(": Could not find a minimal constructor for type '") + type - + QLatin1String("'. This will result in a compilation error."); + return QLatin1String(PYTHON_ARGS) + QLatin1Char('[') + + QString::number(i) + QLatin1Char(']'); } |