diff options
Diffstat (limited to 'sources/shiboken6_generator/ApiExtractor/modifications.cpp')
| -rw-r--r-- | sources/shiboken6_generator/ApiExtractor/modifications.cpp | 746 |
1 files changed, 746 insertions, 0 deletions
diff --git a/sources/shiboken6_generator/ApiExtractor/modifications.cpp b/sources/shiboken6_generator/ApiExtractor/modifications.cpp new file mode 100644 index 000000000..866fd0b6d --- /dev/null +++ b/sources/shiboken6_generator/ApiExtractor/modifications.cpp @@ -0,0 +1,746 @@ +// 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 "modifications.h" +#include "codesnip.h" + +#include "qtcompat.h" + +#include <QtCore/qdebug.h> +#include <QtCore/qregularexpression.h> + +#include <algorithm> +#include <limits> + +using namespace Qt::StringLiterals; + +// ---------------------- FieldModification + +class FieldModificationData : public QSharedData +{ +public: + QString m_name; + QString m_renamedToName; + bool m_readable = true; + bool m_writable = true; + bool m_removed = false; + bool m_opaqueContainer = false; + TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; +}; + +FieldModification::FieldModification() : d(new FieldModificationData) +{ +} + +FieldModification::FieldModification(const FieldModification &) = default; +FieldModification &FieldModification::operator=(const FieldModification &) = default; +FieldModification::FieldModification(FieldModification &&) noexcept = default; +FieldModification &FieldModification::operator=(FieldModification &&) noexcept = default; +FieldModification::~FieldModification() = default; + +QString FieldModification::name() const +{ + return d->m_name; +} + +void FieldModification::setName(const QString &value) +{ + if (d->m_name != value) + d->m_name = value; +} + +bool FieldModification::isRenameModifier() const +{ + return !d->m_renamedToName.isEmpty(); +} + +QString FieldModification::renamedToName() const +{ + return d->m_renamedToName; +} + +void FieldModification::setRenamedToName(const QString &value) +{ + if (d->m_renamedToName != value) + d->m_renamedToName = value; +} + +bool FieldModification::isReadable() const +{ + return d->m_readable; +} + +void FieldModification::setReadable(bool e) +{ + if (d->m_readable != e) + d->m_readable = e; +} + +bool FieldModification::isWritable() const +{ + return d->m_writable; +} + +void FieldModification::setWritable(bool e) +{ + if (d->m_writable != e) + d->m_writable = e; +} + +bool FieldModification::isRemoved() const +{ + return d->m_removed; +} + +void FieldModification::setRemoved(bool r) +{ + if (d->m_removed != r) + d->m_removed = r; +} + +bool FieldModification::isOpaqueContainer() const +{ + return d->m_opaqueContainer; +} + +void FieldModification::setOpaqueContainer(bool r) +{ + if (d->m_opaqueContainer != r) + d->m_opaqueContainer = r; +} + +TypeSystem::SnakeCase FieldModification::snakeCase() const +{ + return d->snakeCase; +} + +void FieldModification::setSnakeCase(TypeSystem::SnakeCase s) +{ + if (d->snakeCase != s) + d->snakeCase = s; +} + +// Remove the parameter names enclosed in '@' from an added function signature +// so that it matches the C++ type signature. +static QString removeParameterNames(QString signature) +{ + while (true) { + const auto ampPos = signature.indexOf(u'@'); + if (ampPos == -1) + break; + const auto closingAmpPos = signature.indexOf(u'@', ampPos + 1); + if (closingAmpPos == -1) + break; + signature.remove(ampPos, closingAmpPos - ampPos + 1); + } + return signature; +} + +DocModification::DocModification(const QString &xpath, const QString &signature) : + m_xpath(xpath), m_signature(removeParameterNames(signature)) +{ +} + +DocModification::DocModification(TypeSystem::DocModificationMode mode, const QString &signature) : + m_signature(removeParameterNames(signature)), m_mode(mode) +{ +} + +void DocModification::setCode(const QString &code) +{ + m_code = CodeSnipAbstract::fixSpaces(code); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const ReferenceCount &r) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "ReferenceCount(" << r.varName << ", action=" << r.action << ')'; + return d; +} + +QDebug operator<<(QDebug d, const CodeSnip &s) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + const auto &fragments = s.codeList(); + const auto size = fragments.size(); + d << "CodeSnip(language=" << s.language << ", position=" << s.position + << ", fragments[" << size << "]="; + for (qsizetype i = 0; i < size; ++i) { + if (i) + d << ", "; + d << '#' << i << ' ' << fragments.at(i); + } + d << ')'; + return d; +} + +class ArgumentModificationData : public QSharedData +{ +public: + ArgumentModificationData(int idx = -1) : index(idx), + removedDefaultExpression(false), removed(false), + noNullPointers(false), resetAfterUse(false), array(false) + {} + + bool equals(const ArgumentModificationData &rhs) const noexcept; + size_t hash(size_t seed) const noexcept; + + QList<ReferenceCount> referenceCounts; + QString modified_type; + QString pyiType; + QString replacedDefaultExpression; + TypeSystem::Ownership m_targetOwnerShip = TypeSystem::UnspecifiedOwnership; + TypeSystem::Ownership m_nativeOwnerShip = TypeSystem::UnspecifiedOwnership; + CodeSnipList conversion_rules; + ArgumentOwner owner; + QString renamed_to; + int index = -1; + uint removedDefaultExpression : 1; + uint removed : 1; + uint noNullPointers : 1; + uint resetAfterUse : 1; + uint array : 1; +}; + +bool ArgumentModificationData::equals(const ArgumentModificationData &rhs) const noexcept +{ + return referenceCounts == rhs.referenceCounts + && modified_type == rhs.modified_type + && pyiType == rhs.pyiType + && replacedDefaultExpression == rhs.replacedDefaultExpression + && m_targetOwnerShip == rhs.m_targetOwnerShip + && m_nativeOwnerShip == rhs.m_nativeOwnerShip + && conversion_rules == rhs.conversion_rules + && owner == rhs.owner + && renamed_to == rhs.renamed_to + && index == rhs.index + && removedDefaultExpression == rhs.removedDefaultExpression + && removed == rhs.removedDefaultExpression + && noNullPointers == rhs.noNullPointers + && resetAfterUse == rhs.resetAfterUse + && array == rhs.array; +} + +size_t ArgumentModificationData::hash(size_t seed) const noexcept +{ + return qHashMulti(seed, referenceCounts, modified_type, pyiType,replacedDefaultExpression, + m_targetOwnerShip, m_nativeOwnerShip, conversion_rules, owner, + renamed_to, index, removedDefaultExpression, removed, noNullPointers, + resetAfterUse, array); +} + +ArgumentModification::ArgumentModification() : d(new ArgumentModificationData) +{ +} + +ArgumentModification::ArgumentModification(int idx) : d(new ArgumentModificationData(idx)) +{ +} + +ArgumentModification::ArgumentModification(const ArgumentModification &) = default; +ArgumentModification &ArgumentModification::operator=(const ArgumentModification &) = default; +ArgumentModification::ArgumentModification(ArgumentModification &&) noexcept = default; +ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) noexcept = default; +ArgumentModification::~ArgumentModification() = default; + +const QString &ArgumentModification::modifiedType() const +{ + return d->modified_type; +} + +void ArgumentModification::setModifiedType(const QString &value) +{ + if (d->modified_type != value) + d->modified_type = value; +} + +bool ArgumentModification::isTypeModified() const +{ + return !d->modified_type.isEmpty(); +} + +QString ArgumentModification::pyiType() const +{ + return d->pyiType; +} + +void ArgumentModification::setPyiType(const QString &value) +{ + if (d->pyiType != value) + d->pyiType = value; +} + +QString ArgumentModification::replacedDefaultExpression() const +{ + return d->replacedDefaultExpression; +} + +void ArgumentModification::setReplacedDefaultExpression(const QString &value) +{ + if (d->replacedDefaultExpression != value) + d->replacedDefaultExpression = value; +} + +TypeSystem::Ownership ArgumentModification::targetOwnerShip() const +{ + return d->m_targetOwnerShip; +} + +void ArgumentModification::setTargetOwnerShip(TypeSystem::Ownership o) +{ + if (o != d->m_targetOwnerShip) + d->m_targetOwnerShip = o; +} + +TypeSystem::Ownership ArgumentModification::nativeOwnership() const +{ + return d->m_nativeOwnerShip; +} + +void ArgumentModification::setNativeOwnership(TypeSystem::Ownership o) +{ + if (o != d->m_nativeOwnerShip) + d->m_nativeOwnerShip = o; +} + +const CodeSnipList &ArgumentModification::conversionRules() const +{ + return d->conversion_rules; +} + +CodeSnipList &ArgumentModification::conversionRules() +{ + return d->conversion_rules; +} + +ArgumentOwner ArgumentModification::owner() const +{ + return d->owner; +} + +void ArgumentModification::setOwner(const ArgumentOwner &value) +{ + d->owner = value; +} + +QString ArgumentModification::renamedToName() const +{ + return d->renamed_to; +} + +void ArgumentModification::setRenamedToName(const QString &value) +{ + if (d->renamed_to != value) + d->renamed_to = value; +} + +int ArgumentModification::index() const +{ + return d->index; +} + +void ArgumentModification::setIndex(int value) +{ + if (d->index != value) + d->index = value; +} + +bool ArgumentModification::removedDefaultExpression() const +{ + return d->removedDefaultExpression; +} + +void ArgumentModification::setRemovedDefaultExpression(const uint &value) +{ + if (d->removedDefaultExpression != value) + d->removedDefaultExpression = value; +} + +bool ArgumentModification::isRemoved() const +{ + return d->removed; +} + +void ArgumentModification::setRemoved(bool value) +{ + if (d->removed != value) + d->removed = value; +} + +bool ArgumentModification::noNullPointers() const +{ + return d->noNullPointers; +} + +void ArgumentModification::setNoNullPointers(bool value) +{ + if (d->noNullPointers != value) + d->noNullPointers = value; +} + +bool ArgumentModification::resetAfterUse() const +{ + return d->resetAfterUse; +} + +void ArgumentModification::setResetAfterUse(bool value) +{ + if (d->resetAfterUse != value) + d->resetAfterUse = value; +} + +bool ArgumentModification::isArray() const +{ + return d->array; +} + +void ArgumentModification::setArray(bool value) +{ + if (d->array != value) + d->array = value; +} + +const QList<ReferenceCount> &ArgumentModification::referenceCounts() const +{ + return d->referenceCounts; +} + +void ArgumentModification::addReferenceCount(const ReferenceCount &value) +{ + d->referenceCounts.append(value); +} + +bool ArgumentModification::equals(const ArgumentModification &rhs) const noexcept +{ + return d.constData() == rhs.d.constData() || d->equals(*rhs.d); +} + +size_t ArgumentModification::hash(size_t seed) const noexcept +{ + return d->hash(seed); +} + +class FunctionModificationData : public QSharedData +{ +public: + bool equals(const FunctionModificationData &rhs) const noexcept; + size_t hash(size_t seed) const noexcept; + + QString renamedToName; + FunctionModification::Modifiers modifiers; + CodeSnipList m_snips; + QList<ArgumentModification> m_argument_mods; + QString m_signature; + QString m_originalSignature; + QRegularExpression m_signaturePattern; + int m_overloadNumber = TypeSystem::OverloadNumberUnset; + bool removed = false; + bool inherited = false; + TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified; + TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; + TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; +}; + +bool FunctionModificationData::equals(const FunctionModificationData &rhs) const noexcept +{ + return renamedToName == rhs.renamedToName + && modifiers == rhs.modifiers + && m_snips == rhs.m_snips + && m_argument_mods == rhs.m_argument_mods + && m_signature == rhs.m_signature + && m_originalSignature == rhs.m_originalSignature + && m_signaturePattern == rhs.m_signaturePattern + && m_overloadNumber == rhs.m_overloadNumber + && removed == rhs.removed + && inherited == rhs.inherited + && m_allowThread == rhs.m_allowThread + && m_exceptionHandling == rhs.m_exceptionHandling + && snakeCase == rhs.snakeCase; +} + +size_t FunctionModificationData::hash(size_t seed) const noexcept +{ + return qHashMulti(seed, renamedToName, modifiers, m_snips, m_argument_mods, m_signature, + m_originalSignature, m_signaturePattern, m_overloadNumber, removed, + inherited, m_allowThread, m_exceptionHandling, snakeCase); +} + +FunctionModification::FunctionModification() : d(new FunctionModificationData) +{ +} + +FunctionModification::FunctionModification(const FunctionModification &) = default; +FunctionModification &FunctionModification::operator=(const FunctionModification &) = default; +FunctionModification::FunctionModification(FunctionModification &&) noexcept = default; +FunctionModification &FunctionModification::operator=(FunctionModification &&) noexcept = default; +FunctionModification::~FunctionModification() = default; + +bool FunctionModification::equals(const FunctionModification &rhs) const noexcept +{ + return d.constData() == rhs.d.constData() || d->equals(*rhs.d); +} + +size_t FunctionModification::hash(size_t seed) const noexcept +{ + return d->hash(seed); +} + +void FunctionModification::formatDebug(QDebug &debug) const +{ + if (d->m_signature.isEmpty()) + debug << "pattern=\"" << d->m_signaturePattern.pattern(); + else + debug << "signature=\"" << d->m_signature; + debug << "\", modifiers=" << d->modifiers; + if (d->removed) + debug << ", removed"; + if (!d->renamedToName.isEmpty()) + debug << ", renamedToName=\"" << d->renamedToName << '"'; + if (d->m_allowThread != TypeSystem::AllowThread::Unspecified) + debug << ", allowThread=" << int(d->m_allowThread); + if (d->m_exceptionHandling != TypeSystem::ExceptionHandling::Unspecified) + debug << ", exceptionHandling=" << int(d->m_exceptionHandling); + if (!d->m_snips.isEmpty()) + debug << ", snips=(" << d->m_snips << ')'; + if (!d->m_argument_mods.isEmpty()) + debug << ", argument_mods=(" << d->m_argument_mods << ')'; +} + +QString FunctionModification::renamedToName() const +{ + return d->renamedToName; +} + +void FunctionModification::setRenamedToName(const QString &value) +{ + if (d->renamedToName != value) + d->renamedToName = value; +} + +FunctionModification::Modifiers FunctionModification::modifiers() const +{ + return d->modifiers; +} + +void FunctionModification::setModifiers(Modifiers m) +{ + if (d->modifiers != m) + d->modifiers = m; +} + +void FunctionModification::setModifierFlag(FunctionModification::ModifierFlag f) +{ + auto newMods = d->modifiers | f; + if (d->modifiers != newMods) + d->modifiers = newMods; +} + +void FunctionModification::clearModifierFlag(ModifierFlag f) +{ + auto newMods = d->modifiers & ~f; + if (d->modifiers != newMods) + d->modifiers = newMods; +} + +bool FunctionModification::isRemoved() const +{ + return d->removed; +} + +void FunctionModification::setRemoved(bool r) +{ + if (d->removed != r) + d->removed = r; +} + +bool FunctionModification::isInherited() const +{ + return d->inherited; +} + +void FunctionModification::setInherited(bool i) +{ + if (d->inherited != i) + d->inherited = i; +} + +const QList<ArgumentModification> &FunctionModification::argument_mods() const +{ + return d->m_argument_mods; +} + +QList<ArgumentModification> &FunctionModification::argument_mods() +{ + return d->m_argument_mods; +} + +void FunctionModification::setArgument_mods(const QList<ArgumentModification> &argument_mods) +{ + d->m_argument_mods = argument_mods; +} + +TypeSystem::SnakeCase FunctionModification::snakeCase() const +{ + return d->snakeCase; +} + +void FunctionModification::setSnakeCase(TypeSystem::SnakeCase s) +{ + if (d->snakeCase != s) + d->snakeCase = s; +} + +const CodeSnipList &FunctionModification::snips() const +{ + return d->m_snips; +} + +CodeSnipList &FunctionModification::snips() +{ + return d->m_snips; +} + +void FunctionModification::appendSnip(const CodeSnip &snip) +{ + d->m_snips.append(snip); +} + +void FunctionModification::setSnips(const CodeSnipList &snips) +{ + d->m_snips = snips; +} + +// ---------------------- FunctionModification +FunctionModification::AllowThread FunctionModification::allowThread() const +{ + return d->m_allowThread; +} + +void FunctionModification::setAllowThread(FunctionModification::AllowThread allow) +{ + if (d->m_allowThread != allow) + d->m_allowThread = allow; +} + +bool FunctionModification::matches(const QStringList &functionSignatures) const +{ + if (!d->m_signature.isEmpty()) + return functionSignatures.contains(d->m_signature); + + const auto &pattern = d->m_signaturePattern; + return std::any_of(functionSignatures.cbegin(), functionSignatures.end(), + [&pattern] (const QString &s) { return pattern.match(s).hasMatch(); }); +} + +bool FunctionModification::setSignature(const QString &s, QString *errorMessage) +{ + if (s.startsWith(u'^')) { + d->m_signaturePattern.setPattern(s); + if (!d->m_signaturePattern.isValid()) { + if (errorMessage) { + *errorMessage = u"Invalid signature pattern: \""_s + + s + u"\": "_s + d->m_signaturePattern.errorString(); + } + return false; + } + } else { + d->m_signature = s; + } + return true; +} + +QString FunctionModification::signature() const +{ + return d->m_signature.isEmpty() ? d->m_signaturePattern.pattern() : d->m_signature; +} + +void FunctionModification::setOriginalSignature(const QString &s) +{ + if (d->m_originalSignature != s) + d->m_originalSignature = s; +} + +QString FunctionModification::originalSignature() const +{ + return d->m_originalSignature; +} + +TypeSystem::ExceptionHandling FunctionModification::exceptionHandling() const +{ + return d->m_exceptionHandling; +} + +void FunctionModification::setExceptionHandling(TypeSystem::ExceptionHandling e) +{ + if (d->m_exceptionHandling != e) + d->m_exceptionHandling = e; +} + +int FunctionModification::overloadNumber() const +{ + return d->m_overloadNumber; +} + +void FunctionModification::setOverloadNumber(int overloadNumber) +{ + d->m_overloadNumber = overloadNumber; +} + +QDebug operator<<(QDebug d, const ArgumentOwner &a) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "ArgumentOwner(index=" << a.index << ", action=" << a.action << ')'; + return d; +} + +QDebug operator<<(QDebug d, const ArgumentModification &a) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "ArgumentModification(index=" << a.index(); + if (a.removedDefaultExpression()) + d << ", removedDefaultExpression"; + if (a.isRemoved()) + d << ", removed"; + if (a.noNullPointers()) + d << ", noNullPointers"; + if (a.isArray()) + d << ", array"; + if (!a.referenceCounts().isEmpty()) + d << ", referenceCounts=" << a.referenceCounts(); + if (!a.modifiedType().isEmpty()) + d << ", modified_type=\"" << a.modifiedType() << '"'; + if (!a.replacedDefaultExpression().isEmpty()) + d << ", replacedDefaultExpression=\"" << a.replacedDefaultExpression() << '"'; + if (a.targetOwnerShip() != TypeSystem::UnspecifiedOwnership) + d << ", target ownership=" << a.targetOwnerShip(); + if (a.nativeOwnership() != TypeSystem::UnspecifiedOwnership) + d << ", native ownership=" << a.nativeOwnership(); + if (!a.renamedToName().isEmpty()) + d << ", renamed_to=\"" << a.renamedToName() << '"'; + const auto &rules = a.conversionRules(); + if (!rules.isEmpty()) + d << ", conversionRules[" << rules.size() << "]=" << rules; + d << ", owner=" << a.owner() << ')'; + return d; +} + +QDebug operator<<(QDebug d, const FunctionModification &fm) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "FunctionModification("; + fm.formatDebug(d); + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM |
