From e1c45ef7c0e453a6df4e83932317b48dbaad3c6f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Jan 2020 17:36:27 +0100 Subject: shiboken: Introduce "until" version attribute as opposite of "since" Prototypically use it for QMessageLogContext, allowing to elegantly build for Qt from version 5.12..now using a single type system file. Fixes: PYSIDE-1191 Change-Id: Iaa7bdc10c7129d84c54e85a09a1c802a409708f9 Reviewed-by: Christian Tismer Reviewed-by: Cristian Maureira-Fredes --- .../PySide2/QtCore/typesystem_core_common.xml | 6 ++- .../ApiExtractor/tests/testtyperevision.cpp | 3 +- sources/shiboken2/ApiExtractor/typedatabase.cpp | 5 +- sources/shiboken2/ApiExtractor/typedatabase.h | 16 +++++- .../shiboken2/ApiExtractor/typesystemparser.cpp | 61 ++++++++++++++-------- .../shiboken2/doc/typesystem_specifying_types.rst | 7 ++- 6 files changed, 69 insertions(+), 29 deletions(-) diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 470e253b1..eec33ea68 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -2830,7 +2830,11 @@ - + + + + + diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp index a7e88e437..10bf35d59 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp @@ -77,6 +77,7 @@ void TestTypeRevision::testVersion_data() QTest::newRow("none") << QString() << 2; QTest::newRow("1.0") << QString::fromLatin1("1.0") << 1; // Bar20 excluded QTest::newRow("2.0") << QString::fromLatin1("2.0") << 2; + QTest::newRow("3.0") << QString::fromLatin1("3.0") << 1; // Bar excluded by "until" } void TestTypeRevision::testVersion() @@ -90,7 +91,7 @@ class Bar20 {}; )CPP"; const char xmlCode[] = R"XML( - + )XML"; diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 014f4dadc..f393bf3bf 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -746,14 +746,15 @@ bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QS } bool TypeDatabase::checkApiVersion(const QString &package, - const QVersionNumber &versionNumber) + const VersionRange &vr) { const ApiVersions &versions = *apiVersions(); if (versions.isEmpty()) // Nothing specified: use latest. return true; for (int i = 0, size = versions.size(); i < size; ++i) { if (versions.at(i).first.match(package).hasMatch()) - return versions.at(i).second >= versionNumber; + return versions.at(i).second >= vr.since + && versions.at(i).second <= vr.until; } return false; } diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index 334e88a14..f615b623d 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -37,9 +37,9 @@ #include #include +#include QT_FORWARD_DECLARE_CLASS(QIODevice) -QT_FORWARD_DECLARE_CLASS(QVersionNumber) class ComplexTypeEntry; class ContainerTypeEntry; @@ -60,6 +60,18 @@ class ContainerTypeEntry; class PrimitiveTypeEntry; class TypeSystemTypeEntry; +struct VersionRange +{ + bool isNull() const + { + return since.majorVersion() == 0 && since.minorVersion() == 0 + && until.majorVersion() == 9999 && until.minorVersion() == 9999; + } + + QVersionNumber since{0, 0}; + QVersionNumber until{9999, 9999}; +}; + class TypeDatabase { TypeDatabase(); @@ -153,7 +165,7 @@ public: static bool setApiVersion(const QString &package, const QString &version); static void clearApiVersions(); - static bool checkApiVersion(const QString &package, const QVersionNumber &version); + static bool checkApiVersion(const QString &package, const VersionRange &vr); bool hasDroppedTypeEntries() const { return !m_dropTypeEntries.isEmpty(); } diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 7388b07fc..0bb56f0fe 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -56,6 +56,7 @@ static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote- static inline QString textAttribute() { return QStringLiteral("text"); } static inline QString nameAttribute() { return QStringLiteral("name"); } static inline QString sinceAttribute() { return QStringLiteral("since"); } +static inline QString untilAttribute() { return QStringLiteral("until"); } static inline QString defaultSuperclassAttribute() { return QStringLiteral("default-superclass"); } static inline QString deleteInMainThreadAttribute() { return QStringLiteral("delete-in-main-thread"); } static inline QString deprecatedAttribute() { return QStringLiteral("deprecated"); } @@ -2582,6 +2583,17 @@ bool TypeSystemParser::parseReplace(const QXmlStreamReader &, return true; } +static bool parseVersion(const QString &versionSpec, const QString &package, + QVersionNumber *result, QString *errorMessage) +{ + *result = QVersionNumber::fromString(versionSpec); + if (result->isNull()) { + *errorMessage = msgInvalidVersion(versionSpec, package); + return false; + } + return true; +} + bool TypeSystemParser::startElement(const QXmlStreamReader &reader) { if (m_ignoreDepth) { @@ -2592,20 +2604,25 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) const QStringRef tagName = reader.name(); QXmlStreamAttributes attributes = reader.attributes(); - QVersionNumber since(0, 0); - int index = indexOfAttribute(attributes, sinceAttribute()); - if (index != -1) { - const QStringRef sinceSpec = attributes.takeAt(index).value(); - since = QVersionNumber::fromString(sinceSpec.toString()); - if (since.isNull()) { - m_error = msgInvalidVersion(sinceSpec, m_defaultPackage); - return false; + VersionRange versionRange; + for (int i = attributes.size() - 1; i >= 0; --i) { + const QStringRef name = attributes.at(i).qualifiedName(); + if (name == sinceAttribute()) { + if (!parseVersion(attributes.takeAt(i).value().toString(), + m_defaultPackage, &versionRange.since, &m_error)) { + return false; + } + } else if (name == untilAttribute()) { + if (!parseVersion(attributes.takeAt(i).value().toString(), + m_defaultPackage, &versionRange.until, &m_error)) { + return false; + } } } - if (!m_defaultPackage.isEmpty() && since > QVersionNumber(0, 0)) { + if (!m_defaultPackage.isEmpty() && !versionRange.isNull()) { TypeDatabase* td = TypeDatabase::instance(); - if (!td->checkApiVersion(m_defaultPackage, since)) { + if (!td->checkApiVersion(m_defaultPackage, versionRange)) { ++m_ignoreDepth; return true; } @@ -2724,15 +2741,15 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) case StackElement::CustomTypeEntry: if (!checkRootElement()) return false; - element->entry = new TypeEntry(name, TypeEntry::CustomType, since, m_current->entry); + element->entry = new TypeEntry(name, TypeEntry::CustomType, versionRange.since, m_current->entry); break; case StackElement::PrimitiveTypeEntry: - element->entry = parsePrimitiveTypeEntry(reader, name, since, &attributes); + element->entry = parsePrimitiveTypeEntry(reader, name, versionRange.since, &attributes); if (Q_UNLIKELY(!element->entry)) return false; break; case StackElement::ContainerTypeEntry: - if (ContainerTypeEntry *ce = parseContainerTypeEntry(reader, name, since, &attributes)) { + if (ContainerTypeEntry *ce = parseContainerTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, ce, &attributes); element->entry = ce; } else { @@ -2741,7 +2758,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) break; case StackElement::SmartPointerTypeEntry: - if (SmartPointerTypeEntry *se = parseSmartPointerEntry(reader, name, since, &attributes)) { + if (SmartPointerTypeEntry *se = parseSmartPointerEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, se, &attributes); element->entry = se; } else { @@ -2749,14 +2766,14 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) } break; case StackElement::EnumTypeEntry: - m_currentEnum = parseEnumTypeEntry(reader, name, since, &attributes); + m_currentEnum = parseEnumTypeEntry(reader, name, versionRange.since, &attributes); if (Q_UNLIKELY(!m_currentEnum)) return false; element->entry = m_currentEnum; break; case StackElement::InterfaceTypeEntry: - if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, since, &attributes)) { + if (ObjectTypeEntry *oe = parseInterfaceTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, oe, &attributes); element->entry = oe; } else { @@ -2764,7 +2781,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) } break; case StackElement::ValueTypeEntry: - if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, since, &attributes)) { + if (ValueTypeEntry *ve = parseValueTypeEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, ve, &attributes); element->entry = ve; } else { @@ -2772,7 +2789,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) } break; case StackElement::NamespaceTypeEntry: - if (auto entry = parseNamespaceTypeEntry(reader, name, since, &attributes)) + if (auto entry = parseNamespaceTypeEntry(reader, name, versionRange.since, &attributes)) element->entry = entry; else return false; @@ -2780,17 +2797,17 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) case StackElement::ObjectTypeEntry: if (!checkRootElement()) return false; - element->entry = new ObjectTypeEntry(name, since, currentParentTypeEntry()); + element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); applyCommonAttributes(element->entry, &attributes); applyComplexTypeAttributes(reader, static_cast(element->entry), &attributes); break; case StackElement::FunctionTypeEntry: - element->entry = parseFunctionTypeEntry(reader, name, since, &attributes); + element->entry = parseFunctionTypeEntry(reader, name, versionRange.since, &attributes); if (Q_UNLIKELY(!element->entry)) return false; break; case StackElement::TypedefTypeEntry: - if (TypedefEntry *te = parseTypedefEntry(reader, name, since, &attributes)) { + if (TypedefEntry *te = parseTypedefEntry(reader, name, versionRange.since, &attributes)) { applyComplexTypeAttributes(reader, te, &attributes); element->entry = te; } else { @@ -2836,7 +2853,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) switch (element->type) { case StackElement::Root: - element->entry = parseRootElement(reader, since, &attributes); + element->entry = parseRootElement(reader, versionRange.since, &attributes); element->type = StackElement::Root; break; case StackElement::LoadTypesystem: diff --git a/sources/shiboken2/doc/typesystem_specifying_types.rst b/sources/shiboken2/doc/typesystem_specifying_types.rst index ac1121461..bca1e0774 100644 --- a/sources/shiboken2/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/doc/typesystem_specifying_types.rst @@ -104,6 +104,7 @@ primitive-type @@ -114,7 +115,11 @@ primitive-type language. If the later two attributes are not specified their default value will be the same as the **name** attribute. - The *optional* **since** value is used to specify the API version of this type. + The *optional* **since** value is used to specify the API version in which + the type was introduced. + + Similarly, the *optional* **until** value can be used to specify the API + version in which the type will be obsoleted. If the *optional* **preferred-conversion** attribute is set to *no*, it indicates that this version of the primitive type is not the preferred C++ -- cgit v1.2.3