diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/modifications.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/modifications.cpp | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp new file mode 100644 index 000000000..d876e8035 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/modifications.cpp @@ -0,0 +1,672 @@ +// 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> +#include <QtCore/QRegularExpression> + +#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 size = s.codeList.size(); + d << "CodeSnip(language=" << s.language << ", position=" << s.position + << ", fragments[" << size << "]="; + for (qsizetype i = 0; i < size; ++i) { + const auto &f = s.codeList.at(i); + if (i) + d << ", "; + d << '#' << i << ' '; + if (!f.instance()) { + d << '"'; + const QString &code = f.code(); + const auto lines = QStringView{code}.split(u'\n'); + for (qsizetype i = 0, size = lines.size(); i < size; ++i) { + if (i) + d << "\\n"; + d << lines.at(i).trimmed(); + } + d << '"'; + } else { + d << "template=\"" << f.instance()->name() << '"'; + } + } + d << ')'; + return d; +} + +class ArgumentModificationData : public QSharedData +{ +public: + ArgumentModificationData(int idx = -1) : index(idx), + removedDefaultExpression(false), removed(false), + noNullPointers(false), resetAfterUse(false), array(false) + {} + + 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; +}; + +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); +} + +class FunctionModificationData : public QSharedData +{ +public: + 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; + TypeSystem::AllowThread m_allowThread = TypeSystem::AllowThread::Unspecified; + TypeSystem::ExceptionHandling m_exceptionHandling = TypeSystem::ExceptionHandling::Unspecified; + TypeSystem::SnakeCase snakeCase = TypeSystem::SnakeCase::Unspecified; +}; + +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; + +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; +} + +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); + + for (const auto &s : functionSignatures) { + if (d->m_signaturePattern.match(s).hasMatch()) + return true; + } + return false; +} + +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 |