diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/typedatabase.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/typedatabase.cpp | 390 |
1 files changed, 254 insertions, 136 deletions
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 9529de40a..c0999e7ab 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -166,64 +166,66 @@ ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const return 0; } -FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const +static bool inline useType(const TypeEntry *t) { - TypeEntry* entry = findType(name); - if (entry && entry->type() == TypeEntry::FunctionType) - return static_cast<FunctionTypeEntry*>(entry); - return 0; + return !t->isPrimitive() + || static_cast<const PrimitiveTypeEntry *>(t)->preferredTargetLangType(); } -TypeEntry* TypeDatabase::findType(const QString& name) const +FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const { - const TypeEntryList &entries = findTypes(name); + const auto entries = findTypes(name); for (TypeEntry *entry : entries) { - if (entry && - (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) { - return entry; - } + if (entry->type() == TypeEntry::FunctionType && useType(entry)) + return static_cast<FunctionTypeEntry*>(entry); } return 0; } -TypeEntryList TypeDatabase::findTypes(const QString &name) const +const TypeSystemTypeEntry *TypeDatabase::findTypeSystemType(const QString &name) const { - return m_entries.value(name); + const auto entries = findTypes(name); + for (const TypeEntry *entry : entries) { + if (entry->type() == TypeEntry::TypeSystemType) + return static_cast<const TypeSystemTypeEntry *>(entry); + } + return nullptr; } -SingleTypeEntryHash TypeDatabase::entries() const +TypeEntry* TypeDatabase::findType(const QString& name) const { - TypeEntryHash entries = allEntries(); - - SingleTypeEntryHash returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) - returned.insert(it.key(), findType(it.key())); + const auto entries = findTypes(name); + for (TypeEntry *entry : entries) { + if (useType(entry)) + return entry; + } + return nullptr; +} - return returned; +TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypes(const QString &name) const +{ + const auto range = m_entries.equal_range(name); + return {range.first, range.second}; } PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const { - TypeEntryHash entries = allEntries(); PrimitiveTypeEntryList returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - for (TypeEntry *typeEntry : it.value()) { - if (typeEntry->isPrimitive()) - returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry)); - } + for (auto it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { + TypeEntry *typeEntry = it.value(); + if (typeEntry->isPrimitive()) + returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry)); } return returned; } ContainerTypeEntryList TypeDatabase::containerTypes() const { - TypeEntryHash entries = allEntries(); ContainerTypeEntryList returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - for (TypeEntry *typeEntry : it.value()) { - if (typeEntry->isContainer()) - returned.append(static_cast<ContainerTypeEntry *>(typeEntry)); - } + for (auto it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { + TypeEntry *typeEntry = it.value(); + if (typeEntry->isContainer()) + returned.append(static_cast<ContainerTypeEntry *>(typeEntry)); } return returned; } @@ -263,6 +265,8 @@ static inline QString msgRejectReason(const TypeRejection &r, const QString &nee str << " matches class \"" << r.className.pattern() << "\" and \"" << needle << "\" matches \"" << r.pattern.pattern() << '"'; break; + case TypeRejection::Invalid: + break; } return result; } @@ -303,9 +307,52 @@ bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumN return findRejection(m_rejections, TypeRejection::Enum, className, enumName, reason); } -void TypeDatabase::addType(TypeEntry *e) +TypeEntry *TypeDatabase::resolveTypeDefEntry(TypedefEntry *typedefEntry, + QString *errorMessage) +{ + QString sourceName = typedefEntry->sourceType(); + const int lessThanPos = sourceName.indexOf(QLatin1Char('<')); + if (lessThanPos != -1) + sourceName.truncate(lessThanPos); + ComplexTypeEntry *source = nullptr; + for (TypeEntry *e : findTypes(sourceName)) { + switch (e->type()) { + case TypeEntry::BasicValueType: + case TypeEntry::ContainerType: + case TypeEntry::InterfaceType: + case TypeEntry::ObjectType: + case TypeEntry::SmartPointerType: + source = dynamic_cast<ComplexTypeEntry *>(e); + Q_ASSERT(source); + break; + default: + break; + } + } + if (!source) { + if (errorMessage) + *errorMessage = QLatin1String("Unable to resolve typedef \"") + + typedefEntry->sourceType() + QLatin1Char('"'); + return nullptr; + } + + ComplexTypeEntry *result = static_cast<ComplexTypeEntry *>(source->clone()); + result->useAsTypedef(typedefEntry); + typedefEntry->setSource(source); + typedefEntry->setTarget(result); + m_typedefEntries.insert(typedefEntry->qualifiedCppName(), typedefEntry); + return result; +} + +bool TypeDatabase::addType(TypeEntry *e, QString *errorMessage) { - m_entries[e->qualifiedCppName()].append(e); + if (e->type() == TypeEntry::TypedefType) { + e = resolveTypeDefEntry(static_cast<TypedefEntry *>(e), errorMessage); + if (Q_UNLIKELY(!e)) + return false; + } + m_entries.insert(e->qualifiedCppName(), e); + return true; } bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, @@ -339,7 +386,7 @@ FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const fte = m_flagsEntries.value(name); if (!fte) { //last hope, search for flag without scope inside of flags hash - for (SingleTypeEntryHash::const_iterator it = m_flagsEntries.cbegin(), end = m_flagsEntries.cend(); it != end; ++it) { + for (auto it = m_flagsEntries.cbegin(), end = m_flagsEntries.cend(); it != end; ++it) { if (it.key().endsWith(name)) { fte = it.value(); break; @@ -427,12 +474,13 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe pattern.append(QLatin1Char('$')); } - const QRegularExpression expression(pattern); + QRegularExpression expression(pattern); if (!expression.isValid()) { *errorMessage = QLatin1String("Invalid message pattern \"") + warning + QLatin1String("\": ") + expression.errorString(); return false; } + expression.setPatternOptions(expression.patternOptions() | QRegularExpression::MultilineOption); m_suppressedWarnings.append(expression); return true; @@ -518,16 +566,21 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) { QXmlStreamReader reader(device); Handler handler(this, generate); - return handler.parse(reader); + const bool result = handler.parse(reader); + if (!result) + qCWarning(lcShiboken, "%s", qPrintable(handler.errorString())); + return result; } PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - const TypeEntryList &entries = findTypes(name); - + const auto entries = findTypes(name); for (TypeEntry *entry : entries) { - if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry*>(entry)->preferredTargetLangType()) - return static_cast<PrimitiveTypeEntry*>(entry); + if (entry->isPrimitive()) { + PrimitiveTypeEntry *pe = static_cast<PrimitiveTypeEntry *>(entry); + if (pe->preferredTargetLangType()) + return pe; + } } return 0; @@ -535,9 +588,9 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - const TypeEntryList &entries = findTypes(name); + const auto entries = findTypes(name); for (TypeEntry *entry : entries) { - if (entry && entry->isComplex()) + if (entry->isComplex() && useType(entry)) return static_cast<ComplexTypeEntry*>(entry); } return 0; @@ -545,9 +598,9 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - const TypeEntryList &entries = findTypes(name); + const auto entries = findTypes(name); for (TypeEntry *entry : entries) { - if (entry && entry->isObject()) + if (entry && entry->isObject() && useType(entry)) return static_cast<ObjectTypeEntry*>(entry); } return 0; @@ -555,9 +608,9 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const { - const TypeEntryList &entries = findTypes(name); + const auto entries = findTypes(name); for (TypeEntry *entry : entries) { - if (entry && entry->isNamespace()) + if (entry->isNamespace() && useType(entry)) return static_cast<NamespaceTypeEntry*>(entry); } return 0; @@ -574,75 +627,64 @@ void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) m_dropTypeEntries.sort(); } -// Using std::pair to save some memory -// the pair means (revision, typeIndex) -// This global variable exists only because we can't break the ABI -typedef QHash<const TypeEntry*, std::pair<int, int> > TypeRevisionMap; -Q_GLOBAL_STATIC(TypeRevisionMap, typeEntryFields); static bool computeTypeIndexes = true; static int maxTypeIndex; -int getTypeRevision(const TypeEntry* typeEntry) +static bool typeEntryLessThan(const TypeEntry* t1, const TypeEntry* t2) { - return typeEntryFields()->value(typeEntry).first; -} - -void setTypeRevision(TypeEntry* typeEntry, int revision) -{ - (*typeEntryFields())[typeEntry].first = revision; - computeTypeIndexes = true; -} - -static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) -{ - return t1->qualifiedCppName() < t2->qualifiedCppName(); + if (t1->revision() < t2->revision()) + return true; + return t1->revision() == t2->revision() + && t1->qualifiedCppName() < t2->qualifiedCppName(); } static void _computeTypeIndexes() { TypeDatabase* tdb = TypeDatabase::instance(); - typedef QMap<int, TypeEntryList> GroupedTypeEntries; - GroupedTypeEntries groupedEntries; + + TypeEntryList list; // Group type entries by revision numbers - 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() - || !entry->generateCode() - || entry->isEnumValue() - || entry->isVarargs() - || entry->isTypeSystem() - || entry->isVoid() - || entry->isCustom()) - continue; - groupedEntries[getTypeRevision(entry)] << entry; - } - } + const auto &allEntries = tdb->entries(); + list.reserve(allEntries.size()); + for (auto tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { + TypeEntry *entry = tit.value(); + if (entry->isPrimitive() + || entry->isContainer() + || entry->isFunction() + || !entry->generateCode() + || entry->isEnumValue() + || entry->isVarargs() + || entry->isTypeSystem() + || entry->isVoid() + || entry->isCustom()) + continue; + if (!list.contains(entry)) // Remove duplicates + list.append(entry); + } + + // Sort the type entries by revision, name + std::sort(list.begin(), list.end(), typeEntryLessThan); maxTypeIndex = 0; - GroupedTypeEntries::iterator it = groupedEntries.begin(); - for (; it != groupedEntries.end(); ++it) { - // Remove duplicates - 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); - - for (TypeEntry *entry : qAsConst(it.value())) { - (*typeEntryFields())[entry].second = maxTypeIndex++; - } - } + for (TypeEntry *e : qAsConst(list)) + e->setSbkIndex(maxTypeIndex++); computeTypeIndexes = false; } -int getTypeIndex(const TypeEntry* typeEntry) +void TypeEntry::setRevision(int r) +{ + if (m_revision != r) { + m_revision = r; + computeTypeIndexes = true; + } +} + +int TypeEntry::sbkIndex() const { if (computeTypeIndexes) _computeTypeIndexes(); - return typeEntryFields()->value(typeEntry).second; + return m_sbkIndex; } int getMaxTypeIndex() @@ -652,6 +694,11 @@ int getMaxTypeIndex() return maxTypeIndex; } +void TypeDatabase::clearApiVersions() +{ + apiVersions()->clear(); +} + bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QString &version) { const QString packagePattern = wildcardToRegExp(packageWildcardPattern.trimmed()); @@ -673,9 +720,11 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS } bool TypeDatabase::checkApiVersion(const QString &package, - const QVersionNumber &versionNumber) const + const QVersionNumber &versionNumber) { const ApiVersions &versions = *apiVersions(); + if (versions.isEmpty()) // Nothing specified: use latest. + return true; for (int i = 0, size = versions.size(); i < size; ++i) { if (versions.at(i).first.match(package).hasMatch()) return versions.at(i).second >= versionNumber; @@ -684,33 +733,111 @@ bool TypeDatabase::checkApiVersion(const QString &package, } #ifndef QT_NO_DEBUG_STREAM + +#define FORMAT_BOOL(name, var) \ + if (var) \ + d << ", [" << name << ']'; + +#define FORMAT_NONEMPTY_STRING(name, var) \ + if (!var.isEmpty()) \ + d << ", " << name << "=\"" << var << '"'; + +#define FORMAT_LIST_SIZE(name, var) \ + if (!var.isEmpty()) \ + d << ", " << var.size() << ' ' << name; + +template <class Container, class Separator> +static void formatList(QDebug &d, const char *name, const Container &c, Separator sep) +{ + if (const int size = c.size()) { + d << ", " << name << '[' << size << "]=("; + for (int i = 0; i < size; ++i) { + if (i) + d << sep; + d << c.at(i); + } + d << ')'; + } +} + +void TypeEntry::formatDebug(QDebug &d) const +{ + const QString cppName = qualifiedCppName(); + d << '"' << m_name << '"'; + if (m_name != cppName) + d << "\", cppName=\"" << cppName << '"'; + d << ", type=" << m_type << ", codeGeneration=0x" + << hex << m_codeGeneration << dec; + FORMAT_NONEMPTY_STRING("package", m_targetLangPackage) + FORMAT_BOOL("stream", m_stream) + FORMAT_LIST_SIZE("codeSnips", m_codeSnips) + FORMAT_NONEMPTY_STRING("conversionRule", m_conversionRule) + if (!m_version.isNull() && m_version > QVersionNumber(0, 0)) + d << ", version=" << m_version; + if (m_revision) + d << ", revision=" << m_revision; + if (m_sbkIndex) + d << ", sbkIndex=" << m_sbkIndex; + if (m_include.isValid()) + d << ", include=" << m_include; + formatList(d, "extraIncludes", m_extraIncludes, ", "); +} + +void ComplexTypeEntry::formatDebug(QDebug &d) const +{ + TypeEntry::formatDebug(d); + FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName) + FORMAT_BOOL("QObject", m_qobject) + FORMAT_BOOL("polymorphicBase", m_polymorphicBase) + FORMAT_BOOL("genericClass", m_genericClass) + FORMAT_BOOL("deleteInMainThread", m_deleteInMainThread) + if (m_typeFlags != 0) + d << ", typeFlags=" << m_typeFlags; + d << ", copyableFlag=" << m_copyableFlag + << ", except=" << int(m_exceptionHandling); + FORMAT_NONEMPTY_STRING("defaultSuperclass", m_defaultSuperclass) + FORMAT_NONEMPTY_STRING("polymorphicIdValue", m_polymorphicIdValue) + FORMAT_NONEMPTY_STRING("lookupName", m_lookupName) + FORMAT_NONEMPTY_STRING("targetType", m_targetType) + FORMAT_NONEMPTY_STRING("hash", m_hashFunction) + FORMAT_LIST_SIZE("addedFunctions", m_addedFunctions) + formatList(d, "functionMods", m_functionMods, ", "); + FORMAT_LIST_SIZE("fieldMods", m_fieldMods) +} + +void TypedefEntry::formatDebug(QDebug &d) const +{ + ComplexTypeEntry::formatDebug(d); + d << ", sourceType=\"" << m_sourceType << '"' + << ", source=" << m_source << ", target=" << m_target; +} + +void EnumTypeEntry::formatDebug(QDebug &d) const +{ + TypeEntry::formatDebug(d); + FORMAT_NONEMPTY_STRING("package", m_packageName) + FORMAT_NONEMPTY_STRING("qualifier", m_qualifier) + FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName) + if (m_flags) + d << ", flags=(" << m_flags << ')'; +} + +void ContainerTypeEntry::formatDebug(QDebug &d) const +{ + ComplexTypeEntry::formatDebug(d); + d << ", type=" << m_type << ",\"" << typeName() << '"'; +} + QDebug operator<<(QDebug d, const TypeEntry *te) { QDebugStateSaver saver(d); d.noquote(); d.nospace(); d << "TypeEntry("; - if (te) { - 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(); - if (const int count = extraIncludes.size()) { - d << ", extraIncludes[" << count << "]="; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - d << extraIncludes.at(i); - } - } - } else { + if (te) + te->formatDebug(d); + else d << '0'; - } d << ')'; return d; } @@ -732,25 +859,14 @@ QDebug operator<<(QDebug d, const TemplateEntry *te) void TypeDatabase::formatDebug(QDebug &d) const { - typedef TypeEntryHash::ConstIterator Eit; - typedef SingleTypeEntryHash::ConstIterator Sit; - typedef TemplateEntryHash::ConstIterator TplIt; d << "TypeDatabase(" << "entries[" << m_entries.size() << "]="; - for (Eit it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { - const int count = it.value().size(); - d << '"' << it.key() << "\" [" << count << "]: ("; - for (int t = 0; t < count; ++t) { - if (t) - d << ", "; - d << it.value().at(t); - } - d << ")\n"; - } + for (auto it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) + d << " " << it.value() << '\n'; if (!m_templates.isEmpty()) { d << "templates[" << m_templates.size() << "]=("; - const TplIt begin = m_templates.cbegin(); - for (TplIt it = begin, end = m_templates.cend(); it != end; ++it) { + const auto begin = m_templates.cbegin(); + for (auto it = begin, end = m_templates.cend(); it != end; ++it) { if (it != begin) d << ", "; d << it.value(); @@ -759,15 +875,17 @@ void TypeDatabase::formatDebug(QDebug &d) const } if (!m_flagsEntries.isEmpty()) { d << "flags[" << m_flagsEntries.size() << "]=("; - const Sit begin = m_flagsEntries.cbegin(); - for (Sit it = begin, end = m_flagsEntries.cend(); it != end; ++it) { + const auto begin = m_flagsEntries.cbegin(); + for (auto it = begin, end = m_flagsEntries.cend(); it != end; ++it) { if (it != begin) d << ", "; d << it.value(); } d << ")\n"; } - d <<"\nglobalUserFunctions=" << m_globalUserFunctions << ')'; + d <<"\nglobalUserFunctions=" << m_globalUserFunctions << '\n'; + formatList(d, "globalFunctionMods", m_functionMods, '\n'); + d << ')'; } QDebug operator<<(QDebug d, const TypeDatabase &db) |