From 7f798dfc9fc6e3e9756f06f0fedc821e16f1320a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 1 Jun 2018 11:20:14 +0200 Subject: shiboken: Streamline the type parsing code Replace struct TypeParser::Info by TypeInfo and remove TypeParser::Info. Move method TypeParser::Info::instantiationName() to TypeInfo for this purpose. Change TypeParser::parse() to return TypeInfo. Task-number: QTBUG-672 Change-Id: I123d5bf378ad146867b571e47e31ae08a92b2504 Reviewed-by: Qt CI Bot Reviewed-by: Alexandru Croitor --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 100 ++++++++-------- .../shiboken2/ApiExtractor/abstractmetabuilder_p.h | 5 +- .../shiboken2/ApiExtractor/parser/codemodel.cpp | 14 +++ sources/shiboken2/ApiExtractor/parser/codemodel.h | 3 + sources/shiboken2/ApiExtractor/typeparser.cpp | 126 ++++----------------- sources/shiboken2/ApiExtractor/typeparser.h | 25 +--- 6 files changed, 87 insertions(+), 186 deletions(-) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index d76c788ec..fa9f78ca0 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1612,7 +1612,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) // we only support our own containers and ONLY if there is only one baseclass if (baseClasses.size() == 1 && baseClasses.constFirst().contains(QLatin1Char('<'))) { - TypeParser::Info info; + TypeInfo info; ComplexTypeEntry* baseContainerType; AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType); if (templ) { @@ -2343,8 +2343,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ return nullptr; QString errorMessage; - TypeParser::Info typeInfo = TypeParser::parse(typei.toString(), &errorMessage); - if (typeInfo.is_busted) { + TypeInfo typeInfo = TypeParser::parse(typei.toString(), &errorMessage); + if (typeInfo.qualifiedName().isEmpty()) { qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString() << "\": " << errorMessage; return 0; @@ -2354,43 +2354,43 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ // 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with // NativePointerPattern usage. bool oneDimensionalArrayOfUnspecifiedSize = - typeInfo.arrays.size() == 1 - && typeInfo.arrays[0].isEmpty(); + typeInfo.arrayElements().size() == 1 + && typeInfo.arrayElements().at(0).isEmpty(); bool isConstCharStarCase = oneDimensionalArrayOfUnspecifiedSize - && typeInfo.qualified_name.size() == 1 - && typeInfo.qualified_name[0] == QStringLiteral("char") - && typeInfo.indirections == 0 - && typeInfo.is_constant == 1 - && typeInfo.is_busted == 0 - && typeInfo.referenceType == NoReference - && typeInfo.template_instantiations.size() == 0; + && typeInfo.qualifiedName().size() == 1 + && typeInfo.qualifiedName().at(0) == QStringLiteral("char") + && typeInfo.indirections() == 0 + && typeInfo.isConstant() + && typeInfo.referenceType() == NoReference + && typeInfo.arguments().isEmpty(); if (isConstCharStarCase) - typeInfo.indirections += typeInfo.arrays.size(); + typeInfo.setIndirections(typeInfo.indirections() + typeInfo.arrayElements().size()); // 2.2 Handle regular arrays. - if (typeInfo.arrays.size() > 0 && !isConstCharStarCase) { + if (!typeInfo.arrayElements().isEmpty() && !isConstCharStarCase) { TypeInfo newInfo; - //newInfo.setArguments(typei.arguments()); - newInfo.setIndirections(typei.indirections()); - newInfo.setConstant(typei.isConstant()); - newInfo.setFunctionPointer(typei.isFunctionPointer()); - newInfo.setQualifiedName(typei.qualifiedName()); - newInfo.setReferenceType(typei.referenceType()); - newInfo.setVolatile(typei.isVolatile()); + //newInfo.setArguments(typeInfo.arguments()); + newInfo.setIndirections(typeInfo.indirections()); + newInfo.setConstant(typeInfo.isConstant()); + newInfo.setFunctionPointer(typeInfo.isFunctionPointer()); + newInfo.setQualifiedName(typeInfo.qualifiedName()); + newInfo.setReferenceType(typeInfo.referenceType()); + newInfo.setVolatile(typeInfo.isVolatile()); AbstractMetaType *elementType = translateType(newInfo); if (!elementType) return nullptr; - for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) { + for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) { AbstractMetaType *arrayType = new AbstractMetaType; arrayType->setArrayElementType(elementType); - if (!typeInfo.arrays.at(i).isEmpty()) { + const QString &arrayElement = typeInfo.arrayElements().at(i); + if (!arrayElement.isEmpty()) { bool _ok; - const qint64 elems = findOutValueFromString(typeInfo.arrays.at(i), _ok); + const qint64 elems = findOutValueFromString(arrayElement, _ok); if (_ok) arrayType->setArrayElementCount(int(elems)); } @@ -2403,7 +2403,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ return elementType; } - QStringList qualifierList = typeInfo.qualified_name; + QStringList qualifierList = typeInfo.qualifiedName(); if (qualifierList.isEmpty()) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("horribly broken type '%1'").arg(_typei.toString()); @@ -2468,21 +2468,16 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ AbstractMetaType *metaType = new AbstractMetaType; metaType->setTypeEntry(type); - metaType->setIndirections(typeInfo.indirections); - metaType->setReferenceType(typeInfo.referenceType); - metaType->setConstant(typeInfo.is_constant); + metaType->setIndirections(typeInfo.indirections()); + metaType->setReferenceType(typeInfo.referenceType()); + metaType->setConstant(typeInfo.isConstant()); metaType->setOriginalTypeDescription(_typei.toString()); - for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) { - TypeInfo info; - info.setConstant(ta.is_constant); - info.setReferenceType(ta.referenceType); - info.setIndirections(ta.indirections); - - info.setFunctionPointer(false); - info.setQualifiedName(ta.instantiationName().split(colonColon())); - - AbstractMetaType *targType = translateType(info); + const auto &templateArguments = typeInfo.arguments(); + for (int t = 0, size = templateArguments.size(); t < size; ++t) { + TypeInfo ti = templateArguments.at(t); + ti.setQualifiedName(ti.instantiationName()); + AbstractMetaType *targType = translateType(ti); if (!targType) { delete metaType; return nullptr; @@ -2671,13 +2666,9 @@ bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringL AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, const AbstractMetaClass *context, - TypeParser::Info *info, + TypeInfo *info, ComplexTypeEntry **baseContainerType) const { - TypeParser::Info localInfo; - if (!info) - info = &localInfo; - TypeDatabase* types = TypeDatabase::instance(); QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon()); @@ -2686,14 +2677,15 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString & for (int i = scope.size(); i >= 0; --i) { QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString(); QString completeName = prefix + name; - const TypeParser::Info parsed = TypeParser::parse(completeName, &errorMessage); - if (parsed.is_busted) { + const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage); + QString qualifiedName = parsed.qualifiedName().join(colonColon()); + if (qualifiedName.isEmpty()) { qWarning().noquote().nospace() << "Unable to parse type \"" << completeName << "\" while looking for template \"" << name << "\": " << errorMessage; continue; } - *info = parsed; - QString qualifiedName = info->qualified_name.join(colonColon()); + if (info) + *info = parsed; AbstractMetaClass* templ = 0; for (AbstractMetaClass *c : qAsConst(m_templates)) { @@ -2795,9 +2787,9 @@ AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector< bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, - const TypeParser::Info &info) + const TypeInfo &info) { - QVector targs = info.template_instantiations; + QVector targs = info.arguments(); QVector templateTypes; if (subclass->isTypeDef()) { @@ -2810,8 +2802,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor()); } - for (const TypeParser::Info &i : qAsConst(targs)) { - QString typeName = i.qualified_name.join(colonColon()); + for (const TypeInfo &i : qAsConst(targs)) { + QString typeName = i.qualifiedName().join(colonColon()); QStringList possibleNames; possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; @@ -2831,9 +2823,9 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, if (t) { AbstractMetaType *temporaryType = new AbstractMetaType; temporaryType->setTypeEntry(t); - temporaryType->setConstant(i.is_constant); - temporaryType->setReferenceType(i.referenceType); - temporaryType->setIndirections(i.indirections); + temporaryType->setConstant(i.isConstant()); + temporaryType->setReferenceType(i.referenceType()); + temporaryType->setIndirections(i.indirections()); temporaryType->decideUsagePattern(); templateTypes << temporaryType; } else { diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 959734462..1f4e209db 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -122,18 +122,17 @@ public: AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo); AbstractMetaType *translateType(const TypeInfo &type, bool resolveType = true); - qint64 findOutValueFromString(const QString &stringValue, bool &ok); AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, - TypeParser::Info *info = Q_NULLPTR, + TypeInfo *info = Q_NULLPTR, ComplexTypeEntry **baseContainerType = Q_NULLPTR) const; AbstractMetaClassList getBaseClasses(const AbstractMetaClass *metaClass) const; bool ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const; bool inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, - const TypeParser::Info &info); + const TypeInfo &info); AbstractMetaType *inheritTemplateType(const QVector &templateTypes, const AbstractMetaType *metaType, bool *ok = Q_NULLPTR); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 0af4905f4..60a699337 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -238,6 +238,20 @@ QString TypeInfo::toString() const return tmp; } +QStringList TypeInfo::instantiationName() const +{ + QStringList result = m_qualifiedName; + if (const int argumentCount = m_arguments.size()) { + QString &last = result.last(); + for (int i = 0; i < argumentCount; ++i) { + last += i ? QLatin1String(", ") : QLatin1String("< "); + last += m_arguments.at(i).toString(); + } + last += QLatin1String(" >"); + } + return result; +} + bool TypeInfo::operator==(const TypeInfo &other) const { if (arrayElements().count() != other.arrayElements().count()) diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index d0d7b677c..d93aa10d9 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -98,6 +98,7 @@ QDebug operator<<(QDebug d, const CodeModel *m); class TypeInfo { + friend class TypeParser; public: TypeInfo() : flags(0), m_referenceType(NoReference) {} @@ -184,6 +185,8 @@ public: QString toString() const; + QStringList instantiationName() const; + static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs); static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope); diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp index 9ef4be346..02c85421b 100644 --- a/sources/shiboken2/ApiExtractor/typeparser.cpp +++ b/sources/shiboken2/ApiExtractor/typeparser.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include "typeparser.h" +#include #include #include @@ -155,19 +156,12 @@ QString Scanner::msgParseError(const QString &why) const + QString(m_chars, m_length) + QStringLiteral("\": ") + why; } -static TypeParser::Info invalidInfo() -{ - TypeParser::Info result; - result.is_busted = true; - return result; -} - -TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) +TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) { Scanner scanner(str); - Info info; - QStack stack; + TypeInfo info; + QStack stack; stack.push(&info); bool colon_prefix = false; @@ -177,7 +171,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) Scanner::Token tok = scanner.nextToken(errorMessage); while (tok != Scanner::NoToken) { if (tok == Scanner::InvalidToken) - return invalidInfo(); + return TypeInfo(); // switch (tok) { // case Scanner::StarToken: printf(" - *\n"); break; @@ -197,16 +191,16 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) switch (tok) { case Scanner::StarToken: - ++stack.top()->indirections; + ++stack.top()->m_indirections; break; case Scanner::AmpersandToken: - switch (stack.top()->referenceType) { + switch (stack.top()->referenceType()) { case NoReference: - stack.top()->referenceType = LValueReference; + stack.top()->setReferenceType(LValueReference); break; case LValueReference: - stack.top()->referenceType = RValueReference; + stack.top()->setReferenceType(RValueReference); break; case RValueReference: const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers")); @@ -214,18 +208,18 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return invalidInfo(); + return TypeInfo(); } break; case Scanner::LessThanToken: - stack.top()->template_instantiations << Info(); - stack.push(&stack.top()->template_instantiations.last()); + stack.top()->m_arguments << TypeInfo(); + stack.push(&stack.top()->m_arguments.last()); break; case Scanner::CommaToken: stack.pop(); - stack.top()->template_instantiations << Info(); - stack.push(&stack.top()->template_instantiations.last()); + stack.top()->m_arguments << TypeInfo(); + stack.push(&stack.top()->m_arguments.last()); break; case Scanner::GreaterThanToken: @@ -237,7 +231,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) break; case Scanner::ConstToken: - stack.top()->is_constant = true; + stack.top()->m_constant = true; break; case Scanner::OpenParenToken: // function pointers not supported @@ -247,17 +241,17 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) *errorMessage = message; else qWarning().noquote().nospace() << message; - return invalidInfo(); + return TypeInfo(); } case Scanner::Identifier: if (in_array) { array = scanner.identifier(); - } else if (colon_prefix || stack.top()->qualified_name.isEmpty()) { - stack.top()->qualified_name << scanner.identifier(); + } else if (colon_prefix || stack.top()->m_qualifiedName.isEmpty()) { + stack.top()->m_qualifiedName << scanner.identifier(); colon_prefix = false; } else { - stack.top()->qualified_name.last().append(QLatin1Char(' ') + scanner.identifier()); + stack.top()->m_qualifiedName.last().append(QLatin1Char(' ') + scanner.identifier()); } break; @@ -267,7 +261,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) case Scanner::SquareEnd: in_array = false; - stack.top()->arrays += array; + stack.top()->m_arrayElements += array; break; @@ -280,83 +274,3 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) return info; } - -QString TypeParser::Info::instantiationName() const -{ - QString s(qualified_name.join(QLatin1String("::"))); - if (!template_instantiations.isEmpty()) { - QStringList insts; - for (const Info &info : template_instantiations) - insts << info.toString(); - s += QLatin1String("< ") + insts.join(QLatin1String(", ")) + QLatin1String(" >"); - } - - return s; -} - -QString TypeParser::Info::toString() const -{ - QString s; - - if (is_constant) - s += QLatin1String("const "); - s += instantiationName(); - for (int i = 0; i < arrays.size(); ++i) - s += QLatin1Char('[') + arrays.at(i) + QLatin1Char(']'); - s += QString(indirections, QLatin1Char('*')); - switch (referenceType) { - case NoReference: - break; - case LValueReference: - s += QLatin1Char('&'); - break; - case RValueReference: - s += QLatin1String("&&"); - break; - } - return s; -} - -#ifndef QT_NO_DEBUG_STREAM - -static void formatTypeInfo(QDebug &d, const TypeParser::Info &i) -{ - if (i.is_busted) { - d << "busted"; - return; - } - - d << '"' << i.qualified_name << '"'; - if (!i.arrays.isEmpty()) { - d << ", arrays="; - for (const QString &a : i.arrays) - d << '[' << a << ']'; - } - if (!i.template_instantiations.isEmpty()) { - d << ", template_instantiations=["; - for (int t = 0, size = i.template_instantiations.size(); t < size; ++t) { - if (t) - d << ", "; - formatTypeInfo(d, i.template_instantiations.at(t)); - } - d << ']'; - } - if (i.referenceType != NoReference) - d << ", refType=" << i.referenceType; - if (i.is_constant) - d << ", [const]"; - if (i.indirections > 0) - d << ", indirections=" << i.indirections; -} - -QDebug operator<<(QDebug d, const TypeParser::Info &i) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TypeParser::Info("; - formatTypeInfo(d, i); - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typeparser.h b/sources/shiboken2/ApiExtractor/typeparser.h index e51a2c21a..3b538017a 100644 --- a/sources/shiboken2/ApiExtractor/typeparser.h +++ b/sources/shiboken2/ApiExtractor/typeparser.h @@ -31,36 +31,15 @@ #include "parser/codemodel_enums.h" -#include #include -#include #include -QT_FORWARD_DECLARE_CLASS(QDebug) +class TypeInfo; class TypeParser { public: - struct Info - { - Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { } - QStringList qualified_name; - QStringList arrays; - QVector template_instantiations; - ReferenceType referenceType; - uint is_constant : 1; - uint is_busted : 1; - uint indirections : 6; - - QString toString() const; - QString instantiationName() const; - }; - - static Info parse(const QString &str, QString *errorMessage = Q_NULLPTR); + static TypeInfo parse(const QString &str, QString *errorMessage = nullptr); }; -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeParser::Info &); -#endif - #endif // TYPEPARSER_H -- cgit v1.2.3