diff options
Diffstat (limited to 'sources/shiboken2/generator/shiboken2/shibokengenerator.cpp')
-rw-r--r-- | sources/shiboken2/generator/shiboken2/shibokengenerator.cpp | 364 |
1 files changed, 219 insertions, 145 deletions
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 670659854..530d9b143 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -35,6 +35,7 @@ #include <QtCore/QDir> #include <QtCore/QDebug> +#include <QtCore/QRegularExpression> #include <limits> #include <memory> @@ -54,6 +55,11 @@ QHash<QString, QString> ShibokenGenerator::m_formatUnits = QHash<QString, QStrin QHash<QString, QString> ShibokenGenerator::m_tpFuncs = QHash<QString, QString>(); QStringList ShibokenGenerator::m_knownPythonTypes = QStringList(); +static QRegularExpression placeHolderRegex(int index) +{ + return QRegularExpression(QLatin1Char('%') + QString::number(index) + QStringLiteral("\\b")); +} + static QString resolveScopePrefix(const AbstractMetaClass* scope, const QString& value) { if (!scope) @@ -87,10 +93,10 @@ ShibokenGenerator::ShibokenGenerator() : Generator() m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible"); m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp"); m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython"); - m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegExp(QLatin1String(CHECKTYPE_REGEX)); - m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegExp(QLatin1String(ISCONVERTIBLE_REGEX)); - m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegExp(QLatin1String(CONVERTTOPYTHON_REGEX)); - m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp(QLatin1String(CONVERTTOCPP_REGEX)); + 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() @@ -115,36 +121,34 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences() // PyBool m_pythonPrimitiveTypeName.insert(QLatin1String("bool"), QLatin1String("PyBool")); + const char *charTypes[] = { + "char", "signed char", "unsigned char" + }; + for (const char *charType : charTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(charType), QStringLiteral("SbkChar")); + // PyInt - m_pythonPrimitiveTypeName.insert(QLatin1String("char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("uint"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ushort"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long"), QLatin1String("PyInt")); + const char *intTypes[] = { + "int", "signed int", "uint", "unsigned int", + "short", "ushort", "signed short", "signed short int", + "unsigned short", "unsigned short", "unsigned short int", + "long" + }; + for (const char *intType : intTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(intType), QStringLiteral("PyInt")); // PyFloat m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat")); m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat")); // PyLong - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ulong"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long int"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("__int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned __int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("size_t"), QLatin1String("PyLong")); + const char *longTypes[] = { + "unsigned long", "signed long", "ulong", "unsigned long int", + "long long", "__int64", + "unsigned long long", "unsigned __int64", "size_t" + }; + for (const char *longType : longTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(longType), QStringLiteral("PyLong")); // Python operators m_pythonOperators.clear(); @@ -243,7 +247,8 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaCl if (!result && metaClass->hasProtectedFunctions()) { int protectedFunctions = 0; int protectedOperators = 0; - foreach (const AbstractMetaFunction* func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (const AbstractMetaFunction *func : funcs) { if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved()) continue; else if (func->isOperatorOverload()) @@ -265,7 +270,8 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi return; if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) continue; if (!enumList.contains(const_cast<AbstractMetaEnum*>(metaEnum))) @@ -415,9 +421,10 @@ static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QStr if (!metaClass) return QString(); - - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { - foreach (const AbstractMetaEnumValue* enumValue, metaEnum->values()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum* metaEnum : enums) { + const AbstractMetaEnumValueList &values = metaEnum->values(); + for (const AbstractMetaEnumValue *enumValue : values) { if (enumValueName == enumValue->name()) return metaClass->qualifiedCppName(); } @@ -444,7 +451,14 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* if (isPointer(arg->type())) return value; - static QRegExp enumValueRegEx(QLatin1String("^([A-Za-z_]\\w*)?$")); + static const QRegularExpression enumValueRegEx(QStringLiteral("^([A-Za-z_]\\w*)?$")); + Q_ASSERT(enumValueRegEx.isValid()); + // Do not qualify macros by class name, eg QSGGeometry(..., int t = GL_UNSIGNED_SHORT); + static const QRegularExpression macroRegEx(QStringLiteral("^[A-Z_][A-Z0-9_]*$")); + Q_ASSERT(macroRegEx.isValid()); + if (arg->type()->isPrimitive() && macroRegEx.match(value).hasMatch()) + return value; + QString prefix; QString suffix; @@ -453,8 +467,9 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* if (metaEnum) prefix = resolveScopePrefix(metaEnum->enclosingClass(), value); } else if (arg->type()->isFlags()) { - static QRegExp numberRegEx(QLatin1String("^\\d+$")); // Numbers to flags - if (numberRegEx.exactMatch(value)) { + static const QRegularExpression numberRegEx(QStringLiteral("^\\d+$")); // Numbers to flags + Q_ASSERT(numberRegEx.isValid()); + if (numberRegEx.match(value).hasMatch()) { QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass()); if (arg->type()->isConstant()) typeName.remove(0, sizeof("const ") / sizeof(char) - 1); @@ -472,16 +487,18 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* suffix = QLatin1Char(')'); } - static QRegExp enumCombinationRegEx(QLatin1String("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) - if (prefix.isEmpty() && enumCombinationRegEx.indexIn(value) != -1) { - QString flagName = enumCombinationRegEx.cap(1); - QStringList enumItems = enumCombinationRegEx.cap(2).split(QLatin1Char('|')); + static const QRegularExpression enumCombinationRegEx(QStringLiteral("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) + Q_ASSERT(enumCombinationRegEx.isValid()); + const QRegularExpressionMatch match = enumCombinationRegEx.match(value); + if (prefix.isEmpty() && match.hasMatch()) { + QString flagName = match.captured(1); + QStringList enumItems = match.captured(2).split(QLatin1Char('|')); QString scope = searchForEnumScope(func->implementingClass(), enumItems.first()); if (!scope.isEmpty()) scope.append(QLatin1String("::")); QStringList fixedEnumItems; - foreach (const QString& enumItem, enumItems) + for (const QString &enumItem : qAsConst(enumItems)) fixedEnumItems << QString(scope + enumItem); if (!fixedEnumItems.isEmpty()) { @@ -492,16 +509,19 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* } } else if (arg->type()->typeEntry()->isValue()) { const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry()); - if (enumValueRegEx.exactMatch(value)&& value != QLatin1String("NULL")) + if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL")) prefix = resolveScopePrefix(metaClass, value); } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) { - if (enumValueRegEx.exactMatch(value) && func->implementingClass()) + if (enumValueRegEx.match(value).hasMatch() && func->implementingClass()) prefix = resolveScopePrefix(func->implementingClass(), value); } else if(arg->type()->isPrimitive()) { - static QRegExp unknowArgumentRegEx(QLatin1String("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] - if (unknowArgumentRegEx.indexIn(value) != -1 && func->implementingClass()) { - foreach (const AbstractMetaField* field, func->implementingClass()->fields()) { - if (unknowArgumentRegEx.cap(1).trimmed() == field->name()) { + static const QRegularExpression unknowArgumentRegEx(QStringLiteral("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] + Q_ASSERT(unknowArgumentRegEx.isValid()); + const QRegularExpressionMatch match = unknowArgumentRegEx.match(value); + if (match.hasMatch() && func->implementingClass()) { + const AbstractMetaFieldList &fields = func->implementingClass()->fields(); + for (const AbstractMetaField *field : fields) { + if (match.captured(1).trimmed() == field->name()) { QString fieldName = field->name(); if (field->isStatic()) { prefix = resolveScopePrefix(func->implementingClass(), value); @@ -510,7 +530,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* } else { fieldName.prepend(QLatin1String(CPP_SELF_VAR "->")); } - value.replace(unknowArgumentRegEx.cap(1), fieldName); + value.replace(match.captured(1), fieldName); break; } } @@ -622,8 +642,9 @@ bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFuncti return false; if (func->argumentRemoved(argIndex + 1)) return false; - foreach (const FunctionModification &funcMod, func->modifications()) { - foreach (const ArgumentModification &argMod, funcMod.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &funcMod : mods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { if (argMod.index == argIndex + 1 && argMod.noNullPointers) return true; } @@ -635,7 +656,8 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, { QString result; const char objType = (incRef ? 'O' : 'N'); - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; @@ -758,6 +780,13 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType* type) return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<const char*>()"); if (isVoidPointer(type)) return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void*>()"); + const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes(); + if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) { + return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<") + + nestedArrayTypes.constLast()->minimalSignature() + + QLatin1String(">(") + QString::number(nestedArrayTypes.size()) + + QLatin1Char(')'); + } if (type->typeEntry()->isContainer()) { return convertersVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); @@ -983,6 +1012,8 @@ bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaCla { if (!metaClass || !metaClass->typeEntry()->isValue()) return false; + if ((metaClass->attributes() & AbstractMetaAttributes::HasRejectedConstructor) != 0) + return false; AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); if (ctors.count() != 1) return false; @@ -1054,7 +1085,8 @@ bool ShibokenGenerator::shouldDereferenceAbstractMetaTypePointer(const AbstractM bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction* func) { - foreach (const FunctionModification &mod, func->modifications()) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { if (mod.modifiers & Modification::Private) return true; } @@ -1208,8 +1240,8 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* return customCheck; } + QString result = QLatin1String("Shiboken::Conversions::"); if (isWrapperType(metaType)) { - QString result = QLatin1String("Shiboken::Conversions::"); if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType)) result += QLatin1String("isPythonToCppPointerConvertible"); else if (metaType->referenceType() == LValueReference) @@ -1220,8 +1252,18 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* + cpythonTypeNameExt(metaType) + QLatin1String("), "); return result; } - return QStringLiteral("Shiboken::Conversions::isPythonToCppConvertible(%1, ") - .arg(converterObject(metaType)); + result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType); + // Write out array sizes if known + const AbstractMetaTypeCList nestedArrayTypes = metaType->nestedArrayTypes(); + if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) { + const int dim1 = metaType->arrayElementCount(); + const int dim2 = nestedArrayTypes.constFirst()->isArray() + ? nestedArrayTypes.constFirst()->arrayElementCount() : -1; + result += QLatin1String(", ") + QString::number(dim1) + + QLatin1String(", ") + QString::number(dim2); + } + result += QLatin1String(", "); + return result; } QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType) @@ -1306,12 +1348,14 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.')); if (!(options & Generator::SkipName)) { - arg += QLatin1Char(' '); - arg += argument->name(); + // "int a", "int a[]" + const int arrayPos = arg.indexOf(QLatin1Char('[')); + if (arrayPos != -1) + arg.insert(arrayPos, QLatin1Char(' ') + argument->name()); + else + arg.append(QLatin1Char(' ') + argument->name()); } - QList<ReferenceCount> referenceCounts; - referenceCounts = func->referenceCounts(func->implementingClass(), argument->argumentIndex() + 1); if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues && !argument->originalDefaultValueExpression().isEmpty()) { @@ -1445,7 +1489,8 @@ void ShibokenGenerator::writeUnusedVariableCast(QTextStream& s, const QString& v AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass) { AbstractMetaFunctionList result; - foreach (AbstractMetaFunction *func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() || (func->isModifiedRemoved() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected()))) @@ -1458,11 +1503,13 @@ AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaCl ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const { ExtendedConverterData extConvs; - foreach (const AbstractMetaClass* metaClass, classes()) { + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { // Use only the classes for the current module. if (!shouldGenerate(metaClass)) continue; - foreach (AbstractMetaFunction* convOp, metaClass->operatorOverloads(AbstractMetaClass::ConversionOp)) { + const AbstractMetaFunctionList &overloads = metaClass->operatorOverloads(AbstractMetaClass::ConversionOp); + for (AbstractMetaFunction *convOp : overloads) { // 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(); @@ -1476,10 +1523,11 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter return extConvs; } -QList<const CustomConversion*> ShibokenGenerator::getPrimitiveCustomConversions() +QVector<const CustomConversion *> ShibokenGenerator::getPrimitiveCustomConversions() { - QList<const CustomConversion*> conversions; - foreach (const PrimitiveTypeEntry* type, primitiveTypes()) { + QVector<const CustomConversion*> conversions; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) { if (!shouldGenerateTypeEntry(type) || !isUserPrimitive(type) || !type->customConversion()) continue; @@ -1522,7 +1570,7 @@ QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips, { QString code; QTextStream c(&code); - foreach (const CodeSnip &snip, codeSnips) { + for (const CodeSnip &snip : codeSnips) { if ((position != TypeSystem::CodeSnipPositionAny && snip.position != position) || !(snip.language & language)) continue; QString snipCode; @@ -1623,6 +1671,17 @@ 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, @@ -1647,15 +1706,18 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // Replace %PYARG_# variables. code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR)); - static QRegExp pyArgsRegex(QLatin1String("%PYARG_(\\d+)")); + static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)")); + Q_ASSERT(pyArgsRegex.isValid()); if (language == TypeSystem::TargetLangCode) { if (usePyArgs) { code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]")); } else { - static QRegExp pyArgsRegexCheck(QLatin1String("%PYARG_([2-9]+)")); - if (pyArgsRegexCheck.indexIn(code) != -1) { + static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)")); + Q_ASSERT(pyArgsRegexCheck.isValid()); + const QRegularExpressionMatch match = pyArgsRegexCheck.match(code); + if (match.hasMatch()) { qCWarning(lcShiboken).noquote().nospace() - << "Wrong index for %PYARG variable (" << pyArgsRegexCheck.cap(1) << ") on " << func->signature(); + << msgWrongIndex("%PYARG", match.captured(1), func); return; } code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG)); @@ -1663,25 +1725,27 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, } else { // Replaces the simplest case of attribution to a // Python argument on the binding virtual method. - static QRegExp pyArgsAttributionRegex(QLatin1String("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)")); + 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)")); } // Replace %ARG#_TYPE variables. - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1); QString argTypeVal = arg->type()->cppSignature(); code.replace(argTypeVar, argTypeVal); } - int pos = 0; - static QRegExp cppArgTypeRegexCheck(QLatin1String("%ARG(\\d+)_TYPE")); - while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) { + static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE")); + Q_ASSERT(cppArgTypeRegexCheck.isValid()); + QRegularExpressionMatchIterator rit = cppArgTypeRegexCheck.globalMatch(code); + while (rit.hasNext()) { + QRegularExpressionMatch match = rit.next(); qCWarning(lcShiboken).noquote().nospace() - << "Wrong index for %ARG#_TYPE variable (" << cppArgTypeRegexCheck.cap(1) - << ") on " << func->signature(); - pos += cppArgTypeRegexCheck.matchedLength(); + << msgWrongIndex("%ARG#_TYPE", match.captured(1), func); } // Replace template variable for return variable name. @@ -1762,17 +1826,17 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values. // Replaces template variables %# for individual arguments. - ArgumentVarReplacementList argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); + const ArgumentVarReplacementList &argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); QStringList args; - foreach (const ArgumentVarReplacementPair &pair, argReplacements) { + for (const ArgumentVarReplacementPair &pair : argReplacements) { if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED))) continue; args << pair.second; } code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", "))); - foreach (const ArgumentVarReplacementPair &pair, argReplacements) { + for (const ArgumentVarReplacementPair &pair : argReplacements) { const AbstractMetaArgument* arg = pair.first; int idx = arg->argumentIndex() + 1; AbstractMetaType* type = arg->type(); @@ -1789,7 +1853,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, if (type->referenceType() == LValueReference || isPointer(type)) code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->")); } - code.replace(QRegExp(QString::fromLatin1("%%1\\b").arg(idx)), pair.second); + code.replace(placeHolderRegex(idx), pair.second); } if (language == TypeSystem::NativeCode) { @@ -1811,7 +1875,8 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // dispatcher. bool hasProtectedOverload = false; if (func->isUserAdded()) { - foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name())) + const AbstractMetaFunctionList &funcs = getFunctionOverloads(func->ownerClass(), func->name()); + for (const AbstractMetaFunction *f : funcs) hasProtectedOverload |= f->isProtected(); } @@ -1842,8 +1907,9 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // and false if it is a variable. static bool isVariable(const QString& code) { - static QRegExp expr(QLatin1String("\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*")); - return expr.exactMatch(code.trimmed()); + static const QRegularExpression expr(QStringLiteral("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$")); + Q_ASSERT(expr.isValid()); + return expr.match(code.trimmed()).hasMatch(); } // A miniature normalizer that puts a type string into a format @@ -1893,12 +1959,11 @@ static QString getConverterTypeSystemVariableArgument(const QString& code, int p typedef QPair<QString, QString> StringPair; void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code) { - QRegExp& regex = m_typeSystemConvRegEx[converterVariable]; - int pos = 0; - QList<StringPair> replacements; - while ((pos = regex.indexIn(code, pos)) != -1) { - pos += regex.matchedLength(); - QStringList list = regex.capturedTexts(); + QVector<StringPair> replacements; + QRegularExpressionMatchIterator rit = m_typeSystemConvRegEx[converterVariable].globalMatch(code); + while (rit.hasNext()) { + const QRegularExpressionMatch match = rit.next(); + const QStringList list = match.capturedTexts(); QString conversionString = list.first(); QString conversionTypeName = list.last(); const AbstractMetaType* conversionType = buildAbstractMetaTypeFromString(conversionTypeName); @@ -1912,7 +1977,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa QTextStream c(&conversion); switch (converterVariable) { case TypeSystemToCppFunction: { - int end = pos - list.first().count(); + int end = match.capturedStart(); int start = end; while (start > 0 && code.at(start) != QLatin1Char('\n')) --start; @@ -1941,7 +2006,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa } else { prefix = QLatin1Char('&'); } - QString arg = getConverterTypeSystemVariableArgument(code, pos); + QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); conversionString += arg; c << arg << ", " << prefix << '(' << varName << ')'; break; @@ -1961,7 +2026,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa if (conversion.isEmpty()) conversion = cpythonToPythonConversionFunction(conversionType); default: { - QString arg = getConverterTypeSystemVariableArgument(code, pos); + 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'") @@ -1977,14 +2042,14 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa } replacements.append(qMakePair(conversionString, conversion)); } - foreach (const StringPair &rep, replacements) + for (const StringPair &rep : qAsConst(replacements)) code.replace(rep.first, rep.second); } bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%CPPSELF"))) return true; } @@ -1994,7 +2059,7 @@ bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%PYSELF"))) return true; } @@ -2010,7 +2075,7 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); } CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%FUNCTION_NAME(")) || snip.code().contains(funcCall) || (func->isConstructor() && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall)) @@ -2023,10 +2088,11 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction* func) { - static QRegExp overrideCallRegexCheck(QLatin1String("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); + static const QRegularExpression overrideCallRegexCheck(QStringLiteral("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); + Q_ASSERT(overrideCallRegexCheck.isValid()); CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - foreach (const CodeSnip &snip, snips) { - if (overrideCallRegexCheck.indexIn(snip.code()) != -1) + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(overrideCallRegexCheck)) return true; } return false; @@ -2034,15 +2100,17 @@ bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFuncti bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language) { - static QRegExp retValAttributionRegexCheck_native(QLatin1String("%0\\s*=[^=]\\s*.+")); - static QRegExp retValAttributionRegexCheck_target(QLatin1String("%PYARG_0\\s*=[^=]\\s*.+")); + static const QRegularExpression retValAttributionRegexCheck_native(QStringLiteral("%0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_native.isValid()); + static const QRegularExpression retValAttributionRegexCheck_target(QStringLiteral("%PYARG_0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_target.isValid()); CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (language == TypeSystem::TargetLangCode) { - if (retValAttributionRegexCheck_target.indexIn(snip.code()) != -1) + if (snip.code().contains(retValAttributionRegexCheck_target)) return true; } else { - if (retValAttributionRegexCheck_native.indexIn(snip.code()) != -1) + if (snip.code().contains(retValAttributionRegexCheck_native)) return true; } } @@ -2052,11 +2120,10 @@ bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMeta bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny); - foreach (const CodeSnip &snip, snips) { + const QRegularExpression argRegEx = placeHolderRegex(argumentIndex + 1); + for (const CodeSnip &snip : qAsConst(snips)) { QString code = snip.code(); - if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) - return true; - if (code.contains(QRegExp(QStringLiteral("%%1\\b").arg(argumentIndex + 1)))) + if (code.contains(QLatin1String("%ARGUMENT_NAMES")) || code.contains(argRegEx)) return true; } return false; @@ -2083,7 +2150,7 @@ bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* meta const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass); for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() || func->isPrivate() || func->ownerClass() != func->implementingClass() || func->isConstructor() || func->isOperatorOverload()) @@ -2114,7 +2181,7 @@ AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStatic const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() || func->isPrivate() || func->ownerClass() != func->implementingClass() || func->isConstructor() || func->isOperatorOverload()) @@ -2134,7 +2201,8 @@ AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* { AbstractMetaClassList baseClasses; if (metaClass) { - foreach (const QString &parent, metaClass->baseClassNames()) { + const QStringList &baseClassNames = metaClass->baseClassNames(); + for (const QString &parent : baseClassNames) { AbstractMetaClass *clazz = AbstractMetaClass::findClass(classes(), parent); if (clazz) baseClasses << clazz; @@ -2157,7 +2225,7 @@ AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass AbstractMetaClassList result; if (metaClass) { AbstractMetaClassList baseClasses = getBaseClasses(metaClass); - foreach (AbstractMetaClass* base, baseClasses) { + for (AbstractMetaClass *base : qAsConst(baseClasses)) { result.append(base); result.append(getAllAncestors(base)); } @@ -2268,7 +2336,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromString(QString typ metaType->setReferenceType(refType); metaType->setConstant(isConst); metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - foreach (const QString& instantiation, instantiatedTypes) { + for (const QString &instantiation : qAsConst(instantiatedTypes)) { AbstractMetaType* tmplArgType = buildAbstractMetaTypeFromString(instantiation); metaType->addInstantiation(tmplArgType); } @@ -2303,7 +2371,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass( static void dumpFunction(AbstractMetaFunctionList lst) { qDebug() << "DUMP FUNCTIONS: "; - foreach (AbstractMetaFunction *func, lst) + for (AbstractMetaFunction *func : qAsConst(lst)) qDebug() << "*" << func->ownerClass()->name() << func->signature() << "Private: " << func->isPrivate() @@ -2331,7 +2399,7 @@ QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(c AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); QMap<QString, AbstractMetaFunctionList> results; - foreach (AbstractMetaFunction* func, lst) { + for (AbstractMetaFunction *func : qAsConst(lst)) { if (isGroupable(func)) results[func->name()].append(func); } @@ -2370,7 +2438,7 @@ AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractM AbstractMetaFunctionList results; QSet<QString> seenSignatures; - foreach (AbstractMetaFunction* func, lst) { + for (AbstractMetaFunction *func : qAsConst(lst)) { if (func->name() != functionName) continue; if (isGroupable(func)) { @@ -2387,9 +2455,10 @@ QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFuncti int minArgs = std::numeric_limits<int>::max(); int maxArgs = 0; - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction* func : qAsConst(overloads)) { int numArgs = 0; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (!func->argumentRemoved(arg->argumentIndex() + 1)) numArgs++; } @@ -2399,27 +2468,26 @@ QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFuncti return qMakePair(minArgs, maxArgs); } -QMap<QString, QString> ShibokenGenerator::options() const +Generator::OptionDescriptions ShibokenGenerator::options() const { - QMap<QString, QString> opts(Generator::options()); - opts.insert(QLatin1String(AVOID_PROTECTED_HACK), - QLatin1String("Avoid the use of the '#define protected public' hack.")); - opts.insert(QLatin1String(PARENT_CTOR_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on constructors.")); - opts.insert(QLatin1String(RETURN_VALUE_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)")); - opts.insert(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), - QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")); - opts.insert(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), - QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")); - opts.insert(QLatin1String(USE_ISNULL_AS_NB_NONZERO), - QLatin1String("If a class have an isNull()const method, it will be used to compute the value of boolean casts")); - return opts; + return OptionDescriptions() + << qMakePair(QLatin1String(AVOID_PROTECTED_HACK), + QLatin1String("Avoid the use of the '#define protected public' hack.")) + << qMakePair(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), + QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")) + << qMakePair(QLatin1String(PARENT_CTOR_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on constructors.")) + << qMakePair(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), + QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")) + << qMakePair(QLatin1String(RETURN_VALUE_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on return values (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 the value of boolean casts")); } static void getCode(QStringList& code, const CodeSnipList& codeSnips) { - foreach (const CodeSnip& snip, codeSnips) + for (const CodeSnip &snip : qAsConst(codeSnips)) code.append(snip.code()); } @@ -2438,7 +2506,7 @@ static void getCode(QStringList& code, const TypeEntry* type) if (toCppConversions.isEmpty()) return; - foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions) + for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions)) code.append(toNative->conversion()); } @@ -2453,20 +2521,23 @@ bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args) TypeDatabase* td = TypeDatabase::instance(); QStringList snips; - foreach (const PrimitiveTypeEntry* type, primitiveTypes()) + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) getCode(snips, type); - foreach (const ContainerTypeEntry* type, containerTypes()) + const ContainerTypeEntryList &containerTypeList = containerTypes(); + for (const ContainerTypeEntry *type : containerTypeList) getCode(snips, type); - foreach (const AbstractMetaClass* metaClass, classes()) + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) getCode(snips, metaClass->typeEntry()); getCode(snips, td->findType(packageName())); const FunctionGroupMap &functionGroups = getFunctionGroups(); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - foreach (AbstractMetaFunction* func, it.value()) + for (AbstractMetaFunction *func : it.value()) getCode(snips, func->injectedCodeSnips()); } - foreach (const QString& code, snips) { + for (const QString &code : qAsConst(snips)) { collectContainerTypesFromConverterMacros(code, true); collectContainerTypesFromConverterMacros(code, false); } @@ -2536,7 +2607,8 @@ QString ShibokenGenerator::convertersVariableName(const QString& moduleName) con static QString processInstantiationsVariableName(const AbstractMetaType* type) { QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper(); - foreach (const AbstractMetaType* instantiation, type->instantiations()) { + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { res += instantiation->isContainer() ? processInstantiationsVariableName(instantiation) : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper(); @@ -2551,7 +2623,8 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* met return QString(); QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); QString instantiations; - foreach (const AbstractMetaType* instantiation, metaClass->templateBaseClassInstantiations()) + const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); + for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) instantiations += processInstantiationsVariableName(instantiation); return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations); } @@ -2615,8 +2688,9 @@ QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, co return arg->defaultValueExpression(); //Check modifications - foreach(FunctionModification m, func->modifications()) { - foreach(ArgumentModification am, m.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &m : mods) { + for (const ArgumentModification &am : m.argument_mods) { if (am.index == (arg->argumentIndex() + 1)) return am.replacedDefaultExpression; } |