aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2019-07-04 13:25:31 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-01-06 16:05:36 +0100
commit3bc59fc8a2a2e36916bd2c4557b8fb48329085f3 (patch)
treeaeebf1f35c4b5e99a808e5c2c4903bf1fa03a10c
parente4aa9e13ac6e4d38c473fc32ea4ace3777df7a57 (diff)
shiboken/typedatabase: Match multiple type entries by name
For smart pointer instantiations, type entries from multiple modules need to be searched, which is currently not implemented. Extend the type database to return all type entries by name. Split out the code finding a type entry from AbstractMetaBuilderPrivate::translateType() and change it return a list. Ignore duplicate primitive types for now since that cannot be easily avoided. Task-number: PYSIDE-1024 Change-Id: I4a30b9151b472acff5fba221019a2e321807d4a0 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp114
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h3
-rw-r--r--sources/shiboken2/ApiExtractor/messages.cpp23
-rw-r--r--sources/shiboken2/ApiExtractor/messages.h4
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp74
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h6
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h9
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_typedefs.h2
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp10
9 files changed, 193 insertions, 52 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index f6c9e407c..e48d2b17c 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -2096,6 +2096,52 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC
return type;
}
+// Helper for translateTypeStatic()
+TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
+ const QString &name,
+ AbstractMetaClass *currentClass,
+ AbstractMetaBuilderPrivate *d)
+{
+ // 5.1 - Try first using the current scope
+ if (currentClass) {
+ if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName))
+ return {type};
+
+ // 5.1.1 - Try using the class parents' scopes
+ if (d && !currentClass->baseClassNames().isEmpty()) {
+ const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
+ for (const AbstractMetaClass *cls : baseClasses) {
+ if (auto type = findTypeEntryUsingContext(cls, qualifiedName))
+ return {type};
+ }
+ }
+ }
+
+ // 5.2 - Try without scope
+ auto types = TypeDatabase::instance()->findCppTypes(qualifiedName);
+ if (!types.isEmpty())
+ return types;
+
+ // 6. No? Try looking it up as a flags type
+ if (auto type = TypeDatabase::instance()->findFlagsType(qualifiedName))
+ return {type};
+
+ // 7. No? Try looking it up as a container type
+ if (auto type = TypeDatabase::instance()->findContainerType(name))
+ return {type};
+
+ // 8. No? Check if the current class is a template and this type is one
+ // of the parameters.
+ if (currentClass) {
+ const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
+ for (TypeEntry *te : template_args) {
+ if (te->name() == qualifiedName)
+ return {te};
+ }
+ }
+ return {};
+}
+
AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
AbstractMetaClass *currentClass,
TranslateTypeFlags flags,
@@ -2228,57 +2274,43 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo
typeInfo.clearInstantiations();
}
- const TypeEntry *type = nullptr;
- // 5. Try to find the type
-
- // 5.1 - Try first using the current scope
- if (currentClass) {
- type = findTypeEntryUsingContext(currentClass, qualifiedName);
-
- // 5.1.1 - Try using the class parents' scopes
- if (!type && d && !currentClass->baseClassNames().isEmpty()) {
- const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
- for (const AbstractMetaClass *cls : baseClasses) {
- type = findTypeEntryUsingContext(cls, qualifiedName);
- if (type)
- break;
- }
+ const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d);
+ if (types.isEmpty()) {
+ if (errorMessageIn) {
+ *errorMessageIn =
+ msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName));
}
+ return nullptr;
}
- // 5.2 - Try without scope
- if (!type)
- type = TypeDatabase::instance()->findType(qualifiedName);
+ const TypeEntry *type = types.constFirst();
+ const TypeEntry::Type typeEntryType = type->type();
- // 6. No? Try looking it up as a flags type
- if (!type)
- type = TypeDatabase::instance()->findFlagsType(qualifiedName);
-
- // 7. No? Try looking it up as a container type
- if (!type)
- type = TypeDatabase::instance()->findContainerType(name);
+ // These are only implicit and should not appear in code...
+ if (typeEntryType == TypeEntry::InterfaceType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgInterfaceTypeFound(qualifiedName);
- // 8. No? Check if the current class is a template and this type is one
- // of the parameters.
- if (!type && currentClass) {
- const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
- for (TypeEntry *te : template_args) {
- if (te->name() == qualifiedName)
- type = te;
- }
+ return nullptr;
}
- if (!type) {
- if (errorMessageIn) {
- *errorMessageIn =
- msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName));
+ if (types.size() > 1) {
+ const bool sameType = std::all_of(types.cbegin() + 1, types.cend(),
+ [typeEntryType](const TypeEntry *e) {
+ return e->type() == typeEntryType; });
+ if (!sameType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgAmbiguousVaryingTypesFound(qualifiedName, types);
+ return nullptr;
+ }
+ // Ambiguous primitive types are possible (when including type systems).
+ if (typeEntryType != TypeEntry::PrimitiveType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types);
+ return nullptr;
}
- return nullptr;
}
- // These are only implicit and should not appear in code...
- Q_ASSERT(!type->isInterface());
-
auto *metaType = new AbstractMetaType;
metaType->setTypeEntry(type);
metaType->setIndirectionsV(typeInfo.indirectionsV());
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
index b381a62cd..e3c9e1a72 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
@@ -146,6 +146,9 @@ public:
AbstractMetaBuilderPrivate *d = nullptr,
TranslateTypeFlags flags = {},
QString *errorMessageIn = nullptr);
+ static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name,
+ AbstractMetaClass *currentClass = nullptr,
+ AbstractMetaBuilderPrivate *d = nullptr);
qint64 findOutValueFromString(const QString &stringValue, bool &ok);
diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp
index d4cf53efe..fb9dd573a 100644
--- a/sources/shiboken2/ApiExtractor/messages.cpp
+++ b/sources/shiboken2/ApiExtractor/messages.cpp
@@ -28,6 +28,7 @@
#include "messages.h"
#include "abstractmetalang.h"
+#include "typedatabase.h"
#include "typesystem.h"
#include <codemodel.h>
@@ -130,6 +131,28 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
return result;
}
+QString msgInterfaceTypeFound(const QString &qualifiedName)
+{
+ return QLatin1String("Interface type found for \"") + qualifiedName
+ + QLatin1String("\".");
+}
+
+QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te)
+{
+ QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName
+ + QLatin1String("\": ");
+ QDebug(&result) << te;
+ return result;
+}
+
+QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te)
+{
+ QString result = QLatin1String("Ambiguous types found for \"") + qualifiedName
+ + QLatin1String("\": ");
+ QDebug(&result) << te;
+ return result;
+}
+
QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n,
const QString &why)
{
diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h
index 2b7b75ba0..944cb231e 100644
--- a/sources/shiboken2/ApiExtractor/messages.h
+++ b/sources/shiboken2/ApiExtractor/messages.h
@@ -59,6 +59,10 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem,
const QString &className,
const TypeEntry *t);
+QString msgInterfaceTypeFound(const QString &qualifiedName);
+QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te);
+QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te);
+
QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n,
const QString &why);
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp
index c952f7b0e..1d2c04748 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp
@@ -185,7 +185,7 @@ static bool inline useType(const TypeEntry *t)
FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const
{
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (entry->type() == TypeEntry::FunctionType && useType(entry))
return static_cast<FunctionTypeEntry*>(entry);
@@ -220,7 +220,7 @@ QString TypeDatabase::defaultPackageName() const
TypeEntry* TypeDatabase::findType(const QString& name) const
{
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (useType(entry))
return entry;
@@ -228,7 +228,54 @@ TypeEntry* TypeDatabase::findType(const QString& name) const
return nullptr;
}
-TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypes(const QString &name) const
+template <class Predicate>
+TypeEntries TypeDatabase::findTypesHelper(const QString &name, Predicate pred) const
+{
+ TypeEntries result;
+ const auto entries = findTypeRange(name);
+ for (TypeEntry *entry : entries) {
+ if (pred(entry))
+ result.append(entry);
+ }
+ return result;
+}
+
+TypeEntries TypeDatabase::findTypes(const QString &name) const
+{
+ return findTypesHelper(name, useType);
+}
+
+static bool useCppType(const TypeEntry *t)
+{
+ bool result = false;
+ switch (t->type()) {
+ case TypeEntry::PrimitiveType:
+ case TypeEntry::VoidType:
+ case TypeEntry::FlagsType:
+ case TypeEntry::EnumType:
+ case TypeEntry::TemplateArgumentType:
+ case TypeEntry::BasicValueType:
+ case TypeEntry::ContainerType:
+ case TypeEntry::InterfaceType:
+ case TypeEntry::ObjectType:
+ case TypeEntry::ArrayType:
+ case TypeEntry::CustomType:
+ case TypeEntry::SmartPointerType:
+ case TypeEntry::TypedefType:
+ result = useType(t);
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+TypeEntries TypeDatabase::findCppTypes(const QString &name) const
+{
+ return findTypesHelper(name, useCppType);
+}
+
+TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypeRange(const QString &name) const
{
const auto range = m_entries.equal_range(name);
return {range.first, range.second};
@@ -341,7 +388,7 @@ TypeEntry *TypeDatabase::resolveTypeDefEntry(TypedefEntry *typedefEntry,
if (lessThanPos != -1)
sourceName.truncate(lessThanPos);
ComplexTypeEntry *source = nullptr;
- for (TypeEntry *e : findTypes(sourceName)) {
+ for (TypeEntry *e : findTypeRange(sourceName)) {
switch (e->type()) {
case TypeEntry::BasicValueType:
case TypeEntry::ContainerType:
@@ -600,7 +647,7 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate)
PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const
{
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (entry->isPrimitive()) {
auto *pe = static_cast<PrimitiveTypeEntry *>(entry);
@@ -614,7 +661,7 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const
ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const
{
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (entry->isComplex() && useType(entry))
return static_cast<ComplexTypeEntry*>(entry);
@@ -624,7 +671,7 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const
ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const
{
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (entry && entry->isObject() && useType(entry))
return static_cast<ObjectTypeEntry*>(entry);
@@ -635,7 +682,7 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const
NamespaceTypeEntryList TypeDatabase::findNamespaceTypes(const QString& name) const
{
NamespaceTypeEntryList result;
- const auto entries = findTypes(name);
+ const auto entries = findTypeRange(name);
for (TypeEntry *entry : entries) {
if (entry->isNamespace())
result.append(static_cast<NamespaceTypeEntry*>(entry));
@@ -907,6 +954,17 @@ void ContainerTypeEntry::formatDebug(QDebug &d) const
d << ", type=" << m_type << ",\"" << typeName() << '"';
}
+void SmartPointerTypeEntry::formatDebug(QDebug &d) const
+{
+ ComplexTypeEntry::formatDebug(d);
+ if (!m_instantiations.isEmpty()) {
+ d << ", instantiations[" << m_instantiations.size() << "]=(";
+ for (auto i : m_instantiations)
+ d << i->name() << ',';
+ d << ')';
+ }
+}
+
QDebug operator<<(QDebug d, const TypeEntry *te)
{
QDebugStateSaver saver(d);
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h
index f1bd0ac9f..23c2b933b 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.h
+++ b/sources/shiboken2/ApiExtractor/typedatabase.h
@@ -101,6 +101,8 @@ public:
QString defaultPackageName() const;
TypeEntry *findType(const QString &name) const;
+ TypeEntries findTypes(const QString &name) const;
+ TypeEntries findCppTypes(const QString &name) const;
const TypeEntryMultiMap &entries() const { return m_entries; }
const TypedefEntryMap &typedefEntries() const { return m_typedefEntries; }
@@ -172,7 +174,9 @@ public:
void formatDebug(QDebug &d) const;
#endif
private:
- TypeEntryMultiMapConstIteratorRange findTypes(const QString &name) const;
+ TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const;
+ template <class Predicate>
+ TypeEntries findTypesHelper(const QString &name, Predicate pred) const;
TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage);
bool m_suppressWarnings = true;
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index d0739c19b..2ac3fd356 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -1465,6 +1465,8 @@ private:
class SmartPointerTypeEntry : public ComplexTypeEntry
{
public:
+ using Instantiations = QVector<const TypeEntry *>;
+
explicit SmartPointerTypeEntry(const QString &entryName,
const QString &getterName,
const QString &smartPointerType,
@@ -1484,6 +1486,12 @@ public:
TypeEntry *clone() const override;
+ Instantiations instantiations() const { return m_instantiations; }
+ void setInstantiations(const Instantiations &i) { m_instantiations = i; }
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const override;
+#endif
protected:
SmartPointerTypeEntry(const SmartPointerTypeEntry &);
@@ -1491,6 +1499,7 @@ private:
QString m_getterName;
QString m_smartPointerType;
QString m_refCountMethodName;
+ Instantiations m_instantiations;
};
class NamespaceTypeEntry : public ComplexTypeEntry
diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h
index fd702793e..73f92b294 100644
--- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h
+++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h
@@ -40,6 +40,7 @@ class DocModification;
struct AddedFunction;
struct FieldModification;
struct FunctionModification;
+class TypeEntry;
using AddedFunctionPtr = QSharedPointer<AddedFunction>;
using AddedFunctionList = QVector<AddedFunctionPtr>;
@@ -47,5 +48,6 @@ using CodeSnipList = QVector<CodeSnip>;
using DocModificationList = QVector<DocModification>;
using FieldModificationList = QVector<FieldModification>;
using FunctionModificationList = QVector<FunctionModification>;
+using TypeEntries = QVector<const TypeEntry *>;
#endif // TYPESYSTEM_TYPEDEFS_H
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 35bd363b5..647ceb67f 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -2550,13 +2550,19 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString &
QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP[");
int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP");
int start = 0;
+ QString errorMessage;
while ((start = code.indexOf(convMacro, start)) != -1) {
int end = code.indexOf(QLatin1Char(']'), start);
start += offset;
if (code.at(start) != QLatin1Char('%')) {
QString typeString = code.mid(start, end - start);
- AbstractMetaType *type = buildAbstractMetaTypeFromString(typeString);
- addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription());
+ if (AbstractMetaType *type =
+ buildAbstractMetaTypeFromString(typeString, &errorMessage)) {
+ addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription());
+ } else {
+ qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__,
+ qPrintable(typeString), qPrintable(errorMessage));
+ }
}
start = end;
}