diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-06 09:59:29 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-09 15:49:23 +0000 |
commit | 4ea3fcec20fdd80ae71cd69039e0ecae0a40653e (patch) | |
tree | a2364d5452dd232fce7361d4522b5fe2c38cfcc5 | |
parent | 3428efa5f69d321bcacdd106b0e724ab99bb63ed (diff) |
shiboken6: Replace AddedFunction::TypeInfo by TypeInfo
AddedFunction::TypeInfo was a stripped-down version of the
code model's TypeInfo with its own, simplified parser.
Replacing it by TypeInfo allows for removing the parser
code and the entire
AbstractMetaBuilderPrivate::translateType(AddedFunction::TypeInfo)
branch. The more powerful TypeParser from the code model
can then be used, allowing for more complex types in <add-function>
or <declare-function>.
As a drive by, replace the AddedFunction constructor by a static
factory function, allowing to pass up parse errors.
Change-Id: I33ad19e9b5ed30bd27898afe771401ddc98c8c73
Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 123 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h | 3 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/messages.cpp | 11 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/messages.h | 4 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/modifications.cpp | 179 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/modifications.h | 32 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp | 107 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/typesystemparser.cpp | 9 |
8 files changed, 153 insertions, 315 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index b4787ec9c..f7c7f1292 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -65,55 +65,6 @@ static QString stripTemplateArgs(const QString &name) return pos < 0 ? name : name.left(pos); } -static QStringList parseTemplateType(const QString &name) { - int n = name.indexOf(QLatin1Char('<')); - if (n <= 0) { - // If name starts with '<' or contains an unmatched (i.e. any) '>', we - // reject it - if (n == 0 || name.count(QLatin1Char('>'))) - return QStringList(); - // Doesn't look like a template instantiation; just return the name - return QStringList() << name; - } - - // Split the type name into the template name and template arguments; the - // part before the opening '<' is the template name - // - // Example: - // "foo<A, bar<B, C>, D>" -> ( "foo", "A", "bar<B, C>", "D" ) - QStringList result; - result << name.left(n).trimmed(); - - // Extract template arguments - int i, depth = 1; - const int l = name.length(); - for (i = n + 1; i < l; ++i) { - // Consume balanced '<'/'>' within a single argument so that we won't - // split on ',' as part of a single argument which is itself a - // multi-argument template type - if (name[i] == QLatin1Char('<')) { - ++depth; - } else if (name[i] == QLatin1Char('>')) { - if (--depth == 0) - break; - } else if (name[i] == QLatin1Char(',') && depth == 1) { - // Encountered ',' in template argument list that is not within - // another template name; add current argument to result and start - // working on the next argument - result << name.mid(n + 1, i - n - 1).trimmed(); - n = i; - } - } - if (i >= l) // arg list not closed - return QStringList(); - if (i + 1 < l) // arg list closed before end of name - return QStringList(); - - // Add final argument and return result - result << name.mid(n + 1, i - n - 1).trimmed(); - return result; -} - AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : m_logDirectory(QLatin1String(".") + QDir::separator()) { @@ -1535,11 +1486,11 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu { QString errorMessage; - AbstractMetaType returnType = translateType(addedFunc->returnType(), metaClass, &errorMessage); + AbstractMetaType returnType = translateType(addedFunc->returnType(), metaClass, {}, &errorMessage); if (!returnType) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidReturnType(addedFunc->name(), - addedFunc->returnType().name, + addedFunc->returnType().qualifiedName(), errorMessage, metaClass))); return nullptr; @@ -1552,11 +1503,11 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu for (int i = 0; i < args.count(); ++i) { const AddedFunction::Argument &arg = args.at(i); - AbstractMetaType type = translateType(arg.typeInfo, metaClass, &errorMessage); + AbstractMetaType type = translateType(arg.typeInfo, metaClass, {}, &errorMessage); if (Q_UNLIKELY(!type)) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidArgType(addedFunc->name(), - arg.typeInfo.name, i + 1, + arg.typeInfo.qualifiedName(), i + 1, errorMessage, metaClass))); delete metaFunction; @@ -1984,72 +1935,6 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return metaFunction; } -AbstractMetaType AbstractMetaBuilderPrivate::translateType(const AddedFunction::TypeInfo &typeInfo, - AbstractMetaClass *currentClass, - QString *errorMessage) -{ - Q_ASSERT(!typeInfo.name.isEmpty()); - TypeDatabase* typeDb = TypeDatabase::instance(); - - QString typeName = typeInfo.name; - - if (typeName == QLatin1String("void")) - return AbstractMetaType::createVoid(); - - const TypeEntry *type = nullptr; - // test if the type is a template, like a container - QStringList templateArgs; - 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); - return {}; - } - const QString name = parsedType.takeFirst(); - templateArgs = parsedType; - type = typeDb->findContainerType(name); - if (!type) { // A template typedef? - if (auto candidate = typeDb->findType(name)) { - if (candidate->type() == TypeEntry::ObjectType || candidate->type() == TypeEntry::BasicValueType) - type = candidate; - } - } - } - - 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... - AbstractMetaType metaType(type); - metaType.setIndirections(typeInfo.indirections); - if (typeInfo.isReference) - metaType.setReferenceType(LValueReference); - metaType.setConstant(typeInfo.isConstant); - if (!templateArgs.isEmpty()) { - for (const QString& templateArg : qAsConst(templateArgs)) { - AbstractMetaType metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg), - currentClass, errorMessage); - if (!metaArgType) - return {}; - metaType.addInstantiation(metaArgType); - } - metaType.setTypeUsagePattern(AbstractMetaType::ContainerPattern); - } else { - metaType.decideUsagePattern(); - } - - return metaType; -} - static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName) { const TypeEntry* type = nullptr; diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 5b5f3e505..7792eb0fc 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -143,9 +143,6 @@ public: QString fixDefaultValue(const ArgumentModelItem &item, const AbstractMetaType &type, AbstractMetaFunction *fnc, AbstractMetaClass *, int argumentIndex); - AbstractMetaType translateType(const AddedFunction::TypeInfo &typeInfo, - AbstractMetaClass *currentClass, - QString *errorMessage); AbstractMetaType translateType(const TypeInfo &type, AbstractMetaClass *currentClass, TranslateTypeFlags flags = {}, diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index 65012893a..aca801d53 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -114,7 +114,7 @@ static void msgFormatEnumType(Stream &str, } QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, - const QString &typeName, + const QStringList &typeName, int pos, const QString &why, const AbstractMetaClass *context) { @@ -122,20 +122,21 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, QTextStream str(&result); if (context) str << context->typeEntry()->sourceLocation(); - str << "Unable to translate type \"" << typeName << "\" of argument " - << pos << " of added function \"" << addedFuncName << "\": " << why; + str << "Unable to translate type \"" << typeName.join(colonColon()) + << "\" of argument " << pos << " of added function \"" + << addedFuncName << "\": " << why; return result; } QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, - const QString &typeName, const QString &why, + const QStringList &typeName, const QString &why, const AbstractMetaClass *context) { QString result; QTextStream str(&result); if (context) str << context->typeEntry()->sourceLocation(); - str << "Unable to translate return type \"" << typeName + str << "Unable to translate return type \"" << typeName.join(colonColon()) << "\" of added function \"" << addedFuncName << "\": " << why; return result; diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index 1e58a7fad..8292e491e 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -48,12 +48,12 @@ QT_FORWARD_DECLARE_CLASS(QFile) QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, - const QString &typeName, + const QStringList &typeName, int pos, const QString &why, const AbstractMetaClass *context = nullptr); QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, - const QString &typeName, const QString &why, + const QStringList &typeName, const QString &why, const AbstractMetaClass *context = nullptr); QString msgNoFunctionForModification(const AbstractMetaClass *klass, diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp index a370a2e03..3f8b1e71f 100644 --- a/sources/shiboken6/ApiExtractor/modifications.cpp +++ b/sources/shiboken6/ApiExtractor/modifications.cpp @@ -29,6 +29,7 @@ #include "modifications.h" #include "modifications_p.h" #include "typedatabase.h" +#include "typeparser.h" #include "typesystem.h" #include <QtCore/QDebug> @@ -284,127 +285,70 @@ Arguments splitParameters(QStringView paramString, QString *errorMessage) } // namespace AddedFunctionParser -// ---------------------- AddedFunction +AddedFunction::AddedFunction(const QString &name, const QList<Argument> &arguments, + const TypeInfo &returnType) : + m_name(name), + m_arguments(arguments), + m_returnType(returnType) +{ +} + +AddedFunction::AddedFunctionPtr + AddedFunction::createAddedFunction(const QString &signatureIn, const QString &returnTypeIn, + QString *errorMessage) -static AddedFunction::TypeInfo parseType(const QString& signature, - int startPos = 0, int *endPos = nullptr, - QString *argumentName = nullptr, - QString *defaultValue = nullptr) { - AddedFunction::TypeInfo result; - static const QRegularExpression regex(QLatin1String("\\w")); - Q_ASSERT(regex.isValid()); - int length = signature.length(); - int start = signature.indexOf(regex, startPos); - if (start == -1) { - if (QStringView{signature}.mid(startPos + 1, 3) == QLatin1String("...")) { // varargs - if (endPos) - *endPos = startPos + 4; - result.name = QLatin1String("..."); - } else { // error - if (endPos) - *endPos = length; - } - return result; - } + errorMessage->clear(); - int cantStop = 0; - QString paramString; - QChar c; - int i = start; - for (; i < length; ++i) { - c = signature[i]; - if (c == QLatin1Char('<')) - cantStop++; - if (c == QLatin1Char('>')) - cantStop--; - if (cantStop < 0) - break; // FIXME: report error? - if ((c == QLatin1Char(')') || c == QLatin1Char(',')) && !cantStop) - break; - paramString += signature[i]; - } - if (endPos) - *endPos = i; - - // Check default value - if (paramString.contains(QLatin1Char('='))) { - QStringList lst = paramString.split(QLatin1Char('=')); - paramString = lst[0].trimmed(); - if (defaultValue != nullptr) - *defaultValue = lst[1].trimmed(); - } + QList<Argument> arguments; + const TypeInfo returnType = returnTypeIn.isEmpty() + ? TypeInfo::voidType() + : TypeParser::parse(returnTypeIn, errorMessage); + if (!errorMessage->isEmpty()) + return {}; - // check constness - if (paramString.startsWith(QLatin1String("const "))) { - result.isConstant = true; - paramString.remove(0, sizeof("const")/sizeof(char)); - paramString = paramString.trimmed(); - } + QStringView signature = QStringView{signatureIn}.trimmed(); - // Extract argument name from "T<bla,blub>* @foo@" - const int nameStartPos = paramString.indexOf(QLatin1Char('@')); - if (nameStartPos != -1) { - const int nameEndPos = paramString.indexOf(QLatin1Char('@'), nameStartPos + 1); - if (nameEndPos > nameStartPos) { - if (argumentName) - *argumentName = paramString.mid(nameStartPos + 1, nameEndPos - nameStartPos - 1); - paramString.remove(nameStartPos, nameEndPos - nameStartPos + 1); - paramString = paramString.trimmed(); - } + // Skip past "operator()(...)" + const int parenSearchStartPos = signature.startsWith(callOperator()) + ? callOperator().size() : 0; + const int openParenPos = signature.indexOf(QLatin1Char('('), parenSearchStartPos); + if (openParenPos < 0) { + return AddedFunctionPtr(new AddedFunction(signature.toString(), + arguments, returnType)); } - // check reference - if (paramString.endsWith(QLatin1Char('&'))) { - result.isReference = true; - paramString.chop(1); - paramString = paramString.trimmed(); + const QString name = signature.left(openParenPos).trimmed().toString(); + const int closingParenPos = signature.lastIndexOf(QLatin1Char(')')); + if (closingParenPos < 0) { + *errorMessage = QLatin1String("Missing closing parenthesis"); + return {}; } - // check Indirections - while (paramString.endsWith(QLatin1Char('*'))) { - result.indirections++; - paramString.chop(1); - paramString = paramString.trimmed(); - } - result.name = paramString; - return result; -} + // Check for "foo() const" + bool isConst = false; + const int signatureLength = signature.length(); + const int qualifierLength = signatureLength - closingParenPos - 1; + if (qualifierLength >= 5 + && signature.right(qualifierLength).contains(QLatin1String("const"))) { + isConst = true; + } -AddedFunction::AddedFunction(QString signature, const QString &returnType) : - m_access(Public) -{ - Q_ASSERT(!returnType.isEmpty()); - m_returnType = parseType(returnType); - signature = signature.trimmed(); - // Skip past "operator()(...)" - const int parenStartPos = signature.startsWith(callOperator()) - ? callOperator().size() : 0; - int endPos = signature.indexOf(QLatin1Char('('), parenStartPos); - if (endPos < 0) { - m_isConst = false; - m_name = signature; - } else { - m_name = signature.left(endPos).trimmed(); - int signatureLength = signature.length(); - while (endPos < signatureLength) { - QString argumentName; - QString defaultValue; - TypeInfo arg = parseType(signature, endPos, &endPos, &argumentName, &defaultValue); - if (!arg.name.isEmpty()) - m_arguments.append({arg, argumentName, defaultValue}); - // end of parameters... - if (endPos >= signatureLength || signature[endPos] == QLatin1Char(')')) - break; - } - // is const? - m_isConst = QStringView{signature}.right(signatureLength - endPos).contains(QLatin1String("const")); + const auto paramString = signature.mid(openParenPos + 1, closingParenPos - openParenPos - 1); + const auto params = AddedFunctionParser::splitParameters(paramString, errorMessage); + if (params.isEmpty() && !errorMessage->isEmpty()) + return {}; + for (const auto &p : params) { + TypeInfo type = p.type == QLatin1String("...") + ? TypeInfo::varArgsType() : TypeParser::parse(p.type, errorMessage); + if (!errorMessage->isEmpty()) + return {}; + arguments.append({type, p.name, p.defaultValue}); } -} -AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& signature) -{ - return parseType(signature); + AddedFunctionPtr result(new AddedFunction(name, arguments, returnType)); + result->setConstant(isConst); + return result; } void DocModification::setCode(const QString &code) @@ -529,23 +473,6 @@ QDebug operator<<(QDebug d, const FunctionModification &fm) return d; } -QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TypeInfo("; - if (ti.isConstant) - d << "const"; - if (ti.indirections) - d << QByteArray(ti.indirections, '*'); - if (ti.isReference) - d << " &"; - d << ti.name; - d << ')'; - return d; -} - QDebug operator<<(QDebug d, const AddedFunction::Argument &a) { QDebugStateSaver saver(d); diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h index 3371f51ee..ecb464773 100644 --- a/sources/shiboken6/ApiExtractor/modifications.h +++ b/sources/shiboken6/ApiExtractor/modifications.h @@ -31,10 +31,12 @@ #include "typesystem_enums.h" #include "typesystem_typedefs.h" +#include "parser/typeinfo.h" #include <QtCore/QList> #include <QtCore/QMap> #include <QtCore/QRegularExpression> +#include <QtCore/QSharedPointer> #include <QtCore/QString> QT_BEGIN_NAMESPACE @@ -393,6 +395,8 @@ struct FieldModification: public Modification */ struct AddedFunction { + using AddedFunctionPtr = QSharedPointer<AddedFunction>; + /// Function access types. enum Access { InvalidAccess = 0, @@ -400,22 +404,6 @@ struct AddedFunction Public = 0x2 }; - /** - * \internal - * Internal struct used to store information about arguments and return type of the - * functions added by the type system. This information is later used to create - * AbstractMetaType and AbstractMetaArgument for the AbstractMetaFunctions. - */ - struct TypeInfo { - TypeInfo() = default; - static TypeInfo fromSignature(const QString& signature); - - QString name; - int indirections = 0; - bool isConstant = false; - bool isReference = false; - }; - struct Argument { TypeInfo typeInfo; @@ -424,7 +412,13 @@ struct AddedFunction }; /// Creates a new AddedFunction with a signature and a return type. - explicit AddedFunction(QString signature, const QString &returnType); + explicit AddedFunction(const QString &name, const QList<Argument> &arguments, + const TypeInfo &returnType); + + static AddedFunctionPtr createAddedFunction(const QString &signatureIn, + const QString &returnTypeIn, + QString *errorMessage); + AddedFunction() = default; /// Returns the function name. @@ -462,6 +456,7 @@ struct AddedFunction { return m_isConst; } + void setConstant(bool c) { m_isConst = c; }; /// Set this method static. void setStatic(bool value) @@ -484,14 +479,13 @@ private: QString m_name; QList<Argument> m_arguments; TypeInfo m_returnType; - Access m_access = Protected; + Access m_access = Public; bool m_isConst = false; bool m_isStatic = false; bool m_isDeclaration = false; }; #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti); QDebug operator<<(QDebug d, const AddedFunction::Argument &a); QDebug operator<<(QDebug d, const AddedFunction &af); #endif diff --git a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp index ca10cbfc6..20ca3ae6f 100644 --- a/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testaddfunction.cpp @@ -38,41 +38,64 @@ void TestAddFunction::testParsingFuncNameAndConstness() { // generic test... const char sig1[] = "func(type1, const type2, const type3* const)"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 3); - AddedFunction::TypeInfo retval = f1.returnType(); - QCOMPARE(retval.name, QLatin1String("void")); - QCOMPARE(retval.indirections, 0); - QCOMPARE(retval.isConstant, false); - QCOMPARE(retval.isReference, false); + QString errorMessage; + auto f1 = AddedFunction::createAddedFunction(QLatin1String(sig1), QLatin1String("void"), + &errorMessage); + QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QCOMPARE(f1->name(), QLatin1String("func")); + QCOMPARE(f1->arguments().count(), 3); + TypeInfo retval = f1->returnType(); + QCOMPARE(retval.qualifiedName(), QStringList{QLatin1String("void")}); + QCOMPARE(retval.indirections(), 0); + QCOMPARE(retval.isConstant(), false); + QCOMPARE(retval.referenceType(), NoReference); // test with a ugly template as argument and other ugly stuff const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *@my_name@, const type3* const ) const "; - AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc<int& , C<char*> * > * *")); - QCOMPARE(f2.name(), QLatin1String("_fu__nc_")); - const auto &args = f2.arguments(); + auto f2 = AddedFunction::createAddedFunction(QLatin1String(sig2), + QLatin1String("const Abc<int& , C<char*> * > * *"), + &errorMessage); + QVERIFY2(!f2.isNull(), qPrintable(errorMessage)); + QCOMPARE(f2->name(), QLatin1String("_fu__nc_")); + const auto &args = f2->arguments(); QCOMPARE(args.count(), 4); - retval = f2.returnType(); - QCOMPARE(retval.name, QLatin1String("Abc<int& , C<char*> * >")); - QCOMPARE(retval.indirections, 2); - QCOMPARE(retval.isConstant, true); - QCOMPARE(retval.isReference, false); - retval = args.at(2).typeInfo; + retval = f2->returnType(); + QCOMPARE(retval.qualifiedName(), QStringList{QLatin1String("Abc")}); + QCOMPARE(retval.instantiations().size(), 2); + QCOMPARE(retval.toString(), QLatin1String("const Abc<int&, C<char*>*>**")); + QCOMPARE(retval.indirections(), 2); + QCOMPARE(retval.isConstant(), true); + QCOMPARE(retval.referenceType(), NoReference); QVERIFY(args.at(0).name.isEmpty()); QVERIFY(args.at(1).name.isEmpty()); + QCOMPARE(args.at(2).name, QLatin1String("my_name")); + auto arg2Type = args.at(2).typeInfo; + QCOMPARE(arg2Type.qualifiedName(), QStringList{QLatin1String("Abc")}); + QCOMPARE(arg2Type.instantiations().size(), 2); + QCOMPARE(arg2Type.toString(), QLatin1String("const Abc<int&, C<char*>*>**")); + QCOMPARE(arg2Type.indirections(), 2); + QCOMPARE(arg2Type.isConstant(), true); + QCOMPARE(arg2Type.referenceType(), NoReference); + QVERIFY(args.at(3).name.isEmpty()); - QCOMPARE(retval.name, QLatin1String("Abc<int& , C<char*> * >")); - QCOMPARE(retval.indirections, 2); - QCOMPARE(retval.isConstant, true); - QCOMPARE(retval.isReference, false); // function with no args. const char sig3[] = "func()"; - AddedFunction f3(QLatin1String(sig3), QLatin1String("void")); - QCOMPARE(f3.name(), QLatin1String("func")); - QCOMPARE(f3.arguments().count(), 0); + auto f3 = AddedFunction::createAddedFunction(QLatin1String(sig3), QLatin1String("void"), + &errorMessage); + QVERIFY2(!f3.isNull(), qPrintable(errorMessage)); + QCOMPARE(f3->name(), QLatin1String("func")); + QCOMPARE(f3->arguments().count(), 0); + + // const call operator + const char sig4[] = "operator()(int)const"; + auto f4 = AddedFunction::createAddedFunction(QLatin1String(sig4), QLatin1String("int"), + &errorMessage); + QVERIFY2(!f4.isNull(), qPrintable(errorMessage)); + QCOMPARE(f4->name(), QLatin1String("operator()")); + QCOMPARE(f4->arguments().count(), 1); + QVERIFY(f4->isConstant()); } void TestAddFunction::testAddFunction() @@ -196,11 +219,13 @@ void TestAddFunction::testAddFunctionCodeSnippets() void TestAddFunction::testAddFunctionWithoutParenteses() { const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 0); - QCOMPARE(f1.isConstant(), false); + QString errorMessage; + auto f1 = AddedFunction::createAddedFunction(QLatin1String(sig1), QLatin1String("void"), + &errorMessage); + QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QCOMPARE(f1->name(), QLatin1String("func")); + QCOMPARE(f1->arguments().count(), 0); + QCOMPARE(f1->isConstant(), false); const char cppCode[] = "struct A {};\n"; const char xmlCode[] = "\ @@ -226,11 +251,13 @@ void TestAddFunction::testAddFunctionWithoutParenteses() void TestAddFunction::testAddFunctionWithDefaultArgs() { const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void")); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 0); - QCOMPARE(f1.isConstant(), false); + QString errorMessage; + auto f1 = AddedFunction::createAddedFunction(QLatin1String(sig1), QLatin1String("void"), + &errorMessage); + QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QCOMPARE(f1->name(), QLatin1String("func")); + QCOMPARE(f1->arguments().count(), 0); + QCOMPARE(f1->isConstant(), false); const char cppCode[] = "struct A { };\n"; const char xmlCode[] = "\ @@ -291,11 +318,13 @@ void TestAddFunction::testAddFunctionAtModuleLevel() void TestAddFunction::testAddFunctionWithVarargs() { const char sig1[] = "func(int,char,...)"; - AddedFunction f1( QLatin1String(sig1), QLatin1String("void")); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 3); - QVERIFY(!f1.isConstant()); + QString errorMessage; + auto f1 = AddedFunction::createAddedFunction(QLatin1String(sig1), QLatin1String("void"), + &errorMessage); + QVERIFY2(!f1.isNull(), qPrintable(errorMessage)); + QCOMPARE(f1->name(), QLatin1String("func")); + QCOMPARE(f1->arguments().count(), 3); + QVERIFY(!f1->isConstant()); const char cppCode[] = "struct A {};\n"; const char xmlCode[] = "\ diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 19f968d87..bb0cffdc0 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -2233,7 +2233,7 @@ bool TypeSystemParser::parseAddFunction(const QXmlStreamReader &, return false; } QString originalSignature; - QString returnType = QLatin1String("void"); + QString returnType; bool staticFunction = false; QString access; int overloadNumber = TypeSystem::OverloadNumberUnset; @@ -2266,7 +2266,12 @@ bool TypeSystemParser::parseAddFunction(const QXmlStreamReader &, return false; } - AddedFunctionPtr func(new AddedFunction(signature, returnType)); + AddedFunctionPtr func = AddedFunction::createAddedFunction(signature, returnType, &errorString); + if (func.isNull()) { + m_error = errorString; + return false; + } + func->setStatic(staticFunction); if (!signature.contains(QLatin1Char('('))) signature += QLatin1String("()"); |