aboutsummaryrefslogtreecommitdiffstats
path: root/generator.h
blob: 0ebe1b55b3f85310d3b850de9b96e1d8faa1e4ba (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
/*
 * This file is part of the API Extractor project.
 *
 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: PySide team <contact@pyside.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#ifndef GENERATOR_H
#define GENERATOR_H

#include <QtCore/QObject>
#include <QtCore/QDir>
#include <QtCore/QLinkedList>
#include <abstractmetalang.h>
#include "generatorrunnermacros.h"

class ApiExtractor;
class AbstractMetaBuilder;
class QFile;

#define EXPORT_GENERATOR_PLUGIN(X)\
extern "C" GENRUNNER_EXPORT void getGenerators(GeneratorList* list)\
{\
    *list << X;\
}\

GENRUNNER_API
QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor);
GENRUNNER_API
void verifyDirectoryFor(const QFile &file);

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

/**
 *   Base class for all generators. The default implementations does nothing,
 *   you must subclass this to create your own generators.
 */
class GENRUNNER_API Generator
{
public:
    /// Optiosn used around the generator code
    enum Option {
        NoOption                 = 0x00000000,
        BoxedPrimitive           = 0x00000001,
        ExcludeConst             = 0x00000002,
        ExcludeReference         = 0x00000004,
        UseNativeIds             = 0x00000008,

        EnumAsInts               = 0x00000010,
        SkipName                 = 0x00000020,
        NoCasts                  = 0x00000040,
        SkipReturnType           = 0x00000080,
        OriginalName             = 0x00000100,
        ShowStatic               = 0x00000200,
        UnderscoreSpaces         = 0x00000400,
        ForceEnumCast            = 0x00000800,
        ArrayAsPointer           = 0x00001000,
        VirtualCall              = 0x00002000,
        SkipTemplateParameters   = 0x00004000,
        SkipAttributes           = 0x00008000,
        OriginalTypeDescription  = 0x00010000,
        SkipRemovedArguments     = 0x00020000,
        IncludeDefaultExpression = 0x00040000,
        NoReturnStatement        = 0x00080000,
        NoBlockedSlot            = 0x00100000,

        SuperCall                = 0x00200000,

        GlobalRefJObject         = 0x00100000,

        SkipDefaultValues        = 0x00400000,

        WriteSelf                = 0x00800000,
        ExcludeMethodConst       = 0x01000000,

        ForceValueType           = ExcludeReference | ExcludeConst
    };
    Q_DECLARE_FLAGS(Options, Option)

    Generator();
    virtual ~Generator();

    bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args);

    virtual QMap<QString, QString> options() const;

    /// Returns the classes used to generate the binding code.
    AbstractMetaClassList classes() const;

    /// Returns all global functions found by APIExtractor
    AbstractMetaFunctionList globalFunctions() const;

    /// Returns all global enums found by APIExtractor
    AbstractMetaEnumList globalEnums() const;

    /// Returns all primitive types found by APIExtractor
    QList<const PrimitiveTypeEntry*> primitiveTypes() const;

    /// Returns all container types found by APIExtractor
    QList<const ContainerTypeEntry*> containerTypes() const;

    /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found.
    const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const;

    /// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found.
    const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const;

    /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found.
    const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const;

    /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found.
    const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) 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
    */
    void generate();

    /// Returns the number of generated items
    int numGenerated() const;

    /// Returns the number of generated items written
    int numGeneratedAndWritten() const;

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

    /// Returns true if the generator should generate any code for the AbstractMetaClass
    virtual bool shouldGenerate(const AbstractMetaClass *) const;

    /// Returns the subdirectory used to write the binding code of an AbstractMetaClass.
    virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) 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(const AbstractMetaType *metatype,
                          const AbstractMetaClass *context,
                          Options options = NoOption) const;

    /**
    *   Function used to write the fucntion arguments on the class buffer.
    *   \param s the class output buffer
    *   \param metafunction the pointer to metafunction information
    *   \param count the number of function arguments
    *   \param options some extra options used during the parser
    */
    virtual void writeFunctionArguments(QTextStream &s,
                                        const AbstractMetaFunction *metafunction,
                                        Options options = NoOption) const = 0;

    virtual void writeArgumentNames(QTextStream &s,
                                    const AbstractMetaFunction *metafunction,
                                    Options options = NoOption) const = 0;

    void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);

    // QtScript
    QSet<QString> qtMetaTypeDeclaredTypeNames() const;

    /**
    *   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 package name.
     */
    QString packageName() 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
     */
    virtual QString moduleName() const;

    /**
     *   Retrieves a list of constructors used in implicit conversions
     *   available on the given type. The TypeEntry must be a value-type
     *   or else it will return an empty list.
     *   \param type a TypeEntry that is expected to be a value-type
     *   \return a list of constructors that could be used as implicit converters
     */
    AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const;

    /// Convenience function for implicitConversions(const TypeEntry* type).
    AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const;

protected:
    /**
     *   Returns the file name used to write the binding code of an AbstractMetaClass.
     *   \param metaClass the AbstractMetaClass for which the file name must be
     *   returned
     *   \return the file name used to write the binding code for the class
     */
    virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0;


    virtual bool doSetup(const QMap<QString, QString>& args) = 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(QTextStream& s, const AbstractMetaClass* metaClass) = 0;
    virtual void 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)
typedef QLinkedList<Generator*> GeneratorList;

/**
* Utility class to store the identation level, use it in a QTextStream.
*/
class GENRUNNER_API Indentor
{
public:
    Indentor() : indent(0) {}
    int indent;
};

/**
*   Class that use the RAII idiom to set and unset the identation level.
*/
class GENRUNNER_API Indentation
{
public:
    Indentation(Indentor &indentor) : indentor(indentor)
    {
        indentor.indent++;
    }
    ~Indentation()
    {
        indentor.indent--;
    }

private:
    Indentor &indentor;
};

GENRUNNER_API inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor)
{
    for (int i = 0; i < indentor.indent; ++i)
        s << "    ";
    return s;
}

#endif // GENERATOR_H