// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef ABSTRACTMETAFUNCTION_H #define ABSTRACTMETAFUNCTION_H #include "abstractmetalang_enums.h" #include "abstractmetalang_typedefs.h" #include "typesystem_enums.h" #include "modifications_typedefs.h" #include "typesystem_typedefs.h" #include "parser/codemodel_enums.h" #include #include #include QT_FORWARD_DECLARE_CLASS(QDebug) QT_FORWARD_DECLARE_CLASS(QRegularExpression) class AbstractMetaFunctionPrivate; class AbstractMetaType; class FunctionTypeEntry; class Documentation; class SourceLocation; struct ArgumentOwner; struct ReferenceCount; class AbstractMetaFunction { Q_GADGET public: Q_DISABLE_COPY_MOVE(AbstractMetaFunction) enum FunctionType { ConstructorFunction, CopyConstructorFunction, MoveConstructorFunction, AssignmentOperatorFunction, MoveAssignmentOperatorFunction, DestructorFunction, NormalFunction, SignalFunction, EmptyFunction, SlotFunction, GetAttroFunction, SetAttroFunction, CallOperator, FirstOperator = CallOperator, ConversionOperator, DereferenceOperator, // Iterator's operator * ReferenceOperator, // operator & ArrowOperator, ArithmeticOperator, IncrementOperator, DecrementOperator, BitwiseOperator, LogicalOperator, ShiftOperator, SubscriptOperator, ComparisonOperator, LastOperator = ComparisonOperator }; Q_ENUM(FunctionType) enum ComparisonOperatorType { OperatorEqual, OperatorNotEqual, OperatorLess, OperatorLessEqual, OperatorGreater, OperatorGreaterEqual }; Q_ENUM(ComparisonOperatorType) enum CompareResultFlag { EqualName = 0x00000001, EqualArguments = 0x00000002, EqualAttributes = 0x00000004, EqualImplementor = 0x00000008, EqualReturnType = 0x00000010, EqualDefaultValueOverload = 0x00000020, EqualModifiedName = 0x00000040, NameLessThan = 0x00001000, PrettySimilar = EqualName | EqualArguments, Equal = 0x0000001f, NotEqual = 0x00001000 }; Q_DECLARE_FLAGS(CompareResult, CompareResultFlag) Q_FLAG(CompareResultFlag) enum Attribute { None = 0x00000000, ClassMethod = 0x00000008, GetterFunction = 0x00000020, SetterFunction = 0x00000040, PropertyReader = 0x00000100, PropertyWriter = 0x00000200, PropertyResetter = 0x00000400, PropertyNotify = 0x00000800, // Add by meta builder (implicit constructors, inherited methods, etc) AddedMethod = 0x001000000, }; Q_DECLARE_FLAGS(Attributes, Attribute) Q_FLAG(Attribute) Attributes attributes() const; void setAttributes(Attributes attributes); void operator+=(Attribute attribute); void operator-=(Attribute attribute); FunctionAttributes cppAttributes() const; void setCppAttributes(FunctionAttributes a); void setCppAttribute(FunctionAttribute a, bool on = true); enum class Flag { // Internal flags not relevant for comparing functions // Binary operator whose leading/trailing argument was removed by metabuilder OperatorLeadingClassArgumentRemoved = 0x1, OperatorTrailingClassArgumentRemoved = 0x2, OperatorClassArgumentByValue = 0x4, // The removed class argument was passed by value InheritedFromTemplate = 0x8, // Inherited from a template in metabuilder HiddenFriend = 0x10, PrivateSignal = 0x20 // Private Qt signal (cannot emit from client code) }; Q_DECLARE_FLAGS(Flags, Flag) Flags flags() const; void setFlags(Flags f); bool isAbstract() const; bool isClassMethod() const; bool isStatic() const; bool isPropertyReader() const; bool isPropertyWriter() const; bool isPropertyResetter() const; AbstractMetaFunction(); explicit AbstractMetaFunction(const QString &name); explicit AbstractMetaFunction(const AddedFunctionPtr &addedFunc); ~AbstractMetaFunction(); QString name() const; void setName(const QString &name); // Names under which the function will be registered to Python. QStringList definitionNames() const; QString originalName() const; void setOriginalName(const QString &name); Access access() const; void setAccess(Access a); void modifyAccess(Access a); bool isPrivate() const { return access() == Access::Private; } bool isProtected() const { return access() == Access::Protected; } bool isPublic() const { return access() == Access::Public; } bool wasPrivate() const; bool wasProtected() const; bool wasPublic() const; const Documentation &documentation() const; void setDocumentation(const Documentation& doc); bool isReverseOperator() const; void setReverseOperator(bool reverse); /// Returns true if this is a binary operator and the "self" operand is a /// pointer, e.g. class Foo {}; operator+(SomeEnum, Foo*); /// (not to be mixed up with DereferenceOperator). bool isPointerOperator() const; void setPointerOperator(bool value); /** * Says if the function (a constructor) was declared as explicit in C++. * \return true if the function was declared as explicit in C++ */ bool isExplicit() const; void setExplicit(bool isExplicit); bool returnsBool() const; bool isOperatorBool() const; static bool isConversionOperator(const QString& funcName); ExceptionSpecification exceptionSpecification() const; void setExceptionSpecification(ExceptionSpecification e); bool generateExceptionHandling() const; bool isConversionOperator() const; static bool isOperatorOverload(const QString& funcName); bool isOperatorOverload() const; bool isArithmeticOperator() const; bool isBitwiseOperator() const; // Includes shift operator bool isComparisonOperator() const; /// Returns whether this is a comparison accepting owner class /// (bool operator==(QByteArray,QByteArray) but not bool operator==(QByteArray,const char *) bool isSymmetricalComparisonOperator() const; bool isIncDecrementOperator() const; bool isLogicalOperator() const; bool isAssignmentOperator() const; // Assignment or move assignment bool isGetter() const; /// Returns whether it is a Qt-style isNull() method suitable for nb_bool bool isQtIsNullMethod() const; /** * Informs the arity of the operator or -1 if the function is not * an operator overload. * /return the arity of the operator or -1 */ int arityOfOperator() const; bool isUnaryOperator() const { return arityOfOperator() == 1; } bool isBinaryOperator() const { return arityOfOperator() == 2; } bool isInplaceOperator() const; bool isVirtual() const; bool allowThread() const; QString modifiedName() const; QString minimalSignature() const; /// List of signatures matched for modifications QStringList modificationSignatures() const; // Signature with replaced argument types and return type for overload // decisor comment. QString signatureComment() const; QString debugSignature() const; // including virtual/override/final, etc., for debugging only. bool isModifiedRemoved(AbstractMetaClassCPtr cls = {}) const; bool isModifiedFinal(AbstractMetaClassCPtr cls = {}) const; bool isVoid() const; const AbstractMetaType &type() const; void setType(const AbstractMetaType &type); // The class that has this function as a member. AbstractMetaClassCPtr ownerClass() const; void setOwnerClass(const AbstractMetaClassCPtr &cls); // Owner excluding invisible namespaces AbstractMetaClassCPtr targetLangOwner() const; // The first class in a hierarchy that declares the function AbstractMetaClassCPtr declaringClass() const; void setDeclaringClass(const AbstractMetaClassCPtr &cls); // The class that actually implements this function AbstractMetaClassCPtr implementingClass() const; void setImplementingClass(const AbstractMetaClassCPtr &cls); const AbstractMetaArgumentList &arguments() const; AbstractMetaArgumentList &arguments(); void setArguments(const AbstractMetaArgumentList &arguments); void addArgument(const AbstractMetaArgument &argument); int actualMinimumArgumentCount() const; // Return the argument index accounting for the isModifiedRemoved arguments [0..n-1] int actualArgumentIndex(int index) const; bool isDeprecated() const; bool isDestructor() const { return functionType() == DestructorFunction; } bool isConstructor() const; bool isCopyConstructor() const { return functionType() == CopyConstructorFunction; } bool isDefaultConstructor() const; bool needsReturnType() const; bool isInGlobalScope() const; bool isSignal() const { return functionType() == SignalFunction; } bool isSlot() const { return functionType() == SlotFunction; } bool isEmptyFunction() const { return functionType() == EmptyFunction; } bool maybeAccessor() const; FunctionType functionType() const; void setFunctionType(FunctionType type); std::optional comparisonOperatorType() const; bool usesRValueReferences() const; bool generateBinding() const; // Returns whether the function is contained in the positive list of the // type entry if one is specified. bool isWhiteListed() const; QString signature() const; /// Return a signature qualified by class name, for error reporting. QString classQualifiedSignature() const; /// Signature with unresolved typedefs as seen by the code parser QString unresolvedSignature() const; void setUnresolvedSignature(const QString &); bool isConstant() const; void setConstant(bool constant); /// Returns true if the AbstractMetaFunction was added by the user via the type system description. bool isUserAdded() const; bool isUserAddedPythonOverride() const; /// Returns true if the AbstractMetaFunction was declared by the user via /// the type system description. bool isUserDeclared() const; CompareResult compareTo(const AbstractMetaFunction *other) const; bool isConstOverloadOf(const AbstractMetaFunction *other) const; bool operator <(const AbstractMetaFunction &a) const; AbstractMetaFunction *copy() const; QString conversionRule(TypeSystem::Language language, int idx) const; bool hasConversionRule(TypeSystem::Language language, int idx) const; QList referenceCounts(const AbstractMetaClassCPtr &cls, int idx = -2) const; ArgumentOwner argumentOwner(const AbstractMetaClassCPtr &cls, int idx) const; // Returns the ownership rules for the given argument (target lang). TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClassCPtr &cls, int idx) const; const QString &modifiedTypeName() const; bool isTypeModified() const { return !modifiedTypeName().isEmpty(); } bool generateOpaqueContainerReturn() const; bool isModifiedToArray(int argumentIndex) const; void applyTypeModifications(); /// Return the (modified) type for the signature; modified-pyi-type, modified-type QString pyiTypeReplaced(int argumentIndex) const; bool argumentRemoved(int) const; /** * Verifies if any modification to the function is an inject code. * \return true if there is inject code modifications to the function. */ bool hasInjectedCode() const; /** * Returns a list of code snips for this function. * The code snips can be filtered by position and language. * \return list of code snips */ CodeSnipList injectedCodeSnips(TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, TypeSystem::Language language = TypeSystem::All) const; bool injectedCodeContains(const QRegularExpression &pattern, TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, TypeSystem::Language language = TypeSystem::All) const; bool injectedCodeContains(QStringView pattern, TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, TypeSystem::Language language = TypeSystem::All) const; /** * Verifies if any modification to the function alters/removes its * arguments types or default values. * \return true if there is some modification to function signature */ bool hasSignatureModifications() const; const FunctionModificationList &modifications(AbstractMetaClassCPtr implementor = {}) const; void clearModificationsCache(); const DocModificationList addedFunctionDocModifications() const; static FunctionModificationList findClassModifications(const AbstractMetaFunction *f, AbstractMetaClassCPtr implementor); static FunctionModificationList findGlobalModifications(const AbstractMetaFunction *f); /** * Return the argument name if there is a modification the renamed value will be returned */ QString argumentName(int index, bool create = true, AbstractMetaClassCPtr cl = {}) const; int propertySpecIndex() const; void setPropertySpecIndex(int i); FunctionTypeEntryPtr typeEntry() const; void setTypeEntry(const FunctionTypeEntryPtr &typeEntry); QString targetLangPackage() const; bool isCallOperator() const; static AbstractMetaFunctionCPtr find(const AbstractMetaFunctionCList &haystack, QAnyStringView needle); bool matches(OperatorQueryOptions) const; // for the meta builder only void setAllowThreadModification(TypeSystem::AllowThread am); void setExceptionHandlingModification(TypeSystem::ExceptionHandling em); int overloadNumber() const; TypeSystem::SnakeCase snakeCase() const; // Query functions for generators /// Verifies if any of the function's code injections of the "native" /// type needs the type system variable "%PYSELF". /// \return true if the function's native code snippets use "%PYSELF" bool injectedCodeUsesPySelf() const; /// Verifies if any of the function's code injections of the "native" class makes a /// call to the C++ method. This is used by the generator to avoid writing calls to /// Python overrides of C++ virtual methods when the user custom code already does this. /// \param func the function to check /// \return true if the function's code snippets call the Python override for a C++ virtual method bool injectedCodeCallsPythonOverride() const; /// Verifies if any of the function's code injections attributes values to /// the return variable (%0 or %PYARG_0). /// \param language the kind of code snip /// \return true if the function's code attributes values to "%0" or "%PYARG_0" bool injectedCodeHasReturnValueAttribution(TypeSystem::Language language = TypeSystem::TargetLangCode) const; /// Verifies if any of the function's code injections uses the type system variable /// for function arguments of a given index. bool injectedCodeUsesArgument(int argumentIndex) const; bool isVisibilityModifiedToPrivate() const; #ifndef QT_NO_DEBUG_STREAM void formatDebugBrief(QDebug &debug) const; void formatDebugVerbose(QDebug &debug) const; #endif SourceLocation sourceLocation() const; void setSourceLocation(const SourceLocation &sourceLocation); static const char *pythonRichCompareOpCode(ComparisonOperatorType ct); static const char *cppComparisonOperator(ComparisonOperatorType ct); private: template bool traverseCodeSnips(Predicate predicate, TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, TypeSystem::Language language = TypeSystem::All) const; bool autoDetectAllowThread() const; QScopedPointer d; }; inline bool AbstractMetaFunction::isAbstract() const { return cppAttributes().testFlag(FunctionAttribute::Abstract); } inline bool AbstractMetaFunction::isStatic() const { return cppAttributes().testFlag(FunctionAttribute::Static); } inline bool AbstractMetaFunction::isClassMethod() const { return attributes().testFlag(ClassMethod); } inline bool AbstractMetaFunction::isPropertyReader() const { return attributes().testFlag(PropertyReader); } inline bool AbstractMetaFunction::isPropertyWriter() const { return attributes().testFlag(PropertyWriter); } inline bool AbstractMetaFunction::isPropertyResetter() const { return attributes().testFlag(PropertyResetter); } Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::CompareResult) Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::Attributes); Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::Flags); #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const AbstractMetaFunction *af); #endif #endif // ABSTRACTMETAFUNCTION_H