aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/shibokengenerator.h
blob: 22ee73fa2d64fcb9c9a3fecdce25aabdebea89aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
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