diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetalang.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/abstractmetalang.cpp | 2707 |
1 files changed, 0 insertions, 2707 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp deleted file mode 100644 index 390143cda..000000000 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ /dev/null @@ -1,2707 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "abstractmetalang.h" -#include "messages.h" -#include "reporthandler.h" -#include "typedatabase.h" -#include "typesystem.h" - -#include <parser/codemodel.h> - -#ifndef QT_NO_DEBUG_STREAM -# include <QtCore/QMetaEnum> -# include <QtCore/QMetaObject> -#endif - -#include <QtCore/QRegularExpression> -#include <QtCore/QStack> - -#include <algorithm> - -#include <algorithm> - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaAttributes("; - if (aa) - d << aa->attributes(); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -template <class MetaClass> -MetaClass *findByName(QVector<MetaClass *> haystack, QStringView needle) -{ - for (MetaClass *c : haystack) { - if (c->name() == needle) - return c; - } - return nullptr; -} - -// Helper for recursing the base classes of an AbstractMetaClass. -// Returns the class for which the predicate is true. -template <class Predicate> -const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass, - Predicate pred) -{ - if (pred(klass)) - return klass; - for (auto base : klass->baseClasses()) { - if (auto r = recurseClassHierarchy(base, pred)) - return r; - } - return nullptr; -} - -/******************************************************************************* - * AbstractMetaVariable - */ - -AbstractMetaVariable::AbstractMetaVariable() = default; - -AbstractMetaVariable::~AbstractMetaVariable() -{ - delete m_type; -} - -void AbstractMetaVariable::assignMetaVariable(const AbstractMetaVariable &other) -{ - m_originalName = other.m_originalName; - m_name = other.m_name; - m_type = other.m_type->copy(); - m_hasName = other.m_hasName; - m_doc = other.m_doc; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaVariable *av) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaVariable("; - if (av) { - d << av->type()->name() << ' ' << av->name(); - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaAttributes - */ - -AbstractMetaAttributes::AbstractMetaAttributes() = default; -AbstractMetaAttributes::~AbstractMetaAttributes() = default; - -void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes &other) -{ - m_attributes = other.m_attributes; - m_originalAttributes = other.m_originalAttributes; - m_doc = other.m_doc; -} - -/******************************************************************************* - * AbstractMetaType - */ - -AbstractMetaType::AbstractMetaType() : - m_constant(false), - m_volatile(false), - m_cppInstantiation(true), - m_reserved(0) -{ -} - -AbstractMetaType::~AbstractMetaType() -{ - qDeleteAll(m_children); - m_instantiations.clear(); -} - -QString AbstractMetaType::package() const -{ - return m_typeEntry->targetLangPackage(); -} - -QString AbstractMetaType::name() const -{ - return m_typeEntry->targetLangEntryName(); -} - -QString AbstractMetaType::fullName() const -{ - return m_typeEntry->qualifiedTargetLangName(); -} - -AbstractMetaType *AbstractMetaType::copy() const -{ - auto *cpy = new AbstractMetaType; - - cpy->setTypeUsagePattern(typeUsagePattern()); - cpy->setConstant(isConstant()); - cpy->setVolatile(isVolatile()); - cpy->setReferenceType(referenceType()); - cpy->setIndirectionsV(indirectionsV()); - cpy->setInstantiations(instantiations()); - cpy->setArrayElementCount(arrayElementCount()); - cpy->setOriginalTypeDescription(originalTypeDescription()); - cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : nullptr); - - cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : nullptr); - - cpy->setTypeEntry(typeEntry()); - - return cpy; -} - -// For applying the <array> function argument modification: change into a type -// where "int *" becomes "int[]". -bool AbstractMetaType::applyArrayModification(QString *errorMessage) -{ - if (m_pattern == AbstractMetaType::NativePointerAsArrayPattern) { - *errorMessage = QLatin1String("<array> modification already applied."); - return false; - } - if (m_arrayElementType != nullptr) { - QTextStream(errorMessage) << "The type \"" << cppSignature() - << "\" is an array of " << m_arrayElementType->name() << '.'; - return false; - } - if (m_indirections.isEmpty()) { - QTextStream(errorMessage) << "The type \"" << cppSignature() - << "\" does not have indirections."; - return false; - } - // Element type to be used for ArrayHandle<>, strip constness. - auto elementType = copy(); - elementType->m_indirections.pop_front(); - elementType->setConstant(false); - elementType->setVolatile(false); - elementType->decideUsagePattern(); - m_arrayElementType = elementType; - setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern); - return true; -} - -AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const -{ - AbstractMetaTypeCList result; - switch (m_pattern) { - case ArrayPattern: - for (const AbstractMetaType *t = this; t->typeUsagePattern() == ArrayPattern; ) { - const AbstractMetaType *elt = t->arrayElementType(); - result.append(elt); - t = elt; - } - break; - case NativePointerAsArrayPattern: - result.append(m_arrayElementType); - break; - default: - break; - } - return result; -} - -bool AbstractMetaType::passByConstRef() const -{ - return isConstant() && m_referenceType == LValueReference && indirections() == 0; -} - -bool AbstractMetaType::passByValue() const -{ - return m_referenceType == NoReference && indirections() == 0; -} - -QString AbstractMetaType::cppSignature() const -{ - if (m_cachedCppSignature.isEmpty()) - m_cachedCppSignature = formatSignature(false); - return m_cachedCppSignature; -} - -QString AbstractMetaType::pythonSignature() const -{ - // PYSIDE-921: Handle container returntypes correctly. - // This is now a clean reimplementation. - if (m_cachedPythonSignature.isEmpty()) - m_cachedPythonSignature = formatPythonSignature(); - return m_cachedPythonSignature; -} - -AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() const -{ - if (m_typeEntry->isTemplateArgument() || m_referenceType == RValueReference) - return InvalidPattern; - - if (m_typeEntry->isPrimitive() && (actualIndirections() == 0 || passByConstRef())) - return PrimitivePattern; - - if (m_typeEntry->isVoid()) - return NativePointerPattern; - - if (m_typeEntry->isVarargs()) - return VarargsPattern; - - if (m_typeEntry->isEnum() && (actualIndirections() == 0 || passByConstRef())) - return EnumPattern; - - if (m_typeEntry->isObject()) { - if (indirections() == 0 && m_referenceType == NoReference) - return ValuePattern; - return ObjectPattern; - } - - if (m_typeEntry->isContainer() && indirections() == 0) - return ContainerPattern; - - if (m_typeEntry->isSmartPointer() && indirections() == 0) - return SmartPointerPattern; - - if (m_typeEntry->isFlags() && (actualIndirections() == 0 || passByConstRef())) - return FlagsPattern; - - if (m_typeEntry->isArray()) - return ArrayPattern; - - if (m_typeEntry->isValue()) - return indirections() == 1 ? ValuePointerPattern : ValuePattern; - - return NativePointerPattern; -} - -void AbstractMetaType::decideUsagePattern() -{ - TypeUsagePattern pattern = determineUsagePattern(); - if (m_typeEntry->isObject() && indirections() == 1 - && m_referenceType == LValueReference && isConstant()) { - // const-references to pointers can be passed as pointers - setReferenceType(NoReference); - setConstant(false); - pattern = ObjectPattern; - } - setTypeUsagePattern(pattern); -} - -bool AbstractMetaType::hasTemplateChildren() const -{ - QStack<AbstractMetaType *> children; - children << m_children; - - // Recursively iterate over the children / descendants of the type, to check if any of them - // corresponds to a template argument type. - while (!children.isEmpty()) { - AbstractMetaType *child = children.pop(); - if (child->typeEntry()->isTemplateArgument()) - return true; - children << child->m_children; - } - - return false; -} - -bool AbstractMetaType::compare(const AbstractMetaType &rhs, ComparisonFlags flags) const -{ - if (m_typeEntry != rhs.m_typeEntry - || m_indirections != rhs.m_indirections - || m_instantiations.size() != rhs.m_instantiations.size() - || m_arrayElementCount != rhs.m_arrayElementCount) { - return false; - } - - if (m_constant != rhs.m_constant || m_referenceType != rhs.m_referenceType) { - if (!flags.testFlag(ConstRefMatchesValue) - || !(passByValue() || passByConstRef()) - || !(rhs.passByValue() || rhs.passByConstRef())) { - return false; - } - } - - if ((m_arrayElementType != nullptr) != (rhs.m_arrayElementType != nullptr) - || (m_arrayElementType != nullptr && !m_arrayElementType->compare(*rhs.m_arrayElementType, flags))) { - return false; - } - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { - if (!m_instantiations.at(i)->compare(*rhs.m_instantiations.at(i), flags)) - return false; - } - return true; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaType *at) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaType("; - if (at) { - d << at->name(); - if (d.verbosity() > 2) { - d << ", typeEntry=" << at->typeEntry() << ", signature=\"" - << at->cppSignature() << "\", pattern=" - << at->typeUsagePattern(); - const auto indirections = at->indirectionsV(); - if (!indirections.isEmpty()) { - d << ", indirections="; - for (auto i : indirections) - d << ' ' << TypeInfo::indirectionKeyword(i); - } - if (at->referenceType()) - d << ", reftype=" << at->referenceType(); - if (at->isConstant()) - d << ", [const]"; - if (at->isVolatile()) - d << ", [volatile]"; - if (at->isArray()) { - d << ", array of \"" << at->arrayElementType()->cppSignature() - << "\", arrayElementCount=" << at->arrayElementCount(); - } - const auto &instantiations = at->instantiations(); - if (const int instantiationsSize = instantiations.size()) { - d << ", instantiations[" << instantiationsSize << "]=<"; - for (int i = 0; i < instantiationsSize; ++i) { - if (i) - d << ", "; - d << instantiations.at(i); - } - } - d << '>'; - } - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaArgument - */ - -AbstractMetaArgument::AbstractMetaArgument() = default; - -void AbstractMetaArgument::assignMetaArgument(const AbstractMetaArgument &other) -{ - assignMetaVariable(other); - m_expression = other.m_expression; - m_originalExpression = other.m_originalExpression; - m_argumentIndex = other.m_argumentIndex; -} - -AbstractMetaArgument *AbstractMetaArgument::copy() const -{ - auto *copy = new AbstractMetaArgument; - copy->assignMetaArgument(*this); - return copy; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaArgument("; - if (aa) - d << aa->toString(); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaFunction - */ - -AbstractMetaFunction::AbstractMetaFunction(const AddedFunctionPtr &addedFunc) : - AbstractMetaFunction() -{ - m_addedFunction = addedFunc; - setConstant(addedFunc->isConstant()); - setName(addedFunc->name()); - setOriginalName(addedFunc->name()); - auto atts = attributes() | AbstractMetaAttributes::FinalInTargetLang; - switch (addedFunc->access()) { - case AddedFunction::InvalidAccess: - break; - case AddedFunction::Protected: - atts |= AbstractMetaAttributes::Protected; - break; - case AddedFunction::Public: - atts |= AbstractMetaAttributes::Public; - break; - } - if (addedFunc->isStatic()) - atts |= AbstractMetaFunction::Static; - setAttributes(atts); -} - -AbstractMetaFunction::AbstractMetaFunction() - : m_constant(false), - m_reverse(false), - m_explicit(false), - m_pointerOperator(false), - m_isCallOperator(false) -{ -} - -AbstractMetaFunction::~AbstractMetaFunction() -{ - qDeleteAll(m_arguments); - delete m_type; -} - -/******************************************************************************* - * Indicates that this function has a modification that removes it - */ -bool AbstractMetaFunction::isModifiedRemoved(int types) const -{ - const FunctionModificationList &mods = modifications(implementingClass()); - for (const FunctionModification &mod : mods) { - if (!mod.isRemoveModifier()) - continue; - - if ((mod.removal & types) == types) - return true; - } - - return false; -} - -bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const -{ - return compareTo(&other) & NameLessThan; -} - - -/*! - Returns a mask of CompareResult describing how this function is - compares to another function -*/ -AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const -{ - CompareResult result; - - // Enclosing class... - if (ownerClass() == other->ownerClass()) - result |= EqualImplementor; - - // Attributes - if (attributes() == other->attributes()) - result |= EqualAttributes; - - // Compare types - AbstractMetaType *t = type(); - AbstractMetaType *ot = other->type(); - if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) - result |= EqualReturnType; - - // Compare names - int cmp = originalName().compare(other->originalName()); - - if (cmp < 0) - result |= NameLessThan; - else if (!cmp) - result |= EqualName; - - // compare name after modification... - cmp = modifiedName().compare(other->modifiedName()); - if (!cmp) - result |= EqualModifiedName; - - // Compare arguments... - AbstractMetaArgumentList minArguments; - AbstractMetaArgumentList maxArguments; - if (arguments().size() < other->arguments().size()) { - minArguments = arguments(); - maxArguments = other->arguments(); - } else { - minArguments = other->arguments(); - maxArguments = arguments(); - } - - int minCount = minArguments.size(); - int maxCount = maxArguments.size(); - bool same = true; - for (int i = 0; i < maxCount; ++i) { - if (i < minCount) { - const AbstractMetaArgument *min_arg = minArguments.at(i); - const AbstractMetaArgument *max_arg = maxArguments.at(i); - if (min_arg->type()->name() != max_arg->type()->name() - && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) { - same = false; - break; - } - } else { - if (maxArguments.at(i)->defaultValueExpression().isEmpty()) { - same = false; - break; - } - } - } - - if (same) - result |= minCount == maxCount ? EqualArguments : EqualDefaultValueOverload; - - return result; -} - -AbstractMetaFunction *AbstractMetaFunction::copy() const -{ - auto *cpy = new AbstractMetaFunction; - cpy->assignMetaAttributes(*this); - cpy->setName(name()); - cpy->setOriginalName(originalName()); - cpy->setOwnerClass(ownerClass()); - cpy->setImplementingClass(implementingClass()); - cpy->setFunctionType(functionType()); - cpy->setDeclaringClass(declaringClass()); - if (type()) - cpy->setType(type()->copy()); - cpy->setConstant(isConstant()); - cpy->setExceptionSpecification(m_exceptionSpecification); - cpy->setAllowThreadModification(m_allowThreadModification); - cpy->setExceptionHandlingModification(m_exceptionHandlingModification); - cpy->m_addedFunction = m_addedFunction; - - for (AbstractMetaArgument *arg : m_arguments) - cpy->addArgument(arg->copy()); - - Q_ASSERT((!type() && !cpy->type()) - || (type()->instantiations() == cpy->type()->instantiations())); - - return cpy; -} - -bool AbstractMetaFunction::usesRValueReferences() const -{ - if (m_functionType == MoveConstructorFunction || m_functionType == MoveAssignmentOperatorFunction) - return true; - if (m_type && m_type->referenceType() == RValueReference) - return true; - for (const AbstractMetaArgument *a : m_arguments) { - if (a->type()->referenceType() == RValueReference) - return true; - } - return false; -} - -QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const -{ - AbstractMetaArgumentList arguments = this->arguments(); - if (arguments.size() == resolvedArguments.size()) { - QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')'); - return QStringList(TypeDatabase::normalizedSignature(signature)); - } - QStringList returned; - - AbstractMetaArgument *argument = arguments.at(resolvedArguments.size()); - QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::")); - for (int i = 0; i < minimalTypeSignature.size(); ++i) { - returned += introspectionCompatibleSignatures(QStringList(resolvedArguments) - << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::"))); - } - - return returned; -} - -QString AbstractMetaFunction::signature() const -{ - if (m_cachedSignature.isEmpty()) { - m_cachedSignature = m_originalName; - - m_cachedSignature += QLatin1Char('('); - - for (int i = 0; i < m_arguments.count(); ++i) { - AbstractMetaArgument *a = m_arguments.at(i); - AbstractMetaType *t = a->type(); - if (t) { - if (i > 0) - m_cachedSignature += QLatin1String(", "); - m_cachedSignature += t->cppSignature(); - // We need to have the argument names in the qdoc files - m_cachedSignature += QLatin1Char(' '); - m_cachedSignature += a->name(); - } else { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("No abstract meta type found for argument '%1' while" - "constructing signature for function '%2'.") - .arg(a->name(), name()); - } - } - m_cachedSignature += QLatin1Char(')'); - - if (isConstant()) - m_cachedSignature += QLatin1String(" const"); - } - return m_cachedSignature; -} - -int AbstractMetaFunction::actualMinimumArgumentCount() const -{ - AbstractMetaArgumentList arguments = this->arguments(); - - int count = 0; - for (int i = 0; i < arguments.size(); ++i && ++count) { - if (argumentRemoved(i + 1)) - --count; - else if (!arguments.at(i)->defaultValueExpression().isEmpty()) - break; - } - - return count; -} - -// Returns reference counts for argument at idx, or all arguments if idx == -2 -QVector<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const -{ - QVector<ReferenceCount> returned; - - const FunctionModificationList &mods = this->modifications(cls); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argumentMod : mod.argument_mods) { - if (argumentMod.index != idx && idx != -2) - continue; - returned += argumentMod.referenceCounts; - } - } - - return returned; -} - - -ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const -{ - const FunctionModificationList &mods = this->modifications(cls); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argumentMod : mod.argument_mods) { - if (argumentMod.index != idx) - continue; - return argumentMod.owner; - } - } - return ArgumentOwner(); -} - -QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index != key) - continue; - - for (const CodeSnip &snip : argumentModification.conversion_rules) { - if (snip.language == language && !snip.code().isEmpty()) - return snip.code(); - } - } - } - - return QString(); -} - -// FIXME If we remove a arg. in the method at the base class, it will not reflect here. -bool AbstractMetaFunction::argumentRemoved(int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key) { - if (argumentModification.removed) - return true; - } - } - } - - return false; -} - -bool AbstractMetaFunction::isDeprecated() const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - if (modification.isDeprecated()) - return true; - } - return false; -} - -// Auto-detect whether a function should be wrapped into -// Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS, that is, temporarily release -// the GIL (global interpreter lock). Doing so is required for any thread-wait -// functions, anything that might call a virtual function (potentially -// reimplemented in Python), and recommended for lengthy I/O or similar. -// It has performance costs, though. -bool AbstractMetaFunction::autoDetectAllowThread() const -{ - // Disallow for simple getter functions. - const bool maybeGetter = m_constant != 0 && m_type != nullptr - && m_arguments.isEmpty(); - return !maybeGetter; -} - -static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass) -{ - return klass->typeEntry()->allowThread(); -} - -static inline bool hasAllowThreadMod(const AbstractMetaClass *klass) -{ - return allowThreadMod(klass) != TypeSystem::AllowThread::Unspecified; -} - -bool AbstractMetaFunction::allowThread() const -{ - auto allowThreadModification = m_allowThreadModification; - // If there is no modification on the function, check for a base class. - if (m_class && allowThreadModification == TypeSystem::AllowThread::Unspecified) { - if (auto base = recurseClassHierarchy(m_class, hasAllowThreadMod)) - allowThreadModification = allowThreadMod(base); - } - - bool result = true; - switch (allowThreadModification) { - case TypeSystem::AllowThread::Disallow: - result = false; - break; - case TypeSystem::AllowThread::Allow: - break; - case TypeSystem::AllowThread::Auto: - result = autoDetectAllowThread(); - break; - case TypeSystem::AllowThread::Unspecified: - result = false; - break; - } - if (!result && ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCInfo(lcShiboken).noquote() << msgDisallowThread(this); - return result; -} - -TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key) - return argumentModification.ownerships.value(language, TypeSystem::InvalidOwnership); - } - } - - return TypeSystem::InvalidOwnership; -} - -bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const -{ - return isRemovedFrom(cls, TypeSystem::All); -} - -bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - if ((modification.removal & language) == language) - return true; - } - - return false; - -} - -QString AbstractMetaFunction::typeReplaced(int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key - && !argumentModification.modified_type.isEmpty()) { - return argumentModification.modified_type; - } - } - } - - return QString(); -} - -bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == argumentIndex && argumentModification.array != 0) - return true; - } - } - return false; -} - -QString AbstractMetaFunction::minimalSignature() const -{ - if (!m_cachedMinimalSignature.isEmpty()) - return m_cachedMinimalSignature; - - QString minimalSignature = originalName() + QLatin1Char('('); - AbstractMetaArgumentList arguments = this->arguments(); - - for (int i = 0; i < arguments.count(); ++i) { - AbstractMetaType *t = arguments.at(i)->type(); - if (t) { - if (i > 0) - minimalSignature += QLatin1Char(','); - minimalSignature += t->minimalSignature(); - } else { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("No abstract meta type found for argument '%1' while constructing" - " minimal signature for function '%2'.") - .arg(arguments.at(i)->name(), name()); - } - } - minimalSignature += QLatin1Char(')'); - if (isConstant()) - minimalSignature += QLatin1String("const"); - - minimalSignature = TypeDatabase::normalizedSignature(minimalSignature); - m_cachedMinimalSignature = minimalSignature; - - return minimalSignature; -} - -QString AbstractMetaFunction::debugSignature() const -{ - QString result; - const bool isOverride = attributes() & AbstractMetaFunction::OverriddenCppMethod; - const bool isFinal = attributes() & AbstractMetaFunction::FinalCppMethod; - if (!isOverride && !isFinal && (attributes() & AbstractMetaFunction::VirtualCppMethod)) - result += QLatin1String("virtual "); - result += minimalSignature(); - if (isOverride) - result += QLatin1String(" override"); - if (isFinal) - result += QLatin1String(" final"); - return result; -} - -FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const -{ - if (!m_addedFunction.isNull()) - return m_addedFunction->modifications; - if (!implementor) - implementor = ownerClass(); - - if (!implementor) - return TypeDatabase::instance()->functionModifications(minimalSignature()); - - FunctionModificationList mods; - while (implementor) { - mods += implementor->typeEntry()->functionModifications(minimalSignature()); - if ((implementor == implementor->baseClass()) || - (implementor == implementingClass() && !mods.isEmpty())) { - break; - } - implementor = implementor->baseClass(); - } - return mods; -} - -QString AbstractMetaFunction::argumentName(int index, - bool /* create */, - const AbstractMetaClass * /* implementor */) const -{ - return m_arguments[--index]->name(); -} - -bool AbstractMetaFunction::isCallOperator() const -{ - return m_name == QLatin1String("operator()"); -} - -bool AbstractMetaFunction::hasInjectedCode() const -{ - const FunctionModificationList &mods = modifications(ownerClass()); - for (const FunctionModification &mod : mods) { - if (mod.isCodeInjection()) - return true; - } - return false; -} - -CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const -{ - CodeSnipList result; - const FunctionModificationList &mods = modifications(ownerClass()); - for (const FunctionModification &mod : mods) { - if (mod.isCodeInjection()) { - for (const CodeSnip &snip : mod.snips) { - if ((snip.language & language) && (snip.position == position || position == TypeSystem::CodeSnipPositionAny)) - result << snip; - } - } - } - return result; -} - -bool AbstractMetaFunction::hasSignatureModifications() const -{ - const FunctionModificationList &mods = modifications(); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) - return true; - for (const ArgumentModification &argmod : mod.argument_mods) { - // since zero represents the return type and we're - // interested only in checking the function arguments, - // it will be ignored. - if (argmod.index > 0) - return true; - } - } - return false; -} - -bool AbstractMetaFunction::isConversionOperator(const QString &funcName) -{ - static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$")); - Q_ASSERT(opRegEx.isValid()); - return opRegEx.match(funcName).hasMatch(); -} - -ExceptionSpecification AbstractMetaFunction::exceptionSpecification() const -{ - return m_exceptionSpecification; -} - -void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e) -{ - m_exceptionSpecification = e; -} - -static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClass *klass) -{ - return klass->typeEntry()->exceptionHandling(); -} - -static inline bool hasExceptionMod(const AbstractMetaClass *klass) -{ - return exceptionMod(klass) != TypeSystem::ExceptionHandling::Unspecified; -} - -bool AbstractMetaFunction::generateExceptionHandling() const -{ - switch (m_functionType) { - case AbstractMetaFunction::CopyConstructorFunction: - case AbstractMetaFunction::MoveConstructorFunction: - case AbstractMetaFunction::AssignmentOperatorFunction: - case AbstractMetaFunction::MoveAssignmentOperatorFunction: - case AbstractMetaFunction::DestructorFunction: - return false; - default: - break; - } - - auto exceptionHandlingModification = m_exceptionHandlingModification; - // If there is no modification on the function, check for a base class. - if (m_class && exceptionHandlingModification == TypeSystem::ExceptionHandling::Unspecified) { - if (auto base = recurseClassHierarchy(m_class, hasExceptionMod)) - exceptionHandlingModification = exceptionMod(base); - } - - bool result = false; - switch (exceptionHandlingModification) { - case TypeSystem::ExceptionHandling::On: - result = true; - break; - case TypeSystem::ExceptionHandling::AutoDefaultToOn: - result = m_exceptionSpecification != ExceptionSpecification::NoExcept; - break; - case TypeSystem::ExceptionHandling::AutoDefaultToOff: - result = m_exceptionSpecification == ExceptionSpecification::Throws; - break; - case TypeSystem::ExceptionHandling::Unspecified: - case TypeSystem::ExceptionHandling::Off: - break; - } - return result; -} - -bool AbstractMetaFunction::isOperatorOverload(const QString &funcName) -{ - if (isConversionOperator(funcName)) - return true; - - static const QRegularExpression opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?" - "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~" - "|\\[\\]|\\s+delete\\[?\\]?" - "|\\(\\)" - "|\\s+new\\[?\\]?)$")); - Q_ASSERT(opRegEx.isValid()); - return opRegEx.match(funcName).hasMatch(); -} - -bool AbstractMetaFunction::isCastOperator() const -{ - return originalName().startsWith(QLatin1String("operator ")); -} - -bool AbstractMetaFunction::isArithmeticOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - - // It's a dereference operator! - if (name == QLatin1String("operator*") && m_arguments.isEmpty()) - return false; - - return name == QLatin1String("operator+") || name == QLatin1String("operator+=") - || name == QLatin1String("operator-") || name == QLatin1String("operator-=") - || name == QLatin1String("operator*") || name == QLatin1String("operator*=") - || name == QLatin1String("operator/") || name == QLatin1String("operator/=") - || name == QLatin1String("operator%") || name == QLatin1String("operator%=") - || name == QLatin1String("operator++") || name == QLatin1String("operator--"); -} - -bool AbstractMetaFunction::isBitwiseOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<<") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator>>") || name == QLatin1String("operator>>=") - || name == QLatin1String("operator&") || name == QLatin1String("operator&=") - || name == QLatin1String("operator|") || name == QLatin1String("operator|=") - || name == QLatin1String("operator^") || name == QLatin1String("operator^=") - || name == QLatin1String("operator~"); -} - -bool AbstractMetaFunction::isComparisonOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<") || name == QLatin1String("operator<=") - || name == QLatin1String("operator>") || name == QLatin1String("operator>=") - || name == QLatin1String("operator==") || name == QLatin1String("operator!="); -} - -bool AbstractMetaFunction::isLogicalOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator!") - || name == QLatin1String("operator&&") - || name == QLatin1String("operator||"); -} - -bool AbstractMetaFunction::isSubscriptOperator() const -{ - if (!isOperatorOverload()) - return false; - - return originalName() == QLatin1String("operator[]"); -} - -bool AbstractMetaFunction::isAssignmentOperator() const -{ - return m_functionType == AssignmentOperatorFunction - || m_functionType == MoveAssignmentOperatorFunction; -} - -bool AbstractMetaFunction::isOtherOperator() const -{ - if (!isOperatorOverload()) - return false; - - return !isArithmeticOperator() - && !isBitwiseOperator() - && !isComparisonOperator() - && !isLogicalOperator() - && !isConversionOperator() - && !isSubscriptOperator() - && !isAssignmentOperator(); -} - -int AbstractMetaFunction::arityOfOperator() const -{ - if (!isOperatorOverload() || isCallOperator()) - return -1; - - int arity = m_arguments.size(); - - // Operator overloads that are class members - // implicitly includes the instance and have - // one parameter less than their arity, - // so we increment it. - if (ownerClass() && arity < 2) - arity++; - - return arity; -} - -bool AbstractMetaFunction::isInplaceOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator+=") || name == QLatin1String("operator&=") - || name == QLatin1String("operator-=") || name == QLatin1String("operator|=") - || name == QLatin1String("operator*=") || name == QLatin1String("operator^=") - || name == QLatin1String("operator/=") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator%=") || name == QLatin1String("operator>>="); -} - -bool AbstractMetaFunction::isVirtual() const -{ - return attributes() & AbstractMetaAttributes::VirtualCppMethod; -} - -QString AbstractMetaFunction::modifiedName() const -{ - if (m_cachedModifiedName.isEmpty()) { - const FunctionModificationList &mods = modifications(implementingClass()); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) { - m_cachedModifiedName = mod.renamedToName; - break; - } - } - if (m_cachedModifiedName.isEmpty()) - m_cachedModifiedName = name(); - } - return m_cachedModifiedName; -} - -bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) -{ - return a->signature() < b->signature(); -} - -AbstractMetaFunction * -AbstractMetaFunction::find(const AbstractMetaFunctionList &haystack, - const QString &needle) -{ - return findByName(haystack, needle); -} - -#ifndef QT_NO_DEBUG_STREAM -static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af) -{ - d << '"' << af->debugSignature() << '"'; -} - -void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const -{ - d << m_functionType << ' ' << m_type << ' ' << m_name; - switch (m_exceptionSpecification) { - case ExceptionSpecification::Unknown: - break; - case ExceptionSpecification::NoExcept: - d << " noexcept"; - break; - case ExceptionSpecification::Throws: - d << " throw(...)"; - break; - } - if (m_exceptionHandlingModification != TypeSystem::ExceptionHandling::Unspecified) - d << " exeption-mod " << int(m_exceptionHandlingModification); - d << '('; - for (int i = 0, count = m_arguments.size(); i < count; ++i) { - if (i) - d << ", "; - d << m_arguments.at(i); - } - d << "), signature=\"" << minimalSignature() << '"'; - if (m_constant) - d << " [const]"; - if (m_reverse) - d << " [reverse]"; - if (isUserAdded()) - d << " [userAdded]"; - if (m_explicit) - d << " [explicit]"; - if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) - d << " [deprecated]"; - if (m_pointerOperator) - d << " [operator->]"; - if (m_isCallOperator) - d << " [operator()]"; - if (m_class) - d << " class: " << m_class->name(); - if (m_implementingClass) - d << " implementing class: " << m_implementingClass->name(); - if (m_declaringClass) - d << " declaring class: " << m_declaringClass->name(); -} - -QDebug operator<<(QDebug d, const AbstractMetaFunction *af) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaFunction("; - if (af) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) { - af->formatDebugVerbose(d); - } else { -#endif - d << "signature="; - formatMetaFunctionBrief(d, af); -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - } -#endif - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaClass - */ - -AbstractMetaClass::AbstractMetaClass() - : m_hasVirtuals(false), - m_isPolymorphic(false), - m_hasNonpublic(false), - m_hasNonPrivateConstructor(false), - m_hasPrivateConstructor(false), - m_functionsFixed(false), - m_hasPrivateDestructor(false), - m_hasProtectedDestructor(false), - m_hasVirtualDestructor(false), - m_hasHashFunction(false), - m_hasEqualsOperator(false), - m_hasCloneOperator(false), - m_isTypeDef(false), - m_hasToStringCapability(false) -{ -} - -AbstractMetaClass::~AbstractMetaClass() -{ - qDeleteAll(m_functions); - qDeleteAll(m_fields); - qDeleteAll(m_enums); - if (hasTemplateBaseClassInstantiations()) - qDeleteAll(templateBaseClassInstantiations()); -} - -/******************************************************************************* - * Returns true if this class is a subclass of the given class - */ -bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const -{ - Q_ASSERT(cls); - - const AbstractMetaClass *clazz = this; - while (clazz) { - if (clazz == cls) - return true; - - clazz = clazz->baseClass(); - } - - return false; -} - -/******************************************************************************* - * Returns a list of all the functions with a given name - */ -AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const -{ - AbstractMetaFunctionList returned; - for (AbstractMetaFunction *function : m_functions) { - if (function->name() == name) - returned.append(function); - } - - return returned; -} - -/******************************************************************************* - * Returns a list of all the functions retrieved during parsing which should - * be added to the API. - */ -AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const -{ - FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; - - // Only public functions in final classes - // default_flags |= isFinal() ? WasPublic : 0; - FunctionQueryOptions public_flags; - if (isFinalInTargetLang()) - public_flags |= WasPublic; - - // Constructors - AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags); - - // Final functions - returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); - - // Virtual functions - returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); - - // Static functions - returned += queryFunctions(StaticFunctions | default_flags | public_flags); - - // Empty, private functions, since they aren't caught by the other ones - returned += queryFunctions(Empty | Invisible); - - return returned; -} - -AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const -{ - if (!hasCloneOperator() && !hasExternalConversionOperators()) - return AbstractMetaFunctionList(); - - AbstractMetaFunctionList returned; - const AbstractMetaFunctionList list = queryFunctions(Constructors) + externalConversionOperators(); - - // Exclude anything that uses rvalue references, be it a move - // constructor "QPolygon(QPolygon &&)" or something else like - // "QPolygon(QVector<QPoint> &&)". - for (AbstractMetaFunction *f : list) { - if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) - && !f->isExplicit() - && f->functionType() != AbstractMetaFunction::CopyConstructorFunction - && !f->usesRValueReferences() - && !f->isModifiedRemoved() - && (f->originalAttributes() & Public)) { - returned += f; - } - } - return returned; -} - -AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptions query) const -{ - const AbstractMetaFunctionList &list = queryFunctions(OperatorOverloads | Visible); - AbstractMetaFunctionList returned; - for (AbstractMetaFunction *f : list) { - if (((query & ArithmeticOp) && f->isArithmeticOperator()) - || ((query & BitwiseOp) && f->isBitwiseOperator()) - || ((query & ComparisonOp) && f->isComparisonOperator()) - || ((query & LogicalOp) && f->isLogicalOperator()) - || ((query & SubscriptionOp) && f->isSubscriptOperator()) - || ((query & AssignmentOp) && f->isAssignmentOperator()) - || ((query & ConversionOp) && f->isConversionOperator()) - || ((query & OtherOp) && f->isOtherOperator())) - returned += f; - } - - return returned; -} - -bool AbstractMetaClass::hasArithmeticOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasBitwiseOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasComparisonOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasLogicalOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate()) - return true; - } - return false; -} - -void AbstractMetaClass::sortFunctions() -{ - std::sort(m_functions.begin(), m_functions.end(), function_sorter); -} - -void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) -{ - m_functions = functions; - - // Functions must be sorted by name before next loop - sortFunctions(); - - for (AbstractMetaFunction *f : qAsConst(m_functions)) { - f->setOwnerClass(this); - if (!f->isPublic()) - m_hasNonpublic = true; - } -} - -bool AbstractMetaClass::hasFieldAccessors() const -{ - for (const AbstractMetaField *field : m_fields) { - if (field->getter() || field->setter()) - return true; - } - - return false; -} - -bool AbstractMetaClass::hasDefaultToStringFunction() const -{ - const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString")); - for (const AbstractMetaFunction *f : funcs) { - if (!f->actualMinimumArgumentCount()) - return true; - } - return false; -} - -void AbstractMetaClass::addFunction(AbstractMetaFunction *function) -{ - Q_ASSERT(!function->signature().startsWith(QLatin1Char('('))); - function->setOwnerClass(this); - - if (!function->isDestructor()) - m_functions << function; - else - Q_ASSERT(false); //memory leak - - m_hasVirtuals |= function->isVirtual(); - m_isPolymorphic |= m_hasVirtuals; - m_hasNonpublic |= !function->isPublic(); -} - -bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const -{ - if (!other->isSignal()) - return false; - - for (const AbstractMetaFunction *f : m_functions) { - if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName) - return other->modifiedName() == f->modifiedName(); - } - - return false; -} - - -QString AbstractMetaClass::name() const -{ - return m_typeEntry->targetLangEntryName(); -} - -void AbstractMetaClass::addBaseClass(AbstractMetaClass *baseClass) -{ - Q_ASSERT(baseClass); - m_baseClasses.append(baseClass); - m_isPolymorphic |= baseClass->isPolymorphic(); -} - -void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) -{ - if (baseClass) { - m_baseClasses.prepend(baseClass); - m_isPolymorphic |= baseClass->isPolymorphic(); - } -} - -QString AbstractMetaClass::package() const -{ - return m_typeEntry->targetLangPackage(); -} - -bool AbstractMetaClass::isNamespace() const -{ - return m_typeEntry->isNamespace(); -} - -static bool qObjectPredicate(const AbstractMetaClass *c) -{ - return c->qualifiedCppName() == QLatin1String("QObject"); -} - -bool AbstractMetaClass::isQObject() const -{ - return qObjectPredicate(this) || recurseClassHierarchy(this, qObjectPredicate) != nullptr; -} - -QString AbstractMetaClass::qualifiedCppName() const -{ - return m_typeEntry->qualifiedCppName(); -} - -bool AbstractMetaClass::hasFunction(const QString &str) const -{ - return findFunction(str); -} - -const AbstractMetaFunction *AbstractMetaClass::findFunction(const QString &functionName) const -{ - return AbstractMetaFunction::find(m_functions, functionName); -} - -bool AbstractMetaClass::hasProtectedFunctions() const -{ - for (AbstractMetaFunction *func : m_functions) { - if (func->isProtected()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasProtectedFields() const -{ - for (const AbstractMetaField *field : m_fields) { - if (field->isProtected()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasProtectedMembers() const -{ - return hasProtectedFields() || hasProtectedFunctions(); -} - -QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const -{ - for (const auto &propertySpec : m_propertySpecs) { - if (name == propertySpec->read()) - return propertySpec; - } - return nullptr; -} - -QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const -{ - for (const auto &propertySpec : m_propertySpecs) { - if (name == propertySpec->write()) - return propertySpec; - } - return nullptr; -} - -QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const -{ - for (const auto &propertySpec : m_propertySpecs) { - if (name == propertySpec->reset()) - return propertySpec; - } - return nullptr; -} - -using AbstractMetaClassBaseTemplateInstantiationsMap = QHash<const AbstractMetaClass *, AbstractMetaTypeList>; -Q_GLOBAL_STATIC(AbstractMetaClassBaseTemplateInstantiationsMap, metaClassBaseTemplateInstantiations); - -bool AbstractMetaClass::hasTemplateBaseClassInstantiations() const -{ - if (!templateBaseClass()) - return false; - return metaClassBaseTemplateInstantiations()->contains(this); -} - -AbstractMetaTypeList AbstractMetaClass::templateBaseClassInstantiations() const -{ - if (!templateBaseClass()) - return AbstractMetaTypeList(); - return metaClassBaseTemplateInstantiations()->value(this); -} - -void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList &instantiations) -{ - if (!templateBaseClass()) - return; - metaClassBaseTemplateInstantiations()->insert(this, instantiations); -} - -// Does any of the base classes require deletion in the main thread? -bool AbstractMetaClass::deleteInMainThread() const -{ - return typeEntry()->deleteInMainThread() - || (!m_baseClasses.isEmpty() && m_baseClasses.constFirst()->deleteInMainThread()); -} - -static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) -{ - for (const AbstractMetaFunction *f : l) { - if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar) - return true; - } - return false; -} - -AbstractMetaField::AbstractMetaField() = default; - -AbstractMetaField::~AbstractMetaField() -{ - delete m_setter; - delete m_getter; -} - -AbstractMetaField *AbstractMetaField::copy() const -{ - auto *returned = new AbstractMetaField; - returned->assignMetaVariable(*this); - returned->assignMetaAttributes(*this); - returned->setEnclosingClass(nullptr); - return returned; -} - -AbstractMetaField *AbstractMetaField::find(const AbstractMetaFieldList &haystack, - const QString &needle) -{ - return findByName(haystack, needle); -} -/******************************************************************************* - * Indicates that this field has a modification that removes it - */ -bool AbstractMetaField::isModifiedRemoved(int types) const -{ - const FieldModificationList &mods = modifications(); - for (const FieldModification &mod : mods) { - if (!mod.isRemoveModifier()) - continue; - - if ((mod.removal & types) == types) - return true; - } - - return false; -} - -static QString upCaseFirst(const QString &str) -{ - Q_ASSERT(!str.isEmpty()); - QString s = str; - s[0] = s.at(0).toUpper(); - return s; -} - -static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, - AbstractMetaAttributes::Attributes type) -{ - auto *f = new AbstractMetaFunction; - - f->setName(name); - f->setOriginalName(name); - f->setOwnerClass(g->enclosingClass()); - f->setImplementingClass(g->enclosingClass()); - f->setDeclaringClass(g->enclosingClass()); - - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::FinalInTargetLang | type; - if (g->isStatic()) - attr |= AbstractMetaAttributes::Static; - if (g->isPublic()) - attr |= AbstractMetaAttributes::Public; - else if (g->isProtected()) - attr |= AbstractMetaAttributes::Protected; - else - attr |= AbstractMetaAttributes::Private; - f->setAttributes(attr); - f->setOriginalAttributes(attr); - - const FieldModificationList &mods = g->modifications(); - for (const FieldModification &mod : mods) { - if (mod.isRenameModifier()) - f->setName(mod.renamedTo()); - if (mod.isAccessModifier()) { - if (mod.isPrivate()) - f->setVisibility(AbstractMetaAttributes::Private); - else if (mod.isProtected()) - f->setVisibility(AbstractMetaAttributes::Protected); - else if (mod.isPublic()) - f->setVisibility(AbstractMetaAttributes::Public); - else if (mod.isFriendly()) - f->setVisibility(AbstractMetaAttributes::Friendly); - } - } - return f; -} - -FieldModificationList AbstractMetaField::modifications() const -{ - const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications(); - FieldModificationList returned; - - for (const FieldModification &mod : mods) { - if (mod.name == name()) - returned += mod; - } - - return returned; -} - -const AbstractMetaFunction *AbstractMetaField::setter() const -{ - if (!m_setter) { - m_setter = createXetter(this, - QLatin1String("set") + upCaseFirst(name()), - AbstractMetaAttributes::SetterFunction); - AbstractMetaArgumentList arguments; - auto *argument = new AbstractMetaArgument; - argument->setType(type()->copy()); - argument->setName(name()); - arguments.append(argument); - m_setter->setArguments(arguments); - } - return m_setter; -} - -const AbstractMetaClass *EnclosingClassMixin::targetLangEnclosingClass() const -{ - auto result = m_enclosingClass; - while (result && !NamespaceTypeEntry::isVisibleScope(result->typeEntry())) - result = result->enclosingClass(); - return result; -} - -const AbstractMetaFunction *AbstractMetaField::getter() const -{ - if (!m_getter) { - m_getter = createXetter(this, - name(), - AbstractMetaAttributes::GetterFunction); - m_getter->setType(type()); - } - - return m_getter; -} - -#ifndef QT_NO_DEBUG_STREAM -static void formatMetaAttributes(QDebug &d, AbstractMetaAttributes::Attributes value) -{ - static const int meIndex = AbstractMetaAttributes::staticMetaObject.indexOfEnumerator("Attribute"); - Q_ASSERT(meIndex >= 0); - const QMetaEnum me = AbstractMetaAttributes::staticMetaObject.enumerator(meIndex); - d << me.valueToKeys(value); -} - -static void formatMetaField(QDebug &d, const AbstractMetaField *af) -{ - formatMetaAttributes(d, af->attributes()); - d << ' ' << af->type()->name() << " \"" << af->name() << '"'; -} - -QDebug operator<<(QDebug d, const AbstractMetaField *af) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaField("; - if (af) - formatMetaField(d, af); - else - d << '0'; - d << ')'; - return d; -} - -static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue *v) -{ - const QString &name = v->stringValue(); - if (!name.isEmpty()) - d << name << '='; - d << v->value(); -} - -QDebug operator<<(QDebug d, const AbstractMetaEnumValue *v) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaEnumValue("; - if (v) - formatMetaEnumValue(d, v); - else - d << '0'; - d << ')'; - return d; -} - -QDebug operator<<(QDebug d, const AbstractMetaEnum *ae) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaEnum("; - if (ae) { - d << ae->fullName(); - if (!ae->isSigned()) - d << " (unsigned) "; - d << '['; - const AbstractMetaEnumValueList &values = ae->values(); - for (int i = 0, count = values.size(); i < count; ++i) { - if (i) - d << ' '; - formatMetaEnumValue(d, values.at(i)); - } - d << ']'; - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -bool AbstractMetaClass::hasConstructors() const -{ - return AbstractMetaClass::queryFirstFunction(m_functions, Constructors) != nullptr; -} - -const AbstractMetaFunction *AbstractMetaClass::copyConstructor() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->functionType() == AbstractMetaFunction::CopyConstructorFunction) - return f; - } - return nullptr; -} - -bool AbstractMetaClass::hasPrivateCopyConstructor() const -{ - const AbstractMetaFunction *copyCt = copyConstructor(); - return copyCt && copyCt->isPrivate(); -} - -void AbstractMetaClass::addDefaultConstructor() -{ - auto *f = new AbstractMetaFunction; - f->setOriginalName(name()); - f->setName(name()); - f->setOwnerClass(this); - f->setFunctionType(AbstractMetaFunction::ConstructorFunction); - f->setArguments(AbstractMetaArgumentList()); - f->setDeclaringClass(this); - - f->setAttributes(Public | FinalInTargetLang | AddedMethod); - f->setImplementingClass(this); - f->setOriginalAttributes(f->attributes()); - - addFunction(f); - this->setHasNonPrivateConstructor(true); -} - -void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) -{ - auto f = new AbstractMetaFunction; - f->setOriginalName(name()); - f->setName(name()); - f->setOwnerClass(this); - f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - f->setDeclaringClass(this); - - auto argType = new AbstractMetaType; - argType->setTypeEntry(typeEntry()); - argType->setReferenceType(LValueReference); - argType->setConstant(true); - argType->setTypeUsagePattern(AbstractMetaType::ValuePattern); - - auto arg = new AbstractMetaArgument; - arg->setType(argType); - arg->setName(name()); - f->addArgument(arg); - - AbstractMetaAttributes::Attributes attr = FinalInTargetLang | AddedMethod; - if (isPrivate) - attr |= AbstractMetaAttributes::Private; - else - attr |= AbstractMetaAttributes::Public; - f->setAttributes(attr); - f->setImplementingClass(this); - f->setOriginalAttributes(f->attributes()); - - addFunction(f); -} - -void AbstractMetaClass::setHasVirtualDestructor(bool value) -{ - m_hasVirtualDestructor = value; - if (value) - m_hasVirtuals = m_isPolymorphic = 1; -} - -bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const -{ - return functions_contains(m_functions, f); -} - -bool AbstractMetaClass::generateExceptionHandling() const -{ - return queryFirstFunction(m_functions, AbstractMetaClass::Visible - | AbstractMetaClass::GenerateExceptionHandling) != nullptr; -} -/* Goes through the list of functions and returns a list of all - functions matching all of the criteria in \a query. - */ - -bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQueryOptions query) -{ - if ((query & NotRemovedFromTargetLang) - && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) { - return false; - } - - if ((query & NotRemovedFromTargetLang) && f->isVirtual() - && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) { - return false; - } - - if ((query & Visible) && f->isPrivate()) - return false; - - if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) - return false; - - if ((query & Invisible) && !f->isPrivate()) - return false; - - if ((query & Empty) && !f->isEmptyFunction()) - return false; - - if ((query & WasPublic) && !f->wasPublic()) - return false; - - if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) - return false; - - if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) - return false; - - if ((query & VirtualInCppFunctions) && !f->isVirtual()) - return false; - - if ((query & Signals) && (!f->isSignal())) - return false; - - if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass())) - return false; - - if (!(query & Constructors) && f->isConstructor()) - return false; - - // Destructors are never included in the functions of a class currently - /* - if ((query & Destructors) && (!f->isDestructor() - || f->ownerClass() != f->implementingClass()) - || f->isDestructor() && (query & Destructors) == 0) { - return false; - }*/ - - if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) - return false; - - if ((query & NonStaticFunctions) && (f->isStatic())) - return false; - - if ((query & NormalFunctions) && (f->isSignal())) - return false; - - if ((query & OperatorOverloads) && !f->isOperatorOverload()) - return false; - - if ((query & GenerateExceptionHandling) && !f->generateExceptionHandling()) - return false; - - if (query.testFlag(GetAttroFunction) - && f->functionType() != AbstractMetaFunction::GetAttroFunction) { - return false; - } - - if (query.testFlag(SetAttroFunction) - && f->functionType() != AbstractMetaFunction::SetAttroFunction) { - return false; - } - - return true; -} - -AbstractMetaFunctionList AbstractMetaClass::queryFunctionList(const AbstractMetaFunctionList &list, - FunctionQueryOptions query) -{ - AbstractMetaFunctionList result; - for (AbstractMetaFunction *f : list) { - if (queryFunction(f, query)) - result.append(f); - } - return result; -} - -const AbstractMetaFunction *AbstractMetaClass::queryFirstFunction(const AbstractMetaFunctionList &list, - FunctionQueryOptions query) -{ - AbstractMetaFunctionList result; - for (AbstractMetaFunction *f : list) { - if (queryFunction(f, query)) - return f; - } - return nullptr; -} - -AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const -{ - return AbstractMetaClass::queryFunctionList(m_functions, query); -} - -bool AbstractMetaClass::hasSignals() const -{ - return queryFirstFunction(m_functions, Signals | Visible | NotRemovedFromTargetLang) != nullptr; -} - -AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const -{ - return queryFunctions(Signals | Visible | NotRemovedFromTargetLang); -} - -AbstractMetaField *AbstractMetaClass::findField(const QString &name) const -{ - return AbstractMetaField::find(m_fields, name); -} - -AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) -{ - if (AbstractMetaEnum *e = findByName(m_enums, enumName)) - return e; - return nullptr; -} - -/*! Recursively searches for the enum value named \a enumValueName in - this class and its superclasses and interfaces. -*/ -AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName) -{ - for (AbstractMetaEnum *e : qAsConst(m_enums)) { - if (AbstractMetaEnumValue *v = e->findEnumValue(enumValueName)) - return v; - } - if (baseClass()) - return baseClass()->findEnumValue(enumValueName); - - return nullptr; -} - - -static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) -{ - if (!type) - return; - - Q_ASSERT(metaClass); - const TypeEntry *entry = (type ? type->typeEntry() : nullptr); - if (entry && entry->isComplex()) { - const auto *centry = static_cast<const ComplexTypeEntry *>(entry); - ComplexTypeEntry *class_entry = metaClass->typeEntry(); - if (class_entry && centry->include().isValid()) - class_entry->addExtraInclude(centry->include()); - } - - if (type->hasInstantiations()) { - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) - addExtraIncludeForType(metaClass, instantiation); - } -} - -static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, const AbstractMetaFunction *meta_function) -{ - Q_ASSERT(metaClass); - Q_ASSERT(meta_function); - addExtraIncludeForType(metaClass, meta_function->type()); - - const AbstractMetaArgumentList &arguments = meta_function->arguments(); - for (AbstractMetaArgument *argument : arguments) - addExtraIncludeForType(metaClass, argument->type()); -} - -void AbstractMetaClass::fixFunctions() -{ - if (m_functionsFixed) - return; - - m_functionsFixed = true; - - AbstractMetaFunctionList funcs = functions(); - - for (auto superClass : m_baseClasses) { - superClass->fixFunctions(); - // Since we always traverse the complete hierarchy we are only - // interrested in what each super class implements, not what - // we may have propagated from their base classes again. - AbstractMetaFunctionList superFuncs; - // Super classes can never be final - if (superClass->isFinalInTargetLang()) { - qCWarning(lcShiboken).noquote().nospace() - << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes"; - *superClass -= AbstractMetaAttributes::FinalInTargetLang; - } - superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); - AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - - QSet<AbstractMetaFunction *> funcsToAdd; - for (auto sf : qAsConst(superFuncs)) { - if (sf->isRemovedFromAllLanguages(sf->implementingClass())) - continue; - - // skip functions added in base classes - if (sf->isUserAdded() && sf->declaringClass() != this) - continue; - - // we generally don't care about private functions, but we have to get the ones that are - // virtual in case they override abstract functions. - bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction()); - for (AbstractMetaFunction *f : funcs) { - if (f->isRemovedFromAllLanguages(f->implementingClass())) - continue; - - - const AbstractMetaFunction::CompareResult cmp = f->compareTo(sf); - - if (cmp & AbstractMetaFunction::EqualModifiedName) { - add = false; - if (cmp & AbstractMetaFunction::EqualArguments) { - // Same function, propegate virtual... - if (!(cmp & AbstractMetaFunction::EqualAttributes)) { - if (!f->isEmptyFunction()) { - if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { - *f -= AbstractMetaAttributes::FinalInTargetLang; - } -#if 0 - if (!f->isFinalInTargetLang() && f->isPrivate()) { - f->setFunctionType(AbstractMetaFunction::EmptyFunction); - f->setVisibility(AbstractMetaAttributes::Protected); - *f += AbstractMetaAttributes::FinalInTargetLang; - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("private virtual function '%1' in '%2'") - .arg(f->signature(), f->implementingClass()->name()); - } -#endif - } - } - - if (f->visibility() != sf->visibility()) { - QString warn = QStringLiteral("visibility of function '%1' modified in class '%2'") - .arg(f->name(), name()); - qCWarning(lcShiboken).noquote().nospace() << warn; -#if 0 - // If new visibility is private, we can't - // do anything. If it isn't, then we - // prefer the parent class's visibility - // setting for the function. - if (!f->isPrivate() && !sf->isPrivate()) - f->setVisibility(sf->visibility()); -#endif - // Private overrides of abstract functions have to go into the class or - // the subclasses will not compile as non-abstract classes. - // But they don't need to be implemented, since they can never be called. - if (f->isPrivate()) { - f->setFunctionType(AbstractMetaFunction::EmptyFunction); - *f += AbstractMetaAttributes::FinalInTargetLang; - } - } - - // Set the class which first declares this function, afawk - f->setDeclaringClass(sf->declaringClass()); - - if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) { - // Shadowed funcion, need to make base class - // function non-virtual - if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) { - - // Check whether the superclass method has been redefined to non-final - - bool hasNonFinalModifier = false; - bool isBaseImplPrivate = false; - const FunctionModificationList &mods = sf->modifications(sf->implementingClass()); - for (const FunctionModification &mod : mods) { - if (mod.isNonFinal()) { - hasNonFinalModifier = true; - break; - } - if (mod.isPrivate()) { - isBaseImplPrivate = true; - break; - } - } - - if (!hasNonFinalModifier && !isBaseImplPrivate) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Shadowing: %1::%2 and %3::%4") - .arg(sf->implementingClass()->name(), sf->signature(), - f->implementingClass()->name(), f->signature()); - } - } - } - - } - - if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { - AbstractMetaArgumentList arguments; - if (f->arguments().size() < sf->arguments().size()) - arguments = sf->arguments(); - else - arguments = f->arguments(); - //TODO: fix this - //for (int i=0; i<arguments.size(); ++i) - // arguments[i]->setDefaultValueExpression("<#>" + QString()); - } - - - // Otherwise we have function shadowing and we can - // skip the thing... - } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) { - // In the case of function shadowing where the function name has been altered to - // avoid conflict, we don't copy in the original. - add = false; - } - } - - if (add) - funcsToAdd << sf; - } - - for (AbstractMetaFunction *f : qAsConst(funcsToAdd)) { - AbstractMetaFunction *copy = f->copy(); - (*copy) += AddedMethod; - funcs.append(copy); - } - } - - bool hasPrivateConstructors = false; - bool hasPublicConstructors = false; - for (AbstractMetaFunction *func : qAsConst(funcs)) { - const FunctionModificationList &mods = func->modifications(this); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) { - func->setName(mod.renamedTo()); - } - } - - // Make sure class is abstract if one of the functions is - if (func->isAbstract()) { - (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::FinalInTargetLang; - } - - if (func->isConstructor()) { - if (func->isPrivate()) - hasPrivateConstructors = true; - else - hasPublicConstructors = true; - } - - - - // Make sure that we include files for all classes that are in use - - if (!func->isRemovedFrom(this, TypeSystem::ShellCode)) - addExtraIncludesForFunction(this, func); - } - - if (hasPrivateConstructors && !hasPublicConstructors) { - (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::FinalInTargetLang; - } - - setFunctions(funcs); -} - -static inline QString formatArraySize(int e) -{ - QString result; - result += QLatin1Char('['); - if (e >= 0) - result += QString::number(e); - result += QLatin1Char(']'); - return result; -} - -QString AbstractMetaType::formatSignature(bool minimal) const -{ - QString result; - if (isConstant()) - result += QLatin1String("const "); - if (isVolatile()) - result += QLatin1String("volatile "); - if (isArray()) { - // Build nested array dimensions a[2][3] in correct order - result += m_arrayElementType->minimalSignature(); - const int arrayPos = result.indexOf(QLatin1Char('[')); - if (arrayPos != -1) - result.insert(arrayPos, formatArraySize(m_arrayElementCount)); - else - result.append(formatArraySize(m_arrayElementCount)); - } else { - result += typeEntry()->qualifiedCppName(); - } - if (!m_instantiations.isEmpty()) { - result += QLatin1Char('<'); - if (minimal) - result += QLatin1Char(' '); - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { - if (i > 0) - result += QLatin1Char(','); - result += m_instantiations.at(i)->minimalSignature(); - } - result += QLatin1String(" >"); - } - - if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) - result += QLatin1Char(' '); - for (Indirection i : m_indirections) - result += TypeInfo::indirectionKeyword(i); - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - result += QLatin1Char('&'); - break; - case RValueReference: - result += QLatin1String("&&"); - break; - } - return result; -} - -QString AbstractMetaType::formatPythonSignature() const -{ - /* - * This is a version of the above, more suitable for Python. - * We avoid extra keywords that are not needed in Python. - * We prepend the package name, unless it is a primitive type. - * - * Primitive types like 'int', 'char' etc.: - * When we have a primitive with an indirection, we use that '*' - * character for later postprocessing, since those indirections - * need to be modified into a result tuple. - */ - QString result; - if (m_pattern == AbstractMetaType::NativePointerAsArrayPattern) - result += QLatin1String("array "); - // We no longer use the "const" qualifier for heuristics. Instead, - // NativePointerAsArrayPattern indicates when we have <array> in XML. - // if (m_typeEntry->isPrimitive() && isConstant()) - // result += QLatin1String("const "); - if (!m_typeEntry->isPrimitive() && !package().isEmpty()) - result += package() + QLatin1Char('.'); - if (isArray()) { - // Build nested array dimensions a[2][3] in correct order - result += m_arrayElementType->formatPythonSignature(); - const int arrayPos = result.indexOf(QLatin1Char('[')); - if (arrayPos != -1) - result.insert(arrayPos, formatArraySize(m_arrayElementCount)); - else - result.append(formatArraySize(m_arrayElementCount)); - } else { - result += typeEntry()->targetLangName(); - } - if (!m_instantiations.isEmpty()) { - result += QLatin1Char('['); - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { - if (i > 0) - result += QLatin1String(", "); - result += m_instantiations.at(i)->formatPythonSignature(); - } - result += QLatin1Char(']'); - } - if (m_typeEntry->isPrimitive()) - for (Indirection i : m_indirections) - result += TypeInfo::indirectionKeyword(i); - // If it is a flags type, we replace it with the full name: - // "PySide2.QtCore.Qt.ItemFlags" instead of "PySide2.QtCore.QFlags<Qt.ItemFlag>" - if (m_typeEntry->isFlags()) - result = fullName(); - result.replace(QLatin1String("::"), QLatin1String(".")); - return result; -} - -bool AbstractMetaType::isCppPrimitive() const -{ - return m_pattern == PrimitivePattern && m_typeEntry->isCppPrimitive(); -} - -/******************************************************************************* - * Other stuff... - */ - - -AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &classes, - const EnumTypeEntry *entry) -{ - Q_ASSERT(entry->isEnum()); - - QString qualifiedName = entry->qualifiedCppName(); - int pos = qualifiedName.lastIndexOf(QLatin1String("::")); - - QString enumName; - QString className; - - if (pos > 0) { - enumName = qualifiedName.mid(pos + 2); - className = qualifiedName.mid(0, pos); - } else { - enumName = qualifiedName; - className = TypeDatabase::globalNamespaceClassName(entry); - } - - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, className); - if (!metaClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("AbstractMeta::findEnum(), unknown class '%1' in '%2'") - .arg(className, entry->qualifiedCppName()); - return nullptr; - } - - return metaClass->findEnum(enumName); -} - -AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, - const QString &name) -{ - const QVector<QStringRef> lst = name.splitRef(QLatin1String("::")); - - if (lst.size() > 1) { - const QStringRef &prefixName = lst.at(0); - const QStringRef &enumName = lst.at(1); - if (AbstractMetaClass *cl = findClass(classes, prefixName.toString())) - return cl->findEnumValue(enumName.toString()); - } - - for (AbstractMetaClass *metaClass : classes) { - if (AbstractMetaEnumValue *enumValue = metaClass->findEnumValue(name)) - return enumValue; - } - - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("no matching enum '%1'").arg(name); - return nullptr; -} - -/*! - * Searches the list after a class that mathces \a name; either as - * C++, Target language base name or complete Target language package.class name. - */ - -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const QString &name) -{ - if (name.isEmpty()) - return nullptr; - - for (AbstractMetaClass *c : classes) { - if (c->qualifiedCppName() == name) - return c; - } - - for (AbstractMetaClass *c : classes) { - if (c->fullName() == name) - return c; - } - - for (AbstractMetaClass *c : classes) { - if (c->name() == name) - return c; - } - - return nullptr; -} - -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const TypeEntry *typeEntry) -{ - for (AbstractMetaClass *c : classes) { - if (c->typeEntry() == typeEntry) - return c; - } - return nullptr; -} - -#ifndef QT_NO_DEBUG_STREAM - -void AbstractMetaClass::format(QDebug &d) const -{ - if (d.verbosity() > 2) - d << static_cast<const void *>(this) << ", "; - d << '"' << qualifiedCppName(); - if (const int count = m_templateArgs.size()) { - for (int i = 0; i < count; ++i) - d << (i ? ',' : '<') << m_templateArgs.at(i)->qualifiedCppName(); - d << '>'; - } - d << '"'; - if (isNamespace()) - d << " [namespace]"; - if (attributes() & AbstractMetaAttributes::FinalCppClass) - d << " [final]"; - if (attributes().testFlag(AbstractMetaAttributes::Deprecated)) - d << " [deprecated]"; - if (!m_baseClasses.isEmpty()) { - d << ", inherits "; - for (auto b : m_baseClasses) - d << " \"" << b->name() << '"'; - } - if (auto templateBase = templateBaseClass()) { - const auto instantiatedTypes = templateBaseClassInstantiations(); - d << ", instantiates \"" << templateBase->name(); - for (int i = 0, count = instantiatedTypes.size(); i < count; ++i) - d << (i ? ',' : '<') << instantiatedTypes.at(i)->name(); - d << ">\""; - } -} - -void AbstractMetaClass::formatMembers(QDebug &d) const -{ - if (!m_enums.isEmpty()) - d << ", enums[" << m_enums.size() << "]=" << m_enums; - if (!m_functions.isEmpty()) { - const int count = m_functions.size(); - d << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaFunctionBrief(d, m_functions.at(i)); - } - d << ')'; - } - if (const int count = m_fields.size()) { - d << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaField(d, m_fields.at(i)); - } - d << ')'; - } -} - -QDebug operator<<(QDebug d, const AbstractMetaClass *ac) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaClass("; - if (ac) { - ac->format(d); - if (d.verbosity() > 2) - ac->formatMembers(d); - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* -* AbstractMetaEnum -*/ - -AbstractMetaEnum::AbstractMetaEnum() : - m_hasQenumsDeclaration(false), m_signed(true) -{ -} - -AbstractMetaEnum::~AbstractMetaEnum() -{ - qDeleteAll(m_enumValues); -} - -template <class String> -AbstractMetaEnumValue *findMatchingEnumValue(const AbstractMetaEnumValueList &list, const String &value) -{ - for (AbstractMetaEnumValue *enumValue : list) { - if (enumValue->name() == value) - return enumValue; - } - return nullptr; -} - -// Find enum values for "enum Enum { e1 }" either for "e1" or "Enum::e1" -AbstractMetaEnumValue *AbstractMetaEnum::findEnumValue(const QString &value) const -{ - if (isAnonymous()) - return findMatchingEnumValue(m_enumValues, value); - const int sepPos = value.indexOf(QLatin1String("::")); - if (sepPos == -1) - return findMatchingEnumValue(m_enumValues, value); - return name() == value.leftRef(sepPos) - ? findMatchingEnumValue(m_enumValues, value.rightRef(value.size() - sepPos - 2)) - : nullptr; -} - -QString AbstractMetaEnum::name() const -{ - return m_typeEntry->targetLangEntryName(); -} - -QString AbstractMetaEnum::qualifier() const -{ - return m_typeEntry->targetLangQualifier(); -} - -QString AbstractMetaEnum::package() const -{ - return m_typeEntry->targetLangPackage(); -} |