diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-03 15:22:50 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-05 15:09:24 +0000 |
| commit | 3019e2079a55d0eea252495954ee784652bca46b (patch) | |
| tree | 90b33ff666d12f59b0fe82135c17d27f3a96a52e /sources/shiboken6/ApiExtractor/parser/codemodel.cpp | |
| parent | ce954a1cec8e7cd44cdad09bcda8f9f6d9aaa83d (diff) | |
shiboken6: Split out class TypeInfo
This is the first step towards using it in AddedFunction
as well, replacing AddedFunction::TypeInfo.
Change list accessors to return const-ref on this occasion.
Change-Id: I78a7be0b3cb738b859519b7fbff8ed024fb46106
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken6/ApiExtractor/parser/codemodel.cpp')
| -rw-r--r-- | sources/shiboken6/ApiExtractor/parser/codemodel.cpp | 391 |
1 files changed, 13 insertions, 378 deletions
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp index 76ce333ed..8e1cb9710 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp @@ -31,14 +31,13 @@ #include "codemodel.h" #include <sourcelocation.h> -#include <clangparser/clangutils.h> + +#include <QtCore/QDebug> +#include <QtCore/QDir> #include <algorithm> #include <functional> #include <iostream> -#include <QDebug> -#include <QDir> -#include <QtCore/QStack> // Predicate to find an item by name in a list of QSharedPointer<Item> template <class T> class ModelItemNamePredicate @@ -134,380 +133,6 @@ QDebug operator<<(QDebug d, const CodeModel *m) #endif // !QT_NO_DEBUG_STREAM // --------------------------------------------------------------------------- -TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) -{ - TypeInfo __result = __lhs; - - __result.setConstant(__result.isConstant() || __rhs.isConstant()); - __result.setVolatile(__result.isVolatile() || __rhs.isVolatile()); - if (__rhs.referenceType() > __result.referenceType()) - __result.setReferenceType(__rhs.referenceType()); - __result.m_indirections.append(__rhs.m_indirections); - __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); - __result.m_instantiations.append(__rhs.m_instantiations); - - return __result; -} - -bool TypeInfo::isVoid() const -{ - return m_indirections.isEmpty() && m_referenceType == NoReference - && m_arguments.isEmpty() && m_arrayElements.isEmpty() - && m_instantiations.isEmpty() - && m_qualifiedName.size() == 1 - && m_qualifiedName.constFirst() == QLatin1String("void"); -} - -TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope) -{ - CodeModel *__model = __scope->model(); - Q_ASSERT(__model != nullptr); - - return TypeInfo::resolveType(__model->findItem(__type.qualifiedName(), __scope), __type, __scope); -} - -TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, const ScopeModelItem &__scope) -{ - // Copy the type and replace with the proper qualified name. This - // only makes sence to do if we're actually getting a resolved - // type with a namespace. We only get this if the returned type - // has more than 2 entries in the qualified name... This test - // could be improved by returning if the type was found or not. - TypeInfo otherType(__type); - if (__item && __item->qualifiedName().size() > 1) { - otherType.setQualifiedName(__item->qualifiedName()); - } - - if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_TypeDefModelItem>(__item)) { - const TypeInfo combined = TypeInfo::combine(__typedef->type(), otherType); - const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); - if (!nextItem) - return combined; - // PYSIDE-362, prevent recursion on opaque structs like - // typedef struct xcb_connection_t xcb_connection_t; - if (nextItem.data() ==__item.data()) { - std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__ - << "() on " << qPrintable(__type.qualifiedName().join(QLatin1String("::"))) - << std::endl; - return otherType; - } - return resolveType(nextItem, combined, __scope); - } - - if (TemplateTypeAliasModelItem templateTypeAlias = qSharedPointerDynamicCast<_TemplateTypeAliasModelItem>(__item)) { - - TypeInfo combined = TypeInfo::combine(templateTypeAlias->type(), otherType); - // For the alias "template<typename T> using QList = QVector<T>" with - // other="QList<int>", replace the instantiations to obtain "QVector<int>". - auto aliasInstantiations = templateTypeAlias->type().instantiations(); - auto concreteInstantiations = otherType.instantiations(); - const int count = qMin(aliasInstantiations.size(), concreteInstantiations.size()); - for (int i = 0; i < count; ++i) - aliasInstantiations[i] = concreteInstantiations[i]; - combined.setInstantiations(aliasInstantiations); - const CodeModelItem nextItem = __scope->model()->findItem(combined.qualifiedName(), __scope); - if (!nextItem) - return combined; - return resolveType(nextItem, combined, __scope); - } - - return otherType; -} - -// Handler for clang::parseTemplateArgumentList() that populates -// TypeInfo::m_instantiations -class TypeInfoTemplateArgumentHandler -{ -public: - explicit TypeInfoTemplateArgumentHandler(TypeInfo *t) - { - m_parseStack.append(t); - } - - void operator()(int level, QStringView name) - { - if (level > m_parseStack.size()) { - Q_ASSERT(!top()->m_instantiations.isEmpty()); - m_parseStack.push(&top()->m_instantiations.back()); - } - while (level < m_parseStack.size()) - m_parseStack.pop(); - TypeInfo instantiation; - instantiation.setQualifiedName(qualifiedName(name)); - top()->addInstantiation(instantiation); - } - -private: - TypeInfo *top() const { return m_parseStack.back(); } - - static QStringList qualifiedName(QStringView name) - { - QStringList result; - const auto nameParts = name.split(u"::"); - result.reserve(nameParts.size()); - for (const auto &p : nameParts) - result.append(p.toString()); - return result; - } - - QStack<TypeInfo *> m_parseStack; -}; - -QPair<int, int> TypeInfo::parseTemplateArgumentList(const QString &l, int from) -{ - return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from); -} - -QString TypeInfo::toString() const -{ - QString tmp; - if (isConstant()) - tmp += QLatin1String("const "); - - if (isVolatile()) - tmp += QLatin1String("volatile "); - - tmp += m_qualifiedName.join(QLatin1String("::")); - - if (const int instantiationCount = m_instantiations.size()) { - tmp += QLatin1Char('<'); - for (int i = 0; i < instantiationCount; ++i) { - if (i) - tmp += QLatin1String(", "); - tmp += m_instantiations.at(i).toString(); - } - if (tmp.endsWith(QLatin1Char('>'))) - tmp += QLatin1Char(' '); - tmp += QLatin1Char('>'); - } - - for (Indirection i : m_indirections) - tmp.append(indirectionKeyword(i)); - - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - tmp += QLatin1Char('&'); - break; - case RValueReference: - tmp += QLatin1String("&&"); - break; - } - - if (isFunctionPointer()) { - tmp += QLatin1String(" (*)("); - for (int i = 0; i < m_arguments.count(); ++i) { - if (i != 0) - tmp += QLatin1String(", "); - - tmp += m_arguments.at(i).toString(); - } - tmp += QLatin1Char(')'); - } - - for (const QString &elt : m_arrayElements) { - tmp += QLatin1Char('['); - tmp += elt; - tmp += QLatin1Char(']'); - } - - return tmp; -} - -bool TypeInfo::operator==(const TypeInfo &other) const -{ - if (arrayElements().count() != other.arrayElements().count()) - return false; - -#if defined (RXX_CHECK_ARRAY_ELEMENTS) // ### it'll break - for (int i = 0; i < arrayElements().count(); ++i) { - QString elt1 = arrayElements().at(i).trimmed(); - QString elt2 = other.arrayElements().at(i).trimmed(); - - if (elt1 != elt2) - return false; - } -#endif - - return flags == other.flags - && m_qualifiedName == other.m_qualifiedName - && (!m_functionPointer || m_arguments == other.m_arguments) - && m_instantiations == other.m_instantiations; -} - -QString TypeInfo::indirectionKeyword(Indirection i) -{ - return i == Indirection::Pointer - ? QStringLiteral("*") : QStringLiteral("*const"); -} - -static inline QString constQualifier() { return QStringLiteral("const"); } -static inline QString volatileQualifier() { return QStringLiteral("volatile"); } - -bool TypeInfo::stripLeadingConst(QString *s) -{ - return stripLeadingQualifier(constQualifier(), s); -} - -bool TypeInfo::stripLeadingVolatile(QString *s) -{ - return stripLeadingQualifier(volatileQualifier(), s); -} - -bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s) -{ - // "const int x" - const int qualifierSize = qualifier.size(); - if (s->size() < qualifierSize + 1 || !s->startsWith(qualifier) - || !s->at(qualifierSize).isSpace()) { - return false; - } - s->remove(0, qualifierSize + 1); - while (!s->isEmpty() && s->at(0).isSpace()) - s->remove(0, 1); - return true; -} - -// Strip all const/volatile/*/& -void TypeInfo::stripQualifiers(QString *s) -{ - stripLeadingConst(s); - stripLeadingVolatile(s); - while (s->endsWith(QLatin1Char('&')) || s->endsWith(QLatin1Char('*')) - || s->endsWith(QLatin1Char(' '))) { - s->chop(1); - } -} - -// Helper functionality to simplify a raw standard type as returned by -// clang_getCanonicalType() for g++ standard containers from -// "std::__cxx11::list<int, std::allocator<int> >" or -// "std::__1::list<int, std::allocator<int> >" -> "std::list<int>". - -bool TypeInfo::isStdType() const -{ - return m_qualifiedName.size() > 1 - && m_qualifiedName.constFirst() == QLatin1String("std"); -} - -static inline bool discardStdType(const QString &name) -{ - return name == QLatin1String("allocator") || name == QLatin1String("less"); -} - -void TypeInfo::simplifyStdType() -{ - if (isStdType()) { - if (m_qualifiedName.at(1).startsWith(QLatin1String("__"))) - m_qualifiedName.removeAt(1); - for (int t = m_instantiations.size() - 1; t >= 0; --t) { - if (m_instantiations.at(t).isStdType()) { - if (discardStdType(m_instantiations.at(t).m_qualifiedName.constLast())) - m_instantiations.removeAt(t); - else - m_instantiations[t].simplifyStdType(); - } - } - } -} - -void TypeInfo::formatTypeSystemSignature(QTextStream &str) const -{ - if (m_constant) - str << "const "; - str << m_qualifiedName.join(QLatin1String("::")); - switch (m_referenceType) { - case NoReference: - break; - case LValueReference: - str << '&'; - break; - case RValueReference: - str << "&&"; - break; - } - for (auto i : m_indirections) { - switch (i) { - case Indirection::Pointer: - str << '*'; - break; - case Indirection::ConstPointer: - str << "* const"; - break; - } - } -} - -#ifndef QT_NO_DEBUG_STREAM -template <class It> -void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") -{ - for (It i = i1; i != i2; ++i) { - if (i != i1) - d << separator; - d << *i; - } -} - -void TypeInfo::formatDebug(QDebug &d) const -{ - d << '"'; - formatSequence(d, m_qualifiedName.begin(), m_qualifiedName.end(), "\", \""); - d << '"'; - if (m_constant) - d << ", [const]"; - if (m_volatile) - d << ", [volatile]"; - if (!m_indirections.isEmpty()) { - d << ", indirections="; - for (auto i : m_indirections) - d << ' ' << TypeInfo::indirectionKeyword(i); - } - switch (m_referenceType) { - case NoReference: - break; - case LValueReference: - d << ", [ref]"; - break; - case RValueReference: - d << ", [rvalref]"; - break; - } - if (!m_instantiations.isEmpty()) { - d << ", template<"; - formatSequence(d, m_instantiations.begin(), m_instantiations.end()); - d << '>'; - } - if (m_functionPointer) { - d << ", function ptr("; - formatSequence(d, m_arguments.begin(), m_arguments.end()); - d << ')'; - } - if (!m_arrayElements.isEmpty()) { - d << ", array[" << m_arrayElements.size() << "]["; - formatSequence(d, m_arrayElements.begin(), m_arrayElements.end()); - d << ']'; - } -} - -QDebug operator<<(QDebug d, const TypeInfo &t) -{ - QDebugStateSaver s(d); - const int verbosity = d.verbosity(); - d.noquote(); - d.nospace(); - d << "TypeInfo("; - if (verbosity > 2) - t.formatDebug(d); - else - d << t.toString(); - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- _CodeModelItem::_CodeModelItem(CodeModel *model, int kind) : m_model(model), m_kind(kind), @@ -612,6 +237,16 @@ SourceLocation _CodeModelItem::sourceLocation() const #ifndef QT_NO_DEBUG_STREAM template <class It> +void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ") +{ + for (It i = i1; i != i2; ++i) { + if (i != i1) + d << separator; + d << *i; + } +} + +template <class It> static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ") { for (It i = i1; i != i2; ++i) { |
