diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/typedatabase.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/typedatabase.cpp | 225 |
1 files changed, 150 insertions, 75 deletions
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 55170d7c1..4a96240c4 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -31,6 +31,7 @@ #include "typesystem_p.h" #include <QtCore/QFile> +#include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QPair> #include <QtCore/QVector> @@ -175,8 +176,8 @@ FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const TypeEntry* TypeDatabase::findType(const QString& name) const { - QList<TypeEntry *> entries = findTypes(name); - foreach (TypeEntry *entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) { return entry; @@ -185,7 +186,7 @@ TypeEntry* TypeDatabase::findType(const QString& name) const return 0; } -QList<TypeEntry *> TypeDatabase::findTypes(const QString &name) const +TypeEntryList TypeDatabase::findTypes(const QString &name) const { return m_entries.value(name); } @@ -201,12 +202,12 @@ SingleTypeEntryHash TypeDatabase::entries() const return returned; } -QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const +PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const { TypeEntryHash entries = allEntries(); - QList<const PrimitiveTypeEntry*> returned; + PrimitiveTypeEntryList returned; for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - foreach (TypeEntry *typeEntry, it.value()) { + for (TypeEntry *typeEntry : it.value()) { if (typeEntry->isPrimitive()) returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry)); } @@ -214,75 +215,121 @@ QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const return returned; } -QList<const ContainerTypeEntry*> TypeDatabase::containerTypes() const +ContainerTypeEntryList TypeDatabase::containerTypes() const { TypeEntryHash entries = allEntries(); - QList<const ContainerTypeEntry*> returned; + ContainerTypeEntryList returned; for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - foreach (TypeEntry *typeEntry, it.value()) { + for (TypeEntry *typeEntry : it.value()) { if (typeEntry->isContainer()) returned.append(static_cast<ContainerTypeEntry *>(typeEntry)); } } return returned; } -void TypeDatabase::addRejection(const QString& className, const QString& functionName, - const QString& fieldName, const QString& enumName) + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeRejection &r) { - TypeRejection r; - r.class_name = className; - r.function_name = functionName; - r.field_name = fieldName; - r.enum_name = enumName; + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeRejection(type=" << r.matchType << ", class=" + << r.className.pattern() << ", pattern=" << r.pattern.pattern() << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM +void TypeDatabase::addRejection(const TypeRejection &r) +{ m_rejections << r; } -bool TypeDatabase::isClassRejected(const QString& className) const +static inline QString msgRejectReason(const TypeRejection &r, const QString &needle = QString()) +{ + QString result; + QTextStream str(&result); + switch (r.matchType) { + case TypeRejection::ExcludeClass: + str << " matches class exclusion \"" << r.className.pattern() << '"'; + break; + case TypeRejection::Function: + case TypeRejection::Field: + case TypeRejection::Enum: + str << " matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; + break; + case TypeRejection::ArgumentType: + case TypeRejection::ReturnType: + str << " matches class \"" << r.className.pattern() << "\" and \"" << needle + << "\" matches \"" << r.pattern.pattern() << '"'; + break; + } + return result; +} + +// Match class name only +bool TypeDatabase::isClassRejected(const QString& className, QString *reason) const { - foreach (const TypeRejection& r, m_rejections) { - if (r.class_name == className && r.function_name == QLatin1String("*") - && r.field_name == QLatin1String("*") && r.enum_name == QLatin1String("*")) { + for (const TypeRejection& r : m_rejections) { + if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r); return true; } } return false; } -bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName) const +// Match class name and function/enum/field +static bool findRejection(const QVector<TypeRejection> &rejections, + TypeRejection::MatchType matchType, + const QString& className, const QString& name, + QString *reason = nullptr) { - foreach (const TypeRejection& r, m_rejections) { - if (r.enum_name == enumName - && (r.class_name == className || r.class_name == QLatin1String("*"))) { + Q_ASSERT(matchType != TypeRejection::ExcludeClass); + for (const TypeRejection& r : rejections) { + if (r.matchType == matchType && r.pattern.match(name).hasMatch() + && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r, name); return true; } } - return false; } +bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName, QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Enum, className, enumName, reason); +} + void TypeDatabase::addType(TypeEntry *e) { m_entries[e->qualifiedCppName()].append(e); } -bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName) const +bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, + QString *reason) const { - foreach (const TypeRejection& r, m_rejections) - if (r.function_name == functionName && - (r.class_name == className || r.class_name == QLatin1String("*"))) - return true; - return false; + return findRejection(m_rejections, TypeRejection::Function, className, functionName, reason); } +bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Field, className, fieldName, reason); +} -bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName) const +bool TypeDatabase::isArgumentTypeRejected(const QString& className, const QString& typeName, + QString *reason) const { - foreach (const TypeRejection& r, m_rejections) - if (r.field_name == fieldName && - (r.class_name == className || r.class_name == QLatin1String("*"))) - return true; - return false; + return findRejection(m_rejections, TypeRejection::ArgumentType, className, typeName, reason); +} + +bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& typeName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::ReturnType, className, typeName, reason); } FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const @@ -321,7 +368,7 @@ void TypeDatabase::addGlobalUserFunctions(const AddedFunctionList &functions) AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const { AddedFunctionList addedFunctions; - foreach (const AddedFunction &func, m_globalUserFunctions) { + for (const AddedFunction &func : m_globalUserFunctions) { if (func.name() == name) addedFunctions.append(func); } @@ -343,16 +390,52 @@ FunctionModificationList TypeDatabase::functionModifications(const QString& sign FunctionModificationList lst; for (int i = 0; i < m_functionMods.count(); ++i) { const FunctionModification& mod = m_functionMods.at(i); - if (mod.signature == signature) + if (mod.matches(signature)) lst << mod; } return lst; } -void TypeDatabase::addSuppressedWarning(const QString &s) +bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMessage) { - m_suppressedWarnings.append(s); + QString pattern; + if (warning.startsWith(QLatin1Char('^')) && warning.endsWith(QLatin1Char('$'))) { + pattern = warning; + } else { + // Legacy syntax: Use wildcards '*' (unless escaped by '\') + QVector<int> asteriskPositions; + const int warningSize = warning.size(); + for (int i = 0; i < warningSize; ++i) { + if (warning.at(i) == QLatin1Char('\\')) + ++i; + else if (warning.at(i) == QLatin1Char('*')) + asteriskPositions.append(i); + } + asteriskPositions.append(warningSize); + + pattern.append(QLatin1Char('^')); + int lastPos = 0; + for (int a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) { + if (a) + pattern.append(QStringLiteral(".*")); + const int nextPos = asteriskPositions.at(a); + if (nextPos > lastPos) + pattern.append(QRegularExpression::escape(warning.mid(lastPos, nextPos - lastPos))); + lastPos = nextPos + 1; + } + pattern.append(QLatin1Char('$')); + } + + const QRegularExpression expression(pattern); + if (!expression.isValid()) { + *errorMessage = QLatin1String("Invalid message pattern \"") + warning + + QLatin1String("\": ") + expression.errorString(); + return false; + } + + m_suppressedWarnings.append(expression); + return true; } bool TypeDatabase::isSuppressedWarning(const QString& s) const @@ -360,36 +443,23 @@ bool TypeDatabase::isSuppressedWarning(const QString& s) const if (!m_suppressWarnings) return false; - foreach (const QString &_warning, m_suppressedWarnings) { - QString warning = _warning; - warning.replace(QLatin1String("\\*"), QLatin1String("&place_holder_for_asterisk;")); - - QStringList segs = warning.split(QLatin1Char('*'), QString::SkipEmptyParts); - if (!segs.size()) - continue; - - int i = 0; - int pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*"))); - //qDebug() << "s == " << s << ", warning == " << segs; - while (pos != -1) { - if (i == segs.size()) - return true; - pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*")), pos); - } + for (const QRegularExpression &warning : m_suppressedWarnings) { + if (warning.match(s).hasMatch()) + return true; } return false; } -QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) const +QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, bool stripPath) const { const QFileInfo tsFi(tsFile); if (tsFi.isAbsolute()) // No point in further lookups return tsFi.absoluteFilePath(); if (tsFi.isFile()) // Make path absolute return tsFi.absoluteFilePath(); - const QString fileName = tsFi.fileName(); - foreach (const QString &path, m_typesystemPaths) { + const QString fileName = stripPath ? tsFi.fileName() : tsFile; + for (const QString &path : m_typesystemPaths) { const QFileInfo fi(path + QLatin1Char('/') + fileName); if (fi.isFile()) return fi.absoluteFilePath(); @@ -440,9 +510,9 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); + const TypeEntryList &entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + for (TypeEntry *entry : entries) { if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry*>(entry)->preferredTargetLangType()) return static_cast<PrimitiveTypeEntry*>(entry); } @@ -452,8 +522,8 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isComplex()) return static_cast<ComplexTypeEntry*>(entry); } @@ -462,8 +532,8 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isObject()) return static_cast<ObjectTypeEntry*>(entry); } @@ -472,8 +542,8 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isNamespace()) return static_cast<NamespaceTypeEntry*>(entry); } @@ -518,13 +588,13 @@ static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) static void _computeTypeIndexes() { TypeDatabase* tdb = TypeDatabase::instance(); - typedef QMap<int, QList<TypeEntry*> > GroupedTypeEntries; + typedef QMap<int, TypeEntryList> GroupedTypeEntries; GroupedTypeEntries groupedEntries; // Group type entries by revision numbers - TypeEntryHash allEntries = tdb->allEntries(); - foreach (QList<TypeEntry*> entryList, allEntries) { - foreach (TypeEntry* entry, entryList) { + const TypeEntryHash &allEntries = tdb->allEntries(); + for (TypeEntryHash::const_iterator tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { + for (TypeEntry *entry : tit.value()) { if (entry->isPrimitive() || entry->isContainer() || entry->isFunction() @@ -543,12 +613,12 @@ static void _computeTypeIndexes() GroupedTypeEntries::iterator it = groupedEntries.begin(); for (; it != groupedEntries.end(); ++it) { // Remove duplicates - QList<TypeEntry*>::iterator newEnd = std::unique(it.value().begin(), it.value().end()); + TypeEntryList::iterator newEnd = std::unique(it.value().begin(), it.value().end()); it.value().erase(newEnd, it.value().end()); // Sort the type entries by name qSort(it.value().begin(), newEnd, compareTypeEntriesByName); - foreach (TypeEntry* entry, it.value()) { + for (TypeEntry *entry : qAsConst(it.value())) { (*typeEntryFields())[entry].second = maxTypeIndex++; } } @@ -614,7 +684,12 @@ QDebug operator<<(QDebug d, const TypeEntry *te) d.nospace(); d << "TypeEntry("; if (te) { - d << '"' << te->qualifiedCppName() << "\", type=" << te->type(); + const QString name = te->name(); + const QString cppName = te->qualifiedCppName(); + d << '"' << name << '"'; + if (name != cppName) + d << "\", cppName=\"" << cppName << '"'; + d << ", type=" << te->type(); if (te->include().isValid()) d << ", include=" << te->include(); const IncludeList &extraIncludes = te->extraIncludes(); |