diff options
Diffstat (limited to 'sources/shiboken6/generator/shiboken/shibokengenerator.h')
-rw-r--r-- | sources/shiboken6/generator/shiboken/shibokengenerator.h | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h new file mode 100644 index 000000000..22ee73fa2 --- /dev/null +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h @@ -0,0 +1,491 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef SHIBOKENGENERATOR_H +#define SHIBOKENGENERATOR_H + +#include <generator.h> + +#include "customconversion_typedefs.h" +#include "abstractmetalang_enums.h" +#include "typesystem_typedefs.h" +#include "typesystem_enums.h" + +#include <QtCore/QRegularExpression> + +#include <array> +#include <optional> + +class EnumTypeEntry; +class FlagsTypeEntry; +class DocParser; +class CodeSnip; +class QPropertySpec; +class OverloadData; +class TargetToNativeConversion; +struct GeneratorClassInfoCacheEntry; +struct IncludeGroup; +struct ShibokenGeneratorOptions; + +class TextStream; + +// Function to be used for implementing nb_bool +struct BoolCastFunction +{ + AbstractMetaFunctionCPtr function; + bool invert = false; // Function is "isNull()", (invert result). +}; + +using BoolCastFunctionOptional = std::optional<BoolCastFunction>; + +/** + * Abstract generator that contains common methods used in CppGenerator and HeaderGenerator. + */ +class ShibokenGenerator : public Generator +{ +public: + Q_DISABLE_COPY_MOVE(ShibokenGenerator) + + /// Besides the actual bindings (see AbstractMetaFunction::generateBinding(), + /// some functions need to be generated into the wrapper class + /// (virtual method/avoid protected hack expose). + enum class FunctionGenerationFlag + { + None = 0x0, + /// Virtual method overridable in Python + VirtualMethod = 0x1, + /// Special QObject virtuals + QMetaObjectMethod = 0x2, + /// Needs a protected wrapper for avoidProtectedHack() + /// public "foo_protected()" calling "foo()" + ProtectedWrapper = 0x4, // + /// Pass through constructor + WrapperConstructor = 0x8, + /// Generate a special copy constructor + /// "FooBar_Wrapper(const Foo&)" for constructing a wrapper from a value + WrapperSpecialCopyConstructor = 0x10 + }; + Q_DECLARE_FLAGS(FunctionGeneration, FunctionGenerationFlag); + + enum class AttroCheckFlag + { + None = 0x0, + GetattroOverloads = 0x01, + GetattroSmartPointer = 0x02, + GetattroUser = 0x04, // Injected code + GetattroMask = 0x0F, + SetattroQObject = 0x10, + SetattroSmartPointer = 0x20, + SetattroMethodOverride = 0x40, + SetattroUser = 0x80, // Injected code + SetattroMask = 0xF0, + }; + Q_DECLARE_FLAGS(AttroCheck, AttroCheckFlag); + + using FunctionGroups = QMap<QString, AbstractMetaFunctionCList>; // Sorted + + ShibokenGenerator(); + ~ShibokenGenerator() override; + + const char *name() const override { return "Shiboken"; } + + static QList<OptionDescription> options(); + static std::shared_ptr<OptionsParser> createOptionsParser(); + + static QString minimalConstructorExpression(const ApiExtractorResult &api, + const AbstractMetaType &type); + static QString minimalConstructorExpression(const ApiExtractorResult &api, + const TypeEntryCPtr &type); + +protected: + bool doSetup() override; + + GeneratorContext contextForClass(const AbstractMetaClassCPtr &c) const override; + + /** + * Returns a map with all functions grouped, the function name is used as key. + * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} + * \param scope Where to search for functions, null means all global functions. + */ + FunctionGroups getGlobalFunctionGroups() const; + static FunctionGroups getFunctionGroups(const AbstractMetaClassCPtr &scope); + + static QList<AbstractMetaFunctionCList> + numberProtocolOperators(const AbstractMetaClassCPtr &scope); + + static BoolCastFunctionOptional boolCast(const AbstractMetaClassCPtr &scope); + + /** + * Returns all different inherited overloads of func, and includes func as well. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + static AbstractMetaFunctionCList getFunctionAndInheritedOverloads(const AbstractMetaFunctionCPtr &func, + QSet<QString> *seen); + + /// Write user's custom code snippets at class or module level. + void writeClassCodeSnips(TextStream &s, + const QList<CodeSnip> &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const GeneratorContext &context) const; + void writeCodeSnips(TextStream &s, + const QList<CodeSnip> &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language) const; + /// Write user's custom code snippets at function level. + void writeCodeSnips(TextStream &s, + const QList<CodeSnip> &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const AbstractMetaFunctionCPtr &func, + bool usePyArgs, + const AbstractMetaArgument *lastArg) const; + + /// Replaces variables for the user's custom code at global or class level. + void processCodeSnip(QString &code) const; + void processCodeSnip(QString &code, const QString &context) const; + void processClassCodeSnip(QString &code, const GeneratorContext &context) const; + + /** + * Verifies if any of the function's code injections makes a call + * to the C++ method. This is used by the generator to avoid writing calls + * to C++ when the user custom code already does this. + * \param func the function to check + * \return true if the function's code snippets call the wrapped C++ function + */ + static bool injectedCodeCallsCppFunction(const GeneratorContext &context, + const AbstractMetaFunctionCPtr &func); + + /** + * Function which parse the metafunction information + * \param func the function witch will be parserd + * \param option some extra options + * \param arg_count the number of function arguments + */ + QString functionSignature(const AbstractMetaFunctionCPtr &func, + const QString &prepend = QString(), + const QString &append = QString(), + Options options = NoOption, + int arg_count = -1) const; + + /// Returns the top-most class that has multiple inheritance in the ancestry. + static AbstractMetaClassCPtr + getMultipleInheritingClass(const AbstractMetaClassCPtr &metaClass); + + static bool useOverrideCaching(const AbstractMetaClassCPtr &metaClass); + static AttroCheck checkAttroFunctionNeeds(const AbstractMetaClassCPtr &metaClass); + + /// Returns a list of methods of the given class where each one is part of + /// a different overload with both static and non-static method. + static AbstractMetaFunctionCList + getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClassCPtr &metaClass); + + static void writeToPythonConversion(TextStream &s, + const AbstractMetaType &type, + const AbstractMetaClassCPtr &context, + const QString &argumentName); + static void writeToCppConversion(TextStream &s, + const AbstractMetaType &type, + const QString &inArgName, + const QString &outArgName); + static void writeToCppConversion(TextStream &s, + const AbstractMetaClassCPtr &metaClass, + const QString &inArgName, + const QString &outArgName); + + /// Returns true if the argument is a pointer that rejects nullptr values. + static bool shouldRejectNullPointerArgument(const AbstractMetaFunctionCPtr &func, + int argIndex); + + /// Verifies if the class should have a C++ wrapper generated for it, + /// instead of only a Python wrapper. + static bool shouldGenerateCppWrapper(const AbstractMetaClassCPtr &metaClass); + + static bool shouldGenerateMetaObjectFunctions(const AbstractMetaClassCPtr &metaClass); + + /// Returns which functions need to be generated into the wrapper class + static FunctionGeneration functionGeneration(const AbstractMetaFunctionCPtr &func); + + // Return a list of implicit conversions if generation is enabled. + AbstractMetaFunctionCList implicitConversions(const TypeEntryCPtr &t) const; + + static QString wrapperName(const AbstractMetaClassCPtr &metaClass); + + static QString fullPythonClassName(const AbstractMetaClassCPtr &metaClass); + + static QString headerFileNameForContext(const GeneratorContext &context); + IncludeGroup baseWrapperIncludes(const GeneratorContext &classContext) const; + + static QString fullPythonFunctionName(const AbstractMetaFunctionCPtr &func, bool forceFunc); + + static bool wrapperDiagnostics(); + + static QString protectedEnumSurrogateName(const AbstractMetaEnum &metaEnum); + + static QString pythonPrimitiveTypeName(const QString &cppTypeName); + + static QString pythonOperatorFunctionName(const AbstractMetaFunctionCPtr &func); + static QList<AbstractMetaFunctionCList> + filterGroupedOperatorFunctions(const AbstractMetaClassCPtr &metaClass, + OperatorQueryOptions query); + + static QString fixedCppTypeName(const TargetToNativeConversion &toNative); + static QString fixedCppTypeName(const AbstractMetaType &type); + static QString fixedCppTypeName(const TypeEntryCPtr &type, QString typeName = {}); + + static bool isNumber(const QString &cpythonApiName); + static bool isNumber(const TypeEntryCPtr &type); + static bool isNumber(const AbstractMetaType &type); + static bool isPyInt(const TypeEntryCPtr &type); + static bool isPyInt(const AbstractMetaType &type); + + static bool isNullPtr(const QString &value); + + static QString converterObject(const AbstractMetaType &type) ; + static QString converterObject(const TypeEntryCPtr &type); + + static QString cpythonBaseName(const AbstractMetaClassCPtr &metaClass); + static QString cpythonBaseName(const TypeEntryCPtr &type); + static QString containerCpythonBaseName(const ContainerTypeEntryCPtr &ctype); + static QString cpythonBaseName(const AbstractMetaType &type); + static QString cpythonTypeName(const AbstractMetaClassCPtr &metaClass); + static QString cpythonTypeName(const TypeEntryCPtr &type); + static QString cpythonTypeNameExtSet(const TypeEntryCPtr &type); + static QString cpythonTypeNameExtSet(const AbstractMetaType &type); + static QString cpythonTypeNameExt(const TypeEntryCPtr &type); + static QString cpythonTypeNameExt(const AbstractMetaType &type); + static QString cpythonCheckFunction(TypeEntryCPtr type); + static QString cpythonCheckFunction(AbstractMetaType metaType); + static QString cpythonIsConvertibleFunction(const TypeEntryCPtr &type); + static QString cpythonIsConvertibleFunction(const AbstractMetaType &metaType); + static QString cpythonIsConvertibleFunction(const AbstractMetaArgument &metaArg); + + static QString cpythonToCppConversionFunction(const AbstractMetaClassCPtr &metaClass) ; + static QString cpythonToCppConversionFunction(const AbstractMetaType &type); + static QString cpythonToPythonConversionFunction(const AbstractMetaType &type); + static QString cpythonToPythonConversionFunction(const AbstractMetaClassCPtr &metaClass); + static QString cpythonToPythonConversionFunction(const TypeEntryCPtr &type); + + static QString cpythonFunctionName(const AbstractMetaFunctionCPtr &func) ; + static QString cpythonMethodDefinitionName(const AbstractMetaFunctionCPtr &func); + static QString cpythonGettersSettersDefinitionName(const AbstractMetaClassCPtr &metaClass); + static QString cpythonGetattroFunctionName(const AbstractMetaClassCPtr &metaClass); + static QString cpythonSetattroFunctionName(const AbstractMetaClassCPtr &metaClass); + static QString cpythonGetterFunctionName(const AbstractMetaField &metaField); + static QString cpythonSetterFunctionName(const AbstractMetaField &metaField); + static QString cpythonGetterFunctionName(const QPropertySpec &property, + const AbstractMetaClassCPtr &metaClass); + static QString cpythonSetterFunctionName(const QPropertySpec &property, + const AbstractMetaClassCPtr &metaClass); + static QString cpythonWrapperCPtr(const AbstractMetaClassCPtr &metaClass, + const QString &argName = QLatin1StringView("self")); + static QString cpythonWrapperCPtr(const AbstractMetaType &metaType, + const QString &argName); + static QString cpythonWrapperCPtr(const TypeEntryCPtr &type, const QString &argName); + + static QString cpythonEnumName(const EnumTypeEntryCPtr &enumEntry); + static QString cpythonEnumName(const AbstractMetaEnum &metaEnum); + + static QString cpythonFlagsName(const FlagsTypeEntryCPtr &flagsEntry); + static QString cpythonFlagsName(const AbstractMetaEnum *metaEnum); + /// Returns the special cast function name, the function used to proper cast + /// class with multiple inheritance. + static QString cpythonSpecialCastFunctionName(const AbstractMetaClassCPtr &metaClass); + + /// Returns the file name for the module global header. If no module name + /// is provided the current will be used. + static QString getModuleHeaderFileName(const QString &moduleName = QString()); + static QString getPrivateModuleHeaderFileName(const QString &moduleName = QString()); + + /// Includes for header (native wrapper class) or binding source + QList<IncludeGroup> classIncludes(const AbstractMetaClassCPtr &metaClass) const; + + /// Returns true if the user enabled the so called "parent constructor heuristic". + static bool useCtorHeuristic(); + /// Returns true if the user enabled the so called "return value heuristic". + static bool useReturnValueHeuristic(); + /// Returns true if the generator should use the result of isNull()const to compute boolean casts. + static bool useIsNullAsNbBool(); + /// Whether to generate lean module headers + static bool leanHeaders(); + /// Returns true if the generator should use operator bool to compute boolean casts. + static bool useOperatorBoolAsNbBool(); + /// Generate implicit conversions of function arguments + static bool generateImplicitConversions(); + static QString cppApiVariableNameOld(const QString &moduleName = {}); + static QString cppApiVariableName(const QString &moduleName = QString()); + static QString pythonModuleObjectName(const QString &moduleName = QString()); + static QString convertersVariableName(const QString &moduleName = QString()); + /// Returns the type index variable name for a given class. + static QString getTypeIndexVariableName(const AbstractMetaClassCPtr &metaClass); + /// Returns the type index variable name for a given typedef for a template + /// class instantiation made of the template class and the instantiation values + static QString getTypeAlternateTemplateIndexVariableName(const AbstractMetaClassCPtr &metaClass); + static QString getTypeIndexVariableName(TypeEntryCPtr type); + static QString getTypeIndexVariableName(const AbstractMetaType &type) ; + + /// Collect all type names as an array for initializing the type/name struct. + void collectFullTypeNamesArray(QStringList &typeNames); + + /// Returns true if the user don't want verbose error messages on the generated bindings. + static bool verboseErrorMessagesDisabled(); + + void collectContainerTypesFromConverterMacros(const QString &code, bool toPythonMacro); + + static void writeFunctionCall(TextStream &s, + const AbstractMetaFunctionCPtr &metaFunc, + Options options = NoOption); + + // All data about extended converters: the type entries of the target type, and a + // list of AbstractMetaClasses accepted as argument for the conversion. + using ExtendedConverterData = QHash<TypeEntryCPtr, AbstractMetaClassCList>; + /// Returns all extended conversions for the current module. + ExtendedConverterData getExtendedConverters() const; + + /// Returns a list of converters for the non wrapper types of the current module. + static QList<CustomConversionPtr> getPrimitiveCustomConversions(); + + /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. + bool pythonFunctionWrapperUsesListOfArguments(const AbstractMetaFunctionCPtr &func) const; + + static const QRegularExpression &convertToCppRegEx() + { return typeSystemConvRegExps()[TypeSystemToCppFunction]; } + + static QString pythonArgsAt(int i); + + /// Return the format character for C++->Python->C++ conversion (Py_BuildValue) + static const QHash<QString, QChar> &formatUnits(); + + static QString stdMove(const QString &c); + +private: + static QString getModuleHeaderFileBaseName(const QString &moduleName = QString()); + static QString cpythonGetterFunctionName(const QString &name, + const AbstractMetaClassCPtr &enclosingClass); + static QString cpythonSetterFunctionName(const QString &name, + const AbstractMetaClassCPtr &enclosingClass); + + static const GeneratorClassInfoCacheEntry & + getGeneratorClassInfo(const AbstractMetaClassCPtr &scope); + static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClassCPtr &scope); + static QList<AbstractMetaFunctionCList> + getNumberProtocolOperators(const AbstractMetaClassCPtr &metaClass); + static BoolCastFunctionOptional getBoolCast(const AbstractMetaClassCPtr &metaClass); + static bool classNeedsGetattroFunctionImpl(const AbstractMetaClassCPtr &metaClass); + + QString translateTypeForWrapperMethod(const AbstractMetaType &cType, + const AbstractMetaClassCPtr &context, + Options opt = NoOption) const; + + /** + * Returns all different inherited overloads of func. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + static void getInheritedOverloads(const AbstractMetaClassCPtr &scope, + AbstractMetaFunctionCList *overloads); + + + /** + * Write a function argument in the C++ in the text stream \p s. + * This function just call \code s << argumentString(); \endcode + * \param s text stream used to write the output. + * \param func the current metafunction. + * \param argument metaargument information to be parsed. + * \param options some extra options. + */ + void writeArgument(TextStream &s, + const AbstractMetaFunctionCPtr &func, + const AbstractMetaArgument &argument, + Options options = NoOption) const; + /** + * Create a QString in the C++ format to an function argument. + * \param func the current metafunction. + * \param argument metaargument information to be parsed. + * \param options some extra options. + */ + QString argumentString(const AbstractMetaFunctionCPtr &func, + const AbstractMetaArgument &argument, + Options options = NoOption) const; + + QString functionReturnType(const AbstractMetaFunctionCPtr &func, Options options = NoOption) const; + + /// Utility function for writeCodeSnips. + using ArgumentVarReplacementPair = std::pair<AbstractMetaArgument, QString>; + using ArgumentVarReplacementList = QList<ArgumentVarReplacementPair>; + static ArgumentVarReplacementList + getArgumentReplacement(const AbstractMetaFunctionCPtr &func, + bool usePyArgs, TypeSystem::Language language, + const AbstractMetaArgument *lastArg); + + /// Returns a string with the user's custom code snippets that comply with \p position and \p language. + static QString getCodeSnippets(const QList<CodeSnip> &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language); + + enum TypeSystemConverterVariable { + TypeSystemCheckFunction = 0, + TypeSystemIsConvertibleFunction, + TypeSystemToCppFunction, + TypeSystemToPythonFunction, + TypeSystemConverterVariables + }; + void replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, + QString &code) const; + + /// Replaces the %CONVERTTOPYTHON type system variable. + inline void replaceConvertToPythonTypeSystemVariable(QString &code) const + { + replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code); + } + /// Replaces the %CONVERTTOCPP type system variable. + inline void replaceConvertToCppTypeSystemVariable(QString &code) const + { + replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code); + } + /// Replaces the %ISCONVERTIBLE type system variable. + inline void replaceIsConvertibleToCppTypeSystemVariable(QString &code) const + { + replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code); + } + /// Replaces the %CHECKTYPE type system variable. + inline void replaceTypeCheckTypeSystemVariable(QString &code) const + { + replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code); + } + + /// Return a prefix with '_' suitable for names in C++ + static QString moduleCppPrefix(const QString &moduleName = QString()); + + /// Functions used to write the function arguments on the class buffer. + /// \param s the class output buffer + /// \param func the pointer to metafunction information + /// \param count the number of function arguments + /// \param options some extra options used during the parser + static void writeArgumentNames(TextStream &s, + const AbstractMetaFunctionCPtr &func, + Options option); + + void writeFunctionArguments(TextStream &s, + const AbstractMetaFunctionCPtr &func, + Options options = NoOption) const; + + void replaceTemplateVariables(QString &code, + const AbstractMetaFunctionCPtr &func) const; + + static ShibokenGeneratorOptions m_options; + + /// Type system converter variable replacement names and regular expressions. + static const QHash<int, QString> &typeSystemConvName(); + + using TypeSystemConverterRegExps = std::array<QRegularExpression, TypeSystemConverterVariables>; + static const TypeSystemConverterRegExps &typeSystemConvRegExps(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(ShibokenGenerator::FunctionGeneration); +Q_DECLARE_OPERATORS_FOR_FLAGS(ShibokenGenerator::AttroCheck); + +#endif // SHIBOKENGENERATOR_H |