aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/generator.h
blob: 131ad427d7a360c4e78566ad892ec7bb5917d28f (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
// 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 GENERATOR_H
#define GENERATOR_H

#include <abstractmetalang_typedefs.h>
#include <typedatabase_typedefs.h>
#include <QtCore/QSharedPointer>
#include <QtCore/QList>

#include <optional>

class ApiExtractorResult;
class GeneratorContext;
class DefaultValue;
class TextStream;

QString getClassTargetFullName(const AbstractMetaClass *metaClass, bool includePackageName = true);
QString getClassTargetFullName(const AbstractMetaEnum &metaEnum, bool includePackageName = true);
QString getFilteredCppSignatureString(QString signature);

/**
 *   Base class for all generators. The default implementations does nothing,
 *   you must subclass this to create your own generators.
 */
class Generator
{
public:
    using OptionDescription = QPair<QString, QString>;
    using OptionDescriptions = QList<OptionDescription>;

    /// Optiosn used around the generator code
    enum Option {
        NoOption                 = 0x00000000,
        ExcludeConst             = 0x00000001,
        ExcludeReference         = 0x00000002,

        SkipReturnType           = 0x00000010,
        VirtualCall              = 0x00000040,
        OriginalTypeDescription  = 0x00000080,
        SkipRemovedArguments     = 0x00000100,

        SkipDefaultValues        = 0x00000200,
    };
    Q_DECLARE_FLAGS(Options, Option)

    enum FileNameFlag {
        UnqualifiedName = 0x1,
        KeepCase = 0x2
    };
    Q_DECLARE_FLAGS(FileNameFlags, FileNameFlag)

    Generator();
    virtual ~Generator();

    bool setup(const ApiExtractorResult &api);

    virtual OptionDescriptions options() const;
    virtual bool handleOption(const QString &key, const QString &value);

    /// Returns the top namespace made invisible
    const AbstractMetaClassCList &invisibleTopNamespaces() const;

    /// Returns the output directory
    QString outputDirectory() const;

    /// Set the output directory
    void setOutputDirectory(const QString &outDir);

    /**
     *   Start the code generation, be sure to call setClasses before callign this method.
     *   For each class it creates a QTextStream, call the write method with the current
     *   class and the associated text stream, then write the text stream contents if needed.
     *   \see #write
     */
    bool generate();

    /// Returns the license comment to be prepended to each source file generated.
    QString licenseComment() const;

    /// Sets the license comment to be prepended to each source file generated.
    void setLicenseComment(const QString &licenseComment);

    /// Returns the generator's name. Used for cosmetic purposes.
    virtual const char *name() const = 0;

    /// Returns the API as determined by ApiExtractor
    const ApiExtractorResult &api() const;

    bool hasPrivateClasses() const;

    /// Returns true if the user enabled PySide extensions (command line option)
    bool usePySideExtensions() const;
    /// Returns true if the generated code should not use the
    /// "#define protected public" hack.
    bool avoidProtectedHack() const;

    /**
     *  Retrieves the name of the currently processed module.
     *  While package name is a complete package idetification, e.g. 'PySide.QtCore',
     *  a module name represents the last part of the package, e.g. 'QtCore'.
     *  If the target language separates the modules with characters other than
     *  dots ('.') the generator subclass must overload this method.
     *  \return a string representing the last part of a package name
     */
    static QString moduleName();

    static QString pythonOperatorFunctionName(const QString &cppOpFuncName);

protected:
    /// Helper for determining the file name
    static QString fileNameForContextHelper(const GeneratorContext &context,
                                            const QString &suffix,
                                            FileNameFlags flags = {});

    /// Returns all primitive types found by APIExtractor
    static PrimitiveTypeEntryCList primitiveTypes();

    /// Returns all container types found by APIExtractor
    static ContainerTypeEntryCList containerTypes();

    virtual GeneratorContext contextForClass(const AbstractMetaClass *c) const;
    static GeneratorContext contextForSmartPointer(const AbstractMetaClass *c,
                                                   const AbstractMetaType &t,
                                                   const AbstractMetaClass *pointeeClass = nullptr);

    /// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case).
    bool generateFileForContext(const GeneratorContext &context);

    /// Returns the file base name for a smart pointer.
    static QString getFileNameBaseForSmartPointer(const AbstractMetaType &smartPointerType);

    /// Returns true if the generator should generate any code for the AbstractMetaClass.
    virtual bool shouldGenerate(const TypeEntryCPtr &t) const;

    /**
    *   Translate metatypes to binding source format.
    *   \param metatype a pointer to metatype
    *   \param context the current meta class
    *   \param option some extra options
    *   \return the metatype translated to binding source format
    */
    QString translateType(AbstractMetaType metatype,
                          const AbstractMetaClass *context,
                          Options options = NoOption) const;

    /**
     *   Returns the package name.
     */
    static QString packageName();

    // Returns the full name of the type.
    static QString getFullTypeName(TypeEntryCPtr type);
    static QString getFullTypeName(const AbstractMetaType &type);
    static QString getFullTypeName(const AbstractMetaClass *metaClass);

    /**
     *  Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers
     *  as 'const', '&', and '*' (except if the class is not derived from a template).
     *  This is useful for instantiated templates.
     */
    static QString getFullTypeNameWithoutModifiers(const AbstractMetaType &type);

    /**
     *   Tries to build a minimal constructor for the type.
     *   It will check first for a user defined default constructor.
     *   Returns a null string if it fails.
     */
    static std::optional<DefaultValue>
        minimalConstructor(const ApiExtractorResult &api, const TypeEntryCPtr &type,
                           QString *errorString = nullptr);
    static std::optional<DefaultValue>
        minimalConstructor(const ApiExtractorResult &api, const AbstractMetaType &type,
                           QString *errorString = nullptr);
    static std::optional<DefaultValue>
        minimalConstructor(const ApiExtractorResult &api,
                           const AbstractMetaClass *metaClass,
                           QString *errorString = nullptr);

    /**
     *   Returns the file name used to write the binding code of an AbstractMetaClass/Type.
     *   \param context the GeneratorContext which contains an AbstractMetaClass or AbstractMetaType
     *   for which the file name must be returned
     *   \return the file name used to write the binding code for the class
     */
    virtual QString fileNameForContext(const GeneratorContext &context) const = 0;


    virtual bool doSetup() = 0;

    /**
     *   Write the bindding code for an AbstractMetaClass.
     *   This is called by generate method.
     *   \param  s   text stream to write the generated output
     *   \param  metaClass  the class that should be generated
     */
    virtual void generateClass(TextStream &s, const GeneratorContext &classContext) = 0;
    virtual bool finishGeneration() = 0;

    /**
    *    Returns the subdirectory path for a given package
    *    (aka module, aka library) name.
    *    If the target language separates the package modules with characters other
    *    than dots ('.') the generator subclass must overload this method.
    *    /param packageName complete package name for which to return the subdirectory path
    *    or nothing the use the name of the currently processed package
    *    /return a string representing the subdirectory path for the given package
    */
    virtual QString subDirectoryForPackage(QString packageName = QString()) const;

private:
    struct GeneratorPrivate;
    GeneratorPrivate *m_d;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options)
Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::FileNameFlags)

using GeneratorPtr = QSharedPointer<Generator>;
using Generators = QList<GeneratorPtr>;

#endif // GENERATOR_H