aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-08-02 14:18:11 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-08-03 14:29:26 +0000
commit26d6ef0c8f359b3bc29e2f68238e28f86e9448c5 (patch)
treeb8202883a6af7b4435dfd4cc05f1728efbc683e2 /sources/shiboken2
parent711515d089574cdc8be63c65d6b01863aadba141 (diff)
shiboken: Implement template inheritance for fields
Add the fields to the typedef'ed class specializing the type similar to the functions. Task-number: PYSIDE-725 Change-Id: I2daae9bd3c8a73fbd868f495cfc3a2dfba703103 Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/shiboken2')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp20
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.cpp98
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.h2
3 files changed, 120 insertions, 0 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index cbe33ae22..bcd447023 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -2922,6 +2922,26 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
subclass->addFunction(f.take());
}
+ const AbstractMetaFieldList &subClassFields = subclass->fields();
+ const AbstractMetaFieldList &templateClassFields = templateClass->fields();
+ for (const AbstractMetaField *field : templateClassFields) {
+ // If the field is modified or the instantiation has a field named
+ // the same as an existing field we have shadowing, so we need to skip it.
+ if (field->isModifiedRemoved(TypeSystem::All)
+ || field->attributes().testFlag(AbstractMetaAttributes::Static)
+ || AbstractMetaField::find(subClassFields, field->name()) != nullptr) {
+ continue;
+ }
+
+ QScopedPointer<AbstractMetaField> f(field->copy());
+ f->setEnclosingClass(subclass);
+ AbstractMetaType *fieldType = inheritTemplateType(templateTypes, field->type());
+ if (!fieldType)
+ continue;
+ f->replaceType(fieldType);
+ subclass->addField(f.take());
+ }
+
subclass->setTemplateBaseClass(templateClass);
subclass->setTemplateBaseClassInstantiations(templateTypes);
subclass->setInterfaces(templateClass->interfaces());
diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
index 8d869e3f9..d32e24379 100644
--- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
+++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
@@ -28,6 +28,7 @@
#include "testtemplates.h"
#include <QtTest/QTest>
+#include <QtCore/QTextStream>
#include <QTemporaryFile>
#include "testutil.h"
#include <abstractmetalang.h>
@@ -438,4 +439,101 @@ typedef Vector<int> IntVector;
QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector<int >"));
}
+// Perform checks on template inheritance; a typedef of a template class
+// should result in rewritten types.
+void TestTemplates::testTemplateTypeDefs_data()
+{
+ QTest::addColumn<QString>("cpp");
+ QTest::addColumn<QString>("xml");
+
+ const char optionalClassDef[] = R"CPP(
+template<class T> // Some value type similar to std::optional
+class Optional {
+public:
+ T value() const { return m_value; }
+ operator bool() const { return m_success; }
+
+ T m_value;
+ bool m_success = false;
+};
+)CPP";
+
+ const char xmlPrefix[] = R"XML(
+<typesystem package='Foo'>
+ <primitive-type name='int'/>
+ <primitive-type name='bool'/>
+)XML";
+
+ const char xmlOptionalDecl[] = "<value-type name='Optional' generate='no'/>\n";
+ const char xmlOptionalIntDecl[] = "<value-type name='IntOptional'/>\n";
+ const char xmlPostFix[] = "</typesystem>\n";
+
+ // Flat, global namespace
+ QString cpp;
+ QTextStream(&cpp) << optionalClassDef
+ << "typedef Optional<int> IntOptional;\n";
+ QString xml;
+ QTextStream(&xml) << xmlPrefix << xmlOptionalDecl << xmlOptionalIntDecl
+ << xmlPostFix;
+ QTest::newRow("global-namespace")
+ << cpp << xml;
+
+ // Typedef from namespace Std
+ cpp.clear();
+ QTextStream(&cpp) << "namespace Std {\n" << optionalClassDef << "}\n"
+ << "typedef Std::Optional<int> IntOptional;\n";
+ xml.clear();
+ QTextStream(&xml) << xmlPrefix
+ << "<namespace-type name='Std'>\n" << xmlOptionalDecl
+ << "</namespace-type>\n" << xmlOptionalIntDecl
+ << xmlPostFix;
+ QTest::newRow("namespace-Std")
+ << cpp << xml;
+
+ // Typedef from nested class
+ cpp.clear();
+ QTextStream(&cpp) << "class Outer {\npublic:\n" << optionalClassDef << "\n};\n"
+ << "typedef Outer::Optional<int> IntOptional;\n";
+ xml.clear();
+ QTextStream(&xml) << xmlPrefix
+ << "<object-type name='Outer'>\n" << xmlOptionalDecl
+ << "</object-type>\n" << xmlOptionalIntDecl
+ << xmlPostFix;
+ QTest::newRow("nested-class")
+ << cpp << xml;
+}
+
+void TestTemplates::testTemplateTypeDefs()
+{
+ QFETCH(QString, cpp);
+ QFETCH(QString, xml);
+
+ const QByteArray cppBa = cpp.toLocal8Bit();
+ const QByteArray xmlBa = xml.toLocal8Bit();
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppBa.constData(), xmlBa.constData(), true));
+ QVERIFY(!builder.isNull());
+ AbstractMetaClassList classes = builder->classes();
+
+ const AbstractMetaClass *optional = AbstractMetaClass::findClass(classes, QLatin1String("Optional"));
+ QVERIFY(optional);
+
+ // Find the typedef'ed class
+ const AbstractMetaClass *optionalInt =
+ AbstractMetaClass::findClass(classes, QLatin1String("IntOptional"));
+ QVERIFY(optionalInt);
+ QCOMPARE(optionalInt->templateBaseClass(), optional);
+
+ // Check whether the value() method now has an 'int' return
+ const AbstractMetaFunction *valueMethod =
+ optionalInt->findFunction(QLatin1String("value"));
+ QVERIFY(valueMethod);
+ QCOMPARE(valueMethod->type()->cppSignature(), QLatin1String("int"));
+
+ // Check whether the m_value field is of type 'int'
+ const AbstractMetaField *valueField =
+ optionalInt->findField(QLatin1String("m_value"));
+ QVERIFY(valueField);
+ QCOMPARE(valueField->type()->cppSignature(), QLatin1String("int"));
+}
+
QTEST_APPLESS_MAIN(TestTemplates)
diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.h b/sources/shiboken2/ApiExtractor/tests/testtemplates.h
index 3e1565933..df3de18b9 100644
--- a/sources/shiboken2/ApiExtractor/tests/testtemplates.h
+++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.h
@@ -46,6 +46,8 @@ private slots:
void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration();
void testTypedefOfInstantiationOfTemplateClass();
void testContainerTypeIncompleteArgument();
+ void testTemplateTypeDefs_data();
+ void testTemplateTypeDefs();
};
#endif