diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetaenum.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetaenum.cpp | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp new file mode 100644 index 000000000..780170c22 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp @@ -0,0 +1,423 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "abstractmetaenum.h" +#include "abstractmetalang.h" +#include "documentation.h" +#include "enumtypeentry.h" +#include "parser/enumvalue.h" + +#include "qtcompat.h" + +#include <QtCore/QDebug> + +#include <algorithm> + +using namespace Qt::StringLiterals; + +class AbstractMetaEnumValueData : public QSharedData +{ +public: + QString m_name; + QString m_stringValue; + EnumValue m_value; + Documentation m_doc; + bool m_deprecated = false; +}; + +AbstractMetaEnumValue::AbstractMetaEnumValue() : + d(new AbstractMetaEnumValueData) +{ +} + +AbstractMetaEnumValue::AbstractMetaEnumValue(const AbstractMetaEnumValue &) = default; +AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(const AbstractMetaEnumValue &) = default; +AbstractMetaEnumValue::AbstractMetaEnumValue(AbstractMetaEnumValue &&) noexcept = default; +AbstractMetaEnumValue &AbstractMetaEnumValue::operator=(AbstractMetaEnumValue &&) noexcept = default; +AbstractMetaEnumValue::~AbstractMetaEnumValue() = default; + +EnumValue AbstractMetaEnumValue::value() const +{ + return d->m_value; +} + +void AbstractMetaEnumValue::setValue(EnumValue value) +{ + if (d->m_value != value) + d->m_value = value; +} + +QString AbstractMetaEnumValue::stringValue() const +{ + return d->m_stringValue; +} + +void AbstractMetaEnumValue::setStringValue(const QString &v) +{ + if (d->m_stringValue != v) + d->m_stringValue = v; +} + +QString AbstractMetaEnumValue::name() const +{ + return d->m_name; +} + +void AbstractMetaEnumValue::setName(const QString &name) +{ + if (d->m_name != name) + d->m_name = name; +} + +bool AbstractMetaEnumValue::isDeprecated() const +{ + return d->m_deprecated; +} + +void AbstractMetaEnumValue::setDeprecated(bool deprecated) +{ + if (d->m_deprecated != deprecated) + d->m_deprecated = deprecated; +} + +Documentation AbstractMetaEnumValue::documentation() const +{ + return d->m_doc; +} + +void AbstractMetaEnumValue::setDocumentation(const Documentation &doc) +{ + if (d->m_doc != doc) + d->m_doc = doc; +} + +// --------------------- AbstractMetaEnum + +class AbstractMetaEnumData : public QSharedData +{ +public: + AbstractMetaEnumData() : m_deprecated(false), + m_hasQenumsDeclaration(false), m_signed(true) + { + } + + int unsignedUsedBits() const; + int signedUsedBits() const; + + AbstractMetaEnumValueList m_enumValues; + + EnumTypeEntryCPtr m_typeEntry; + Documentation m_doc; + QString m_underlyingType; + + EnumKind m_enumKind = CEnum; + Access m_access = Access::Public; + uint m_deprecated : 1; + uint m_hasQenumsDeclaration : 1; + uint m_signed : 1; +}; + +static int _usedBits(uint64_t v) +{ + return (v >> 32) ? 64 : (v >> 16) ? 32 : (v >> 8) ? 16 : 8; +} + +static int _usedBits(int64_t v) +{ + return (v >> 31) ? 64 : (v >> 15) ? 32 : (v >> 7) ? 16 : 8; +} + +int AbstractMetaEnumData::unsignedUsedBits() const +{ + uint64_t maxValue = 0; + for (const auto &v : m_enumValues) { + if (const auto uv = v.value().unsignedValue(); uv > maxValue) + maxValue = uv; + } + return _usedBits(maxValue); +} + +int AbstractMetaEnumData::signedUsedBits() const +{ + int64_t maxValue = 0; + for (const auto &v : m_enumValues) { + const auto sv = v.value().value(); + const auto absV = sv < 0 ? ~sv : sv; + if (absV > maxValue) + maxValue = absV; + } + return _usedBits(maxValue); +} + +AbstractMetaEnum::AbstractMetaEnum() : d(new AbstractMetaEnumData) +{ +} + +AbstractMetaEnum::AbstractMetaEnum(const AbstractMetaEnum &) = default; +AbstractMetaEnum &AbstractMetaEnum::operator=(const AbstractMetaEnum&) = default; +AbstractMetaEnum::AbstractMetaEnum(AbstractMetaEnum &&) noexcept = default; +AbstractMetaEnum &AbstractMetaEnum::operator=(AbstractMetaEnum &&) noexcept = default; +AbstractMetaEnum::~AbstractMetaEnum() = default; + +const AbstractMetaEnumValueList &AbstractMetaEnum::values() const +{ + return d->m_enumValues; +} + +AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const +{ + auto te = d->m_typeEntry; + AbstractMetaEnumValueList result = d->m_enumValues; + auto pred = [te](const AbstractMetaEnumValue &v) { + return te->isEnumValueRejected(v.name()); }; + result.erase(std::remove_if(result.begin(), result.end(), pred), result.end()); + return result; +} + +void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue) +{ + d->m_enumValues << enumValue; +} + +std::optional<AbstractMetaEnumValue> + findMatchingEnumValue(const AbstractMetaEnumValueList &list, QStringView value) +{ + for (const AbstractMetaEnumValue &enumValue : list) { + if (enumValue.name() == value) + return enumValue; + } + return {}; +} + +// Find enum values for "enum Enum { e1 }" either for "e1" or "Enum::e1" +std::optional<AbstractMetaEnumValue> + AbstractMetaEnum::findEnumValue(QStringView value) const +{ + if (isAnonymous()) + return findMatchingEnumValue(d->m_enumValues, value); + const int sepPos = value.indexOf(u"::"); + if (sepPos == -1) + return findMatchingEnumValue(d->m_enumValues, value); + if (name() == value.left(sepPos)) + return findMatchingEnumValue(d->m_enumValues, value.right(value.size() - sepPos - 2)); + return {}; +} + +QString AbstractMetaEnum::name() const +{ + return d->m_typeEntry->targetLangEntryName(); +} + +QString AbstractMetaEnum::qualifiedCppName() const +{ + return enclosingClass() + ? enclosingClass()->qualifiedCppName() + u"::"_s + name() + : name(); +} + +Access AbstractMetaEnum::access() const +{ + return d->m_access; +} + +void AbstractMetaEnum::setAccess(Access a) +{ + if (a != d->m_access) + d->m_access = a; +} + +bool AbstractMetaEnum::isDeprecated() const +{ + return d->m_deprecated; +} + +void AbstractMetaEnum::setDeprecated(bool deprecated) +{ + if (d->m_deprecated != deprecated) + d->m_deprecated = deprecated; +} + +static bool isDeprecatedValue(const AbstractMetaEnumValue &v) +{ + return v.isDeprecated(); +}; + +bool AbstractMetaEnum::hasDeprecatedValues() const +{ + return std::any_of(d->m_enumValues.cbegin(), d->m_enumValues.cend(), + isDeprecatedValue); +} + +AbstractMetaEnumValueList AbstractMetaEnum::deprecatedValues() const +{ + AbstractMetaEnumValueList result; + std::copy_if(d->m_enumValues.cbegin(), d->m_enumValues.cend(), + std::back_inserter(result), isDeprecatedValue); + return result; +} + +const Documentation &AbstractMetaEnum::documentation() const +{ + return d->m_doc; +} + +void AbstractMetaEnum::setDocumentation(const Documentation &doc) +{ + if (d->m_doc != doc) + d->m_doc = doc; +} + +QString AbstractMetaEnum::qualifier() const +{ + return d->m_typeEntry->targetLangQualifier(); +} + +QString AbstractMetaEnum::package() const +{ + return d->m_typeEntry->targetLangPackage(); +} + +QString AbstractMetaEnum::fullName() const +{ + return package() + u'.' + qualifier() + u'.' + name(); +} + +EnumKind AbstractMetaEnum::enumKind() const +{ + return d->m_enumKind; +} + +void AbstractMetaEnum::setEnumKind(EnumKind kind) +{ + if (d->m_enumKind != kind) + d->m_enumKind = kind; +} + +bool AbstractMetaEnum::isAnonymous() const +{ + return d->m_enumKind == AnonymousEnum; +} + +bool AbstractMetaEnum::hasQEnumsDeclaration() const +{ + return d->m_hasQenumsDeclaration; +} + +void AbstractMetaEnum::setHasQEnumsDeclaration(bool on) +{ + if (d->m_hasQenumsDeclaration != on) + d->m_hasQenumsDeclaration = on; +} + +EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const +{ + return d->m_typeEntry; +} + +void AbstractMetaEnum::setTypeEntry(const EnumTypeEntryCPtr &entry) +{ + if (d->m_typeEntry != entry) + d->m_typeEntry = entry; +} + +bool AbstractMetaEnum::isSigned() const +{ + return d->m_signed; +} + +void AbstractMetaEnum::setSigned(bool s) +{ + if (d->m_signed != s) + d->m_signed = s; +} + +QString AbstractMetaEnum::underlyingType() const +{ + return d->m_underlyingType; +} + +void AbstractMetaEnum::setUnderlyingType(const QString &underlyingType) +{ + if (d->m_underlyingType != underlyingType) + d->m_underlyingType = underlyingType; +} + +int AbstractMetaEnum::usedBits() const +{ + return isSigned() ? d->signedUsedBits() : d->unsignedUsedBits(); +} + +QString AbstractMetaEnum::intTypeForSize(int usedBits, bool isSigned) +{ + QString result = u"int"_s + QString::number(usedBits) + u"_t"_s; + return isSigned ? result : u'u' + result; +} + +#ifndef QT_NO_DEBUG_STREAM + +static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue &v, bool forceHex = false) +{ + d << v.name() << '='; + if (forceHex) + v.value().formatDebugHex(d); + else + v.value().formatDebug(d); + if (v.isDeprecated()) + d << " (deprecated)"; +} + +QDebug operator<<(QDebug d, const AbstractMetaEnumValue &v) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaEnumValue("; + formatMetaEnumValue(d, v); + d << ')'; + return d; +} + +static void formatMetaEnum(QDebug &d, const AbstractMetaEnum &e) +{ + d << '"' << e.fullName() << '"'; + if (e.isDeprecated()) + d << " (deprecated)"; + d << " \"" << e.underlyingType() << '"'; + if (!e.isSigned()) + d << " (unsigned)"; + d << " ["; + const AbstractMetaEnumValueList &values = e.values(); + const bool hasFlags = e.typeEntry()->flags() != nullptr; + for (qsizetype i = 0, count = values.size(); i < count; ++i) { + if (i) + d << ", "; + formatMetaEnumValue(d, values.at(i), hasFlags); + } + d << ']'; +} + +QDebug operator<<(QDebug d, const AbstractMetaEnum *ae) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaEnum("; + if (ae) + formatMetaEnum(d, *ae); + else + d << '0'; + d << ')'; + return d; +} + +QDebug operator<<(QDebug d, const AbstractMetaEnum &ae) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaEnum("; + formatMetaEnum(d, ae); + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM |