aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-11-03 15:22:50 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-11-05 15:09:24 +0000
commit3019e2079a55d0eea252495954ee784652bca46b (patch)
tree90b33ff666d12f59b0fe82135c17d27f3a96a52e
parentce954a1cec8e7cd44cdad09bcda8f9f6d9aaa83d (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>
-rw-r--r--sources/shiboken6/ApiExtractor/CMakeLists.txt1
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp3
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp391
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h152
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.cpp413
-rw-r--r--sources/shiboken6/ApiExtractor/parser/typeinfo.h168
-rw-r--r--sources/shiboken6/ApiExtractor/typeparser.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/typeparser.h1
8 files changed, 598 insertions, 533 deletions
diff --git a/sources/shiboken6/ApiExtractor/CMakeLists.txt b/sources/shiboken6/ApiExtractor/CMakeLists.txt
index e1b1f64e4..ec9c55364 100644
--- a/sources/shiboken6/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken6/ApiExtractor/CMakeLists.txt
@@ -30,6 +30,7 @@ clangparser/clangbuilder.cpp
clangparser/clangdebugutils.cpp
clangparser/clangutils.cpp
# Old parser
+parser/typeinfo.cpp
parser/codemodel.cpp
parser/enumvalue.cpp
xmlutils.cpp
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 3bcc35048..122ea374f 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -2670,10 +2670,9 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
const AbstractMetaClass *templateClass,
const TypeInfo &info)
{
- QVector<TypeInfo> targs = info.instantiations();
AbstractMetaTypeList templateTypes;
- for (const TypeInfo &i : qAsConst(targs)) {
+ for (const TypeInfo &i : info.instantiations()) {
QString typeName = i.qualifiedName().join(colonColon());
TypeDatabase *typeDb = TypeDatabase::instance();
TypeEntry *t = nullptr;
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) {
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h
index 13bc7cf36..e3ff4cf70 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h
@@ -34,6 +34,7 @@
#include "codemodel_fwd.h"
#include "codemodel_enums.h"
#include "enumvalue.h"
+#include "typeinfo.h"
#include <QtCore/QHash>
#include <QtCore/QPair>
@@ -97,157 +98,6 @@ private:
QDebug operator<<(QDebug d, const CodeModel *m);
#endif
-class TypeInfo
-{
- friend class TypeParser;
-public:
- using Indirections = QVector<Indirection>;
-
- TypeInfo() : flags(0), m_referenceType(NoReference) {}
-
- QStringList qualifiedName() const
- {
- return m_qualifiedName;
- }
-
- void setQualifiedName(const QStringList &qualified_name)
- {
- m_qualifiedName = qualified_name;
- }
-
- bool isVoid() const;
-
- bool isConstant() const
- {
- return m_constant;
- }
-
- void setConstant(bool is)
- {
- m_constant = is;
- }
-
- bool isVolatile() const
- {
- return m_volatile;
- }
-
- void setVolatile(bool is)
- {
- m_volatile = is;
- }
-
- ReferenceType referenceType() const { return m_referenceType; }
- void setReferenceType(ReferenceType r) { m_referenceType = r; }
-
- Indirections indirectionsV() const { return m_indirections; }
- void setIndirectionsV(const Indirections &i) { m_indirections = i; }
- void addIndirection(Indirection i) { m_indirections.append(i); }
-
- // "Legacy", rename?
- int indirections() const { return m_indirections.size(); }
-
- void setIndirections(int indirections)
- {
- m_indirections = Indirections(indirections, Indirection::Pointer);
- }
-
- bool isFunctionPointer() const
- {
- return m_functionPointer;
- }
- void setFunctionPointer(bool is)
- {
- m_functionPointer = is;
- }
-
- QStringList arrayElements() const
- {
- return m_arrayElements;
- }
- void setArrayElements(const QStringList &arrayElements)
- {
- m_arrayElements = arrayElements;
- }
-
- void addArrayElement(const QString &a) { m_arrayElements.append(a); }
-
- QVector<TypeInfo> arguments() const { return m_arguments; }
-
- void setArguments(const QVector<TypeInfo> &arguments);
-
- void addArgument(const TypeInfo &arg)
- {
- m_arguments.append(arg);
- }
-
- QVector<TypeInfo> instantiations() const { return m_instantiations; }
- void setInstantiations(const QVector<TypeInfo> &i) { m_instantiations = i; }
- void addInstantiation(const TypeInfo &i) { m_instantiations.append(i); }
- void clearInstantiations() { m_instantiations.clear(); }
-
- bool isStdType() const;
-
- QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0);
-
- bool operator==(const TypeInfo &other) const;
-
- bool operator!=(const TypeInfo &other) const
- {
- return !(*this == other);
- }
-
- // ### arrays and templates??
-
- QString toString() const;
-
- static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs);
- static TypeInfo resolveType(TypeInfo const &__type, const ScopeModelItem &__scope);
-
- void formatTypeSystemSignature(QTextStream &str) const;
-
-#ifndef QT_NO_DEBUG_STREAM
- void formatDebug(QDebug &d) const;
-#endif
-
- static QString indirectionKeyword(Indirection i);
-
- static bool stripLeadingConst(QString *s);
- static bool stripLeadingVolatile(QString *s);
- static bool stripLeadingQualifier(const QString &qualifier, QString *s);
- static void stripQualifiers(QString *s);
-
- void simplifyStdType();
-
-private:
- friend class TypeInfoTemplateArgumentHandler;
-
- static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope);
-
- QStringList m_qualifiedName;
- QStringList m_arrayElements;
- QVector<TypeInfo> m_arguments;
- QVector<TypeInfo> m_instantiations;
- Indirections m_indirections;
-
- union {
- uint flags;
-
- struct {
- uint m_constant: 1;
- uint m_volatile: 1;
- uint m_functionPointer: 1;
- uint m_padding: 29;
- };
- };
-
- ReferenceType m_referenceType;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const TypeInfo &t);
-#endif
-
class _CodeModelItem
{
Q_DISABLE_COPY(_CodeModelItem)
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
new file mode 100644
index 000000000..0765e9c9e
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.cpp
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "typeinfo.h"
+#include "codemodel.h"
+
+#include <clangparser/clangutils.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QStack>
+#include <QtCore/QTextStream>
+
+#include <iostream>
+
+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();
+ const 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::equals(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
diff --git a/sources/shiboken6/ApiExtractor/parser/typeinfo.h b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
new file mode 100644
index 000000000..74987493d
--- /dev/null
+++ b/sources/shiboken6/ApiExtractor/parser/typeinfo.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TYPEINFO_H
+#define TYPEINFO_H
+
+#include "codemodel_enums.h"
+#include "codemodel_fwd.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+class TypeInfo
+{
+ friend class TypeParser;
+public:
+ using Indirections = QList<Indirection>;
+ using TypeInfoList = QList<TypeInfo>;
+
+ TypeInfo() : flags(0), m_referenceType(NoReference) {}
+
+ QStringList qualifiedName() const { return m_qualifiedName; }
+ void setQualifiedName(const QStringList &qualified_name)
+ {
+ m_qualifiedName = qualified_name;
+ }
+
+ bool isVoid() const;
+
+ bool isConstant() const { return m_constant; }
+ void setConstant(bool is) { m_constant = is; }
+
+ bool isVolatile() const { return m_volatile; }
+
+ void setVolatile(bool is) { m_volatile = is; }
+
+ ReferenceType referenceType() const { return m_referenceType; }
+ void setReferenceType(ReferenceType r) { m_referenceType = r; }
+
+ const Indirections &indirectionsV() const { return m_indirections; }
+ void setIndirectionsV(const Indirections &i) { m_indirections = i; }
+ void addIndirection(Indirection i) { m_indirections.append(i); }
+
+ // "Legacy", rename?
+ int indirections() const { return m_indirections.size(); }
+
+ void setIndirections(int indirections)
+ {
+ m_indirections = Indirections(indirections, Indirection::Pointer);
+ }
+
+ bool isFunctionPointer() const { return m_functionPointer; }
+ void setFunctionPointer(bool is) { m_functionPointer = is; }
+
+ const QStringList &arrayElements() const { return m_arrayElements; }
+ void setArrayElements(const QStringList &arrayElements)
+ {
+ m_arrayElements = arrayElements;
+ }
+
+ void addArrayElement(const QString &a) { m_arrayElements.append(a); }
+
+ const TypeInfoList &arguments() const { return m_arguments; }
+ void setArguments(const TypeInfoList &arguments);
+
+ void addArgument(const TypeInfo &arg)
+ {
+ m_arguments.append(arg);
+ }
+
+ const TypeInfoList &instantiations() const { return m_instantiations; }
+ void setInstantiations(const TypeInfoList &i) { m_instantiations = i; }
+ void addInstantiation(const TypeInfo &i) { m_instantiations.append(i); }
+ void clearInstantiations() { m_instantiations.clear(); }
+
+ bool isStdType() const;
+
+ QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0);
+
+ bool equals(const TypeInfo &other) const;
+
+ // ### arrays and templates??
+
+ QString toString() const;
+
+ static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs);
+ static TypeInfo resolveType(TypeInfo const &__type, const ScopeModelItem &__scope);
+
+ void formatTypeSystemSignature(QTextStream &str) const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+ static QString indirectionKeyword(Indirection i);
+
+ static bool stripLeadingConst(QString *s);
+ static bool stripLeadingVolatile(QString *s);
+ static bool stripLeadingQualifier(const QString &qualifier, QString *s);
+ static void stripQualifiers(QString *s);
+
+ void simplifyStdType();
+
+private:
+ friend class TypeInfoTemplateArgumentHandler;
+
+ static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope);
+
+ QStringList m_qualifiedName;
+ QStringList m_arrayElements;
+ QList<TypeInfo> m_arguments;
+ QList<TypeInfo> m_instantiations;
+ Indirections m_indirections;
+
+ union {
+ uint flags;
+
+ struct {
+ uint m_constant: 1;
+ uint m_volatile: 1;
+ uint m_functionPointer: 1;
+ uint m_padding: 29;
+ };
+ };
+
+ ReferenceType m_referenceType;
+};
+
+inline bool operator==(const TypeInfo &t1, const TypeInfo &t2)
+{ return t1.equals(t2); }
+
+inline bool operator!=(const TypeInfo &t1, const TypeInfo &t2)
+{ return !t1.equals(t2); }
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const TypeInfo &t);
+#endif
+
+#endif // TYPEINFO_H
diff --git a/sources/shiboken6/ApiExtractor/typeparser.cpp b/sources/shiboken6/ApiExtractor/typeparser.cpp
index c440fb66d..08063af48 100644
--- a/sources/shiboken6/ApiExtractor/typeparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typeparser.cpp
@@ -27,7 +27,7 @@
****************************************************************************/
#include "typeparser.h"
-#include <codemodel.h>
+#include <typeinfo.h>
#include <QtCore/QDebug>
#include <QtCore/QStack>
diff --git a/sources/shiboken6/ApiExtractor/typeparser.h b/sources/shiboken6/ApiExtractor/typeparser.h
index 3b538017a..2359da7b2 100644
--- a/sources/shiboken6/ApiExtractor/typeparser.h
+++ b/sources/shiboken6/ApiExtractor/typeparser.h
@@ -32,7 +32,6 @@
#include "parser/codemodel_enums.h"
#include <QtCore/QString>
-#include <QtCore/QVector>
class TypeInfo;