diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-10-22 17:35:12 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-11-10 16:12:48 +0100 |
commit | f8b711554cb29448c10eace6118b595a715b0ade (patch) | |
tree | c12fdb536238ce9c37bcb51c43e46a4831ec11c6 | |
parent | aa99817ab7f55f145f0ac6be7036fa72251632e8 (diff) |
shiboken6: Refactor resolving of inner container types in argument default values
Add an explanatory comment, rewrite without regexes and add a test.
Task-number: PYSIDE-1691
Change-Id: Idfa5022016d16f29718042b4677f248d20418a22
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 8ab90a73c792bd20deced21bad878c349f758605)
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 38 | ||||
-rw-r--r-- | sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp | 20 |
2 files changed, 50 insertions, 8 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index d4847f401..d50d2f5f6 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -2511,6 +2511,17 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV return 0; } +// Return whether candidate is some underqualified specification of qualifiedType +// ("B::C" should be qualified to "A::B::C") +static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidate) +{ + const auto candidateSize = candidate.size(); + const auto qualifiedTypeSize = qualifiedType.size(); + return candidateSize < qualifiedTypeSize + && qualifiedType.endsWith(candidate) + && qualifiedType.at(qualifiedTypeSize - candidateSize - 1) == u':'; +} + QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type, const QString &expr) const { @@ -2544,14 +2555,25 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract } else if (type.isFlags() || type.isEnum()) { expr = fixEnumDefault(type, expr); } else if (type.isContainer() && expr.contains(QLatin1Char('<'))) { - static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature()); - static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); - Q_ASSERT(defaultRegEx.isValid()); - const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); - if (typeMatch.hasMatch() && defaultMatch.hasMatch()) - expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); + // Expand a container of a nested class, fex + // "QList<FormatRange>()" -> "QList<QTextLayout::FormatRange>()" + if (type.instantiations().size() != 1) + return expr; // Only simple types are handled, not QMap<int, int>. + auto *innerTypeEntry = type.instantiations().constFirst().typeEntry(); + if (!innerTypeEntry->isComplex()) + return expr; + const QString &qualifiedInnerTypeName = innerTypeEntry->qualifiedCppName(); + if (!qualifiedInnerTypeName.contains(u"::")) // Nothing to qualify here + return expr; + const auto openPos = expr.indexOf(u'<'); + const auto closingPos = expr.lastIndexOf(u'>'); + if (openPos == -1 || closingPos == -1) + return expr; + const auto innerPos = openPos + 1; + const auto innerLen = closingPos - innerPos; + const auto innerType = QStringView{expr}.mid(innerPos, innerLen).trimmed(); + if (isUnderQualifiedSpec(qualifiedInnerTypeName, innerType)) + expr.replace(innerPos, innerLen, qualifiedInnerTypeName); } else { // Here the default value is supposed to be a constructor, // a class field, or a constructor receiving a class field diff --git a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp index c88dd7a53..809e3b824 100644 --- a/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp @@ -76,6 +76,7 @@ struct DefaultValuesFixture AbstractMetaType intType; AbstractMetaType stringType; AbstractMetaType classType; + AbstractMetaType listType; const AbstractMetaClass *klass{}; }; @@ -86,6 +87,8 @@ static int populateDefaultValuesFixture(DefaultValuesFixture *fixture) { static const char cppCode[] =R"( #include <string> +#include <list> + namespace Namespace { class Test { @@ -93,6 +96,8 @@ public: explicit Test(int x = INT_FIELD_1); explicit Test(const std::string &t = std::string(CHAR_FIELD_1)); + static void listFunc(std::list<Test> list = std::list<Test>()); + static const int INT_FIELD_1 = 42; static const char *CHAR_FIELD_1; }; @@ -106,6 +111,7 @@ public: <namespace-type name='Namespace'> <value-type name='Test'/> </namespace-type> + <container-type name="std::list" type="list"/> </typesystem> )"; @@ -138,6 +144,11 @@ public: if (fixture->intType.isVoid() || fixture->stringType.isVoid()) return -3; + auto listFunc = fixture->klass->findFunction(u"listFunc"_qs); + if (listFunc.isNull() || listFunc->arguments().size() != 1) + return -3; + fixture->listType = listFunc->arguments().constFirst().type(); + return 0; } @@ -154,6 +165,15 @@ void TestResolveType::testFixDefaultArguments_data() QTest::newRow("int") << fixture << setupOk << fixture.intType << "1" << "1"; + + // Test expansion of container types + QString expected = u"std::list<Namespace::Test>()"_qs; + QTest::newRow("list") + << fixture << setupOk << fixture.listType + << expected << expected; + QTest::newRow("partially qualified list") + << fixture << setupOk << fixture.listType + << "std::list<Test>()" << expected; } void TestResolveType::testFixDefaultArguments() |