From 021f8974a1784b37baaec4cfd1285dc44dfdab83 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 29 Oct 2020 16:23:52 +0100 Subject: shiboken6: Consolidate argument type parsing of added functions Use the same functionality that is used for argument type parsing of functions from the code model, which has a more powerful type search. This will for example enable specifying class template arguments (like QList::append(T)). Move the error handling from translateTypeStatic(TypeInfo,...) to the findTypeEntries() function, extracting a helper for the search, and use this in translateType(AddedFunction::TypeInfo,...). Task-number: PYSIDE-904 Task-number: PYSIDE-1339 Change-Id: I34428d76e811c3b1444a4d2ded0606e67c4dcf57 Reviewed-by: Cristian Maureira-Fredes --- .../shiboken6/ApiExtractor/abstractmetabuilder.cpp | 128 +++++++++++---------- .../shiboken6/ApiExtractor/abstractmetabuilder_p.h | 7 +- 2 files changed, 73 insertions(+), 62 deletions(-) (limited to 'sources') diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index b6e68bfde..3bcc35048 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -1532,7 +1532,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu { QString errorMessage; - AbstractMetaType returnType = translateType(addedFunc->returnType(), &errorMessage); + AbstractMetaType returnType = translateType(addedFunc->returnType(), metaClass, &errorMessage); if (!returnType) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidReturnType(addedFunc->name(), @@ -1549,7 +1549,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu for (int i = 0; i < args.count(); ++i) { const AddedFunction::TypeInfo& typeInfo = args.at(i).typeInfo; - AbstractMetaType type = translateType(typeInfo, &errorMessage); + AbstractMetaType type = translateType(typeInfo, metaClass, &errorMessage); if (Q_UNLIKELY(!type)) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidArgType(addedFunc->name(), @@ -1982,7 +1982,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } AbstractMetaType AbstractMetaBuilderPrivate::translateType(const AddedFunction::TypeInfo &typeInfo, - QString *errorMessage) + AbstractMetaClass *currentClass, + QString *errorMessage) { Q_ASSERT(!typeInfo.name.isEmpty()); TypeDatabase* typeDb = TypeDatabase::instance(); @@ -1992,14 +1993,11 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateType(const AddedFunction:: if (typeName == QLatin1String("void")) return AbstractMetaType::createVoid(); - TypeEntry *type = typeDb->findType(typeName); - if (!type) - type = typeDb->findFlagsType(typeName); - + const TypeEntry *type = nullptr; // test if the type is a template, like a container - bool isTemplate = false; QStringList templateArgs; - if (!type && typeInfo.name.contains(QLatin1Char('<'))) { + if (!typeInfo.name.startsWith(QLatin1String("QFlags<")) + && typeInfo.name.contains(QLatin1Char('<'))) { QStringList parsedType = parseTemplateType(typeInfo.name); if (parsedType.isEmpty()) { *errorMessage = QStringLiteral("Template type parsing failed for '%1'").arg(typeInfo.name); @@ -2014,29 +2012,17 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateType(const AddedFunction:: type = candidate; } } - isTemplate = type != nullptr; } - if (!type) { - QStringList candidates; - const auto &entries = typeDb->entries(); - for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - // Let's try to find the type in different scopes. - if (it.key().endsWith(colonColon() + typeName)) - candidates.append(it.key()); - } - QTextStream str(errorMessage); - str << "Type '" << typeName << "' wasn't found in the type database.\n"; - - if (candidates.isEmpty()) { - str << "Declare it in the type system using the proper <*-type> tag."; - } else { - str << "Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"; - candidates.sort(); - for (const QString& candidate : qAsConst(candidates)) - str << " " << candidate << '\n'; - } - return {}; + if (type == nullptr) { + QString unqualifiedName = typeName; + const int last = unqualifiedName.lastIndexOf(colonColon()); + if (last != -1) + unqualifiedName.remove(0, last + 2); + auto types = findTypeEntries(typeName, unqualifiedName, currentClass, this, errorMessage); + if (types.isEmpty()) + return {}; + type = types.constFirst(); } // These are only implicit and should not appear in code... @@ -2045,9 +2031,10 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateType(const AddedFunction:: if (typeInfo.isReference) metaType.setReferenceType(LValueReference); metaType.setConstant(typeInfo.isConstant); - if (isTemplate) { + if (!templateArgs.isEmpty()) { for (const QString& templateArg : qAsConst(templateArgs)) { - AbstractMetaType metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg), errorMessage); + AbstractMetaType metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg), + currentClass, errorMessage); if (!metaArgType) return {}; metaType.addInstantiation(metaArgType); @@ -2071,11 +2058,11 @@ 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) +// Helper for findTypeEntries/translateTypeStatic() +TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName, + const QString &name, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d) { // 5.1 - Try first using the current scope if (currentClass) { @@ -2117,6 +2104,46 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified return {}; } +// Helper for translateTypeStatic() that calls findTypeEntriesHelper() +// and does some error checking. +TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName, + const QString &name, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d, + QString *errorMessage) +{ + const TypeEntries types = findTypeEntriesHelper(qualifiedName, name, currentClass, d); + if (types.isEmpty()) { + if (errorMessage != nullptr) + *errorMessage = msgCannotFindTypeEntry(qualifiedName); + return {}; + } + + if (types.size() == 1) + return types; + + const auto typeEntryType = types.constFirst()->type(); + const bool sameType = std::all_of(types.cbegin() + 1, types.cend(), + [typeEntryType](const TypeEntry *e) { + return e->type() == typeEntryType; + }); + + if (!sameType) { + if (errorMessage != nullptr) + *errorMessage = msgAmbiguousVaryingTypesFound(qualifiedName, types); + return {}; + } + // Ambiguous primitive/smart pointer types are possible (when + // including type systems). + if (typeEntryType != TypeEntry::PrimitiveType + && typeEntryType != TypeEntry::SmartPointerType) { + if (errorMessage != nullptr) + *errorMessage = msgAmbiguousTypesFound(qualifiedName, types); + return {}; + } + return types; +} + // Reverse lookup of AbstractMetaType representing a template specialization // found during traversing function arguments to its type system typedef'ed // class. @@ -2272,12 +2299,10 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo typeInfo.clearInstantiations(); } - const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d); + const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d, errorMessageIn); if (types.isEmpty()) { - if (errorMessageIn) { - *errorMessageIn = - msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName)); - } + if (errorMessageIn != nullptr) + *errorMessageIn = msgUnableToTranslateType(_typei, *errorMessageIn); return {}; } @@ -2313,25 +2338,6 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo metaType.addInstantiation(targType); } - 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 {}; - } - // Ambiguous primitive/smart pointer types are possible (when - // including type systems). - if (typeEntryType != TypeEntry::PrimitiveType - && typeEntryType != TypeEntry::SmartPointerType) { - if (errorMessageIn) - *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types); - return {}; - } - } - if (typeEntryType == TypeEntry::SmartPointerType) { // Find a matching instantiation if (metaType.instantiations().size() != 1) { diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 1854b8b56..2620effff 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -143,6 +143,7 @@ public: AbstractMetaFunction *fnc, AbstractMetaClass *, int argumentIndex); AbstractMetaType translateType(const AddedFunction::TypeInfo &typeInfo, + AbstractMetaClass *currentClass, QString *errorMessage); AbstractMetaType translateType(const TypeInfo &type, AbstractMetaClass *currentClass, @@ -153,9 +154,13 @@ public: AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, QString *errorMessageIn = nullptr); + static TypeEntries findTypeEntriesHelper(const QString &qualifiedName, const QString &name, + AbstractMetaClass *currentClass = nullptr, + AbstractMetaBuilderPrivate *d = nullptr); static TypeEntries findTypeEntries(const QString &qualifiedName, const QString &name, AbstractMetaClass *currentClass = nullptr, - AbstractMetaBuilderPrivate *d = nullptr); + AbstractMetaBuilderPrivate *d = nullptr, + QString *errorMessage = nullptr); qint64 findOutValueFromString(const QString &stringValue, bool &ok); -- cgit v1.2.3