aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-10-22 17:35:12 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-11-10 16:12:48 +0100
commitf8b711554cb29448c10eace6118b595a715b0ade (patch)
treec12fdb536238ce9c37bcb51c43e46a4831ec11c6
parentaa99817ab7f55f145f0ac6be7036fa72251632e8 (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.cpp38
-rw-r--r--sources/shiboken6/ApiExtractor/tests/testresolvetype.cpp20
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()