1
/*
2
 * This file is part of the API Extractor project.
3
 *
4
 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
5
 *
6
 * Contact: PySide team <contact@pyside.org>
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * version 2 as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
 * 02110-1301 USA
21
 *
22
 */
23
24
#ifndef GENERATOR_H
25
#define GENERATOR_H
26
27
#include <QtCore/QObject>
28
#include <QtCore/QDir>
29
#include <QtCore/QLinkedList>
30
#include <abstractmetalang.h>
31
#include "generatorrunnermacros.h"
32
33
class ApiExtractor;
34
class AbstractMetaBuilder;
35
class QFile;
36
37
#define EXPORT_GENERATOR_PLUGIN(X)\
38
extern "C" GENRUNNER_EXPORT void getGenerators(GeneratorList* list)\
39
{\
40
    *list << X;\
41
}\
42
43
GENRUNNER_API
44
QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor);
45
GENRUNNER_API
46
void verifyDirectoryFor(const QFile &file);
47
48
GENRUNNER_API QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true);
49
GENRUNNER_API QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true);
50
51
/**
52
 *   Base class for all generators. The default implementations does nothing,
53
 *   you must subclass this to create your own generators.
54
 */
55
class GENRUNNER_API Generator
56
{
57
public:
58
    /// Optiosn used around the generator code
59
    enum Option {
60
        NoOption                 = 0x00000000,
61
        BoxedPrimitive           = 0x00000001,
62
        ExcludeConst             = 0x00000002,
63
        ExcludeReference         = 0x00000004,
64
        UseNativeIds             = 0x00000008,
65
66
        EnumAsInts               = 0x00000010,
67
        SkipName                 = 0x00000020,
68
        NoCasts                  = 0x00000040,
69
        SkipReturnType           = 0x00000080,
70
        OriginalName             = 0x00000100,
71
        ShowStatic               = 0x00000200,
72
        UnderscoreSpaces         = 0x00000400,
73
        ForceEnumCast            = 0x00000800,
74
        ArrayAsPointer           = 0x00001000,
75
        VirtualCall              = 0x00002000,
76
        SkipTemplateParameters   = 0x00004000,
77
        SkipAttributes           = 0x00008000,
78
        OriginalTypeDescription  = 0x00010000,
79
        SkipRemovedArguments     = 0x00020000,
80
        IncludeDefaultExpression = 0x00040000,
81
        NoReturnStatement        = 0x00080000,
82
        NoBlockedSlot            = 0x00100000,
83
84
        SuperCall                = 0x00200000,
85
86
        GlobalRefJObject         = 0x00100000,
87
88
        SkipDefaultValues        = 0x00400000,
89
90
        WriteSelf                = 0x00800000,
91
        ExcludeMethodConst       = 0x01000000,
92
93
        ForceValueType           = ExcludeReference | ExcludeConst
94
    };
95
    Q_DECLARE_FLAGS(Options, Option)
96
97
    Generator();
98
    virtual ~Generator();
99
100
    bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args);
101
102
    virtual QMap<QString, QString> options() const;
103
104
    /// Returns the classes used to generate the binding code.
105
    AbstractMetaClassList classes() const;
106
107
    /// Returns all global functions found by APIExtractor
108
    AbstractMetaFunctionList globalFunctions() const;
109
110
    /// Returns all global enums found by APIExtractor
111
    AbstractMetaEnumList globalEnums() const;
112
113
    /// Returns all primitive types found by APIExtractor
114
    QList<const PrimitiveTypeEntry*> primitiveTypes() const;
115
116
    /// Returns all container types found by APIExtractor
117
    QList<const ContainerTypeEntry*> containerTypes() const;
118
119
    /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found.
120
    const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const;
121
122
    /// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found.
123
    const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const;
124
125
    /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found.
126
    const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const;
127
128
    /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found.
129
    const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const;
130
131
    /// Returns the output directory
132
    QString outputDirectory() const;
133
134
    /// Set the output directory
135
    void setOutputDirectory(const QString &outDir);
136
137
    /**
138
    *   Start the code generation, be sure to call setClasses before callign this method.
139
    *   For each class it creates a QTextStream, call the write method with the current
140
    *   class and the associated text stream, then write the text stream contents if needed.
141
    *   \see #write
142
    */
143
    void generate();
144
145
    /// Returns the number of generated items
146
    int numGenerated() const;
147
148
    /// Returns the number of generated items written
149
    int numGeneratedAndWritten() const;
150
151
    /// Returns the generator's name. Used for cosmetic purposes.
152
    virtual const char* name() const = 0;
153
154
    /// Returns true if the generator should generate any code for the TypeEntry.
155
    bool shouldGenerateTypeEntry(const TypeEntry*) const;
156
157
    /// Returns true if the generator should generate any code for the AbstractMetaClass.
158
    virtual bool shouldGenerate(const AbstractMetaClass *) const;
159
160
    /// Returns the subdirectory used to write the binding code of an AbstractMetaClass.
161
    virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const;
162
163
    /**
164
    *   Translate metatypes to binding source format.
165
    *   \param metatype a pointer to metatype
166
    *   \param context the current meta class
167
    *   \param option some extra options
168
    *   \return the metatype translated to binding source format
169
    */
170
    QString translateType(const AbstractMetaType *metatype,
171
                          const AbstractMetaClass *context,
172
                          Options options = NoOption) const;
173
174
    /**
175
    *   Function used to write the fucntion arguments on the class buffer.
176
    *   \param s the class output buffer
177
    *   \param metafunction the pointer to metafunction information
178
    *   \param count the number of function arguments
179
    *   \param options some extra options used during the parser
180
    */
181
    virtual void writeFunctionArguments(QTextStream &s,
182
                                        const AbstractMetaFunction *metafunction,
183
                                        Options options = NoOption) const = 0;
184
185
    virtual void writeArgumentNames(QTextStream &s,
186
                                    const AbstractMetaFunction *metafunction,
187
                                    Options options = NoOption) const = 0;
188
189
    void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);
190
191
    // QtScript
192
    QSet<QString> qtMetaTypeDeclaredTypeNames() const;
193
194
    /**
195
    *   Returns the license comment to be prepended to each source file generated.
196
    */
197
    QString licenseComment() const;
198
199
    /**
200
    *   Sets the license comment to be prepended to each source file generated.
201
    */
202
    void setLicenseComment(const QString &licenseComment);
203
204
    /**
205
     *   Returns the package name.
206
     */
207
    QString packageName() const;
208
209
    /**
210
     *  Retrieves the name of the currently processed module.
211
     *  While package name is a complete package idetification, e.g. 'PySide.QtCore',
212
     *  a module name represents the last part of the package, e.g. 'QtCore'.
213
     *  If the target language separates the modules with characters other than
214
     *  dots ('.') the generator subclass must overload this method.
215
     *  \return a string representing the last part of a package name
216
     */
217
    virtual QString moduleName() const;
218
219
    /**
220
     *   Retrieves a list of constructors used in implicit conversions
221
     *   available on the given type. The TypeEntry must be a value-type
222
     *   or else it will return an empty list.
223
     *   \param type a TypeEntry that is expected to be a value-type
224
     *   \return a list of constructors that could be used as implicit converters
225
     */
226
    AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const;
227
228
    /// Convenience function for implicitConversions(const TypeEntry* type).
229
    AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const;
230
231
    /// Check if type is a pointer.
232
    static bool isPointer(const AbstractMetaType* type);
233
234
    /// Tells if the type or class is an Object (or QObject) Type.
235
    static bool isObjectType(const TypeEntry* type);
236
    static bool isObjectType(const ComplexTypeEntry* type);
237
    static bool isObjectType(const AbstractMetaType* metaType);
238
    static bool isObjectType(const AbstractMetaClass* metaClass);
239
240
    /// Returns true if the type is a C string (const char*).
241
    static bool isCString(const AbstractMetaType* type);
242
    /// Returns true if the type is a void pointer.
243
    static bool isVoidPointer(const AbstractMetaType* type);
244
245
    // Returns the full name of the type.
246
    QString getFullTypeName(const TypeEntry* type) const;
247
    QString getFullTypeName(const AbstractMetaType* type) const;
248
    QString getFullTypeName(const AbstractMetaClass* metaClass) const;
249
250
    /**
251
     *  Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers
252
     *  as 'const', '&', and '*' (except if the class is not derived from a template).
253
     *  This is useful for instantiated templates.
254
     */
255
    QString getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const;
256
257
    /**
258
     *   Tries to build a minimal constructor for the type.
259
     *   It will check first for a user defined default constructor.
260
     *   Returns a null string if it fails.
261
     */
262
    QString minimalConstructor(const TypeEntry* type) const;
263
    QString minimalConstructor(const AbstractMetaType* type) const;
264
    QString minimalConstructor(const AbstractMetaClass* metaClass) const;
265
protected:
266
    /**
267
     *   Returns the file name used to write the binding code of an AbstractMetaClass.
268
     *   \param metaClass the AbstractMetaClass for which the file name must be
269
     *   returned
270
     *   \return the file name used to write the binding code for the class
271
     */
272
    virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0;
273
274
275
    virtual bool doSetup(const QMap<QString, QString>& args) = 0;
276
277
    /**
278
     *   Write the bindding code for an AbstractMetaClass.
279
     *   This is called by generate method.
280
     *   \param  s   text stream to write the generated output
281
     *   \param  metaClass  the class that should be generated
282
     */
283
    virtual void generateClass(QTextStream& s, const AbstractMetaClass* metaClass) = 0;
284
    virtual void finishGeneration() = 0;
285
286
    /**
287
    *    Returns the subdirectory path for a given package
288
    *    (aka module, aka library) name.
289
    *    If the target language separates the package modules with characters other
290
    *    than dots ('.') the generator subclass must overload this method.
291
    *    /param packageName complete package name for which to return the subdirectory path
292
    *    or nothing the use the name of the currently processed package
293
    *    /return a string representing the subdirectory path for the given package
294
    */
295
    virtual QString subDirectoryForPackage(QString packageName = QString()) const;
296
297
    QList<const AbstractMetaType*> instantiatedContainers() const;
298
299
    static QString getSimplifiedContainerTypeName(const AbstractMetaType* type);
300
    void addInstantiatedContainers(const AbstractMetaType* type);
301
302
private:
303
    struct GeneratorPrivate;
304
    GeneratorPrivate* m_d;
305
    void collectInstantiatedContainers(const AbstractMetaFunction* func);
306
    void collectInstantiatedContainers(const AbstractMetaClass* metaClass);
307
    void collectInstantiatedContainers();
308
};
309
310
Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options)
311
typedef QLinkedList<Generator*> GeneratorList;
312
313
/**
314
* Utility class to store the identation level, use it in a QTextStream.
315
*/
316
class GENRUNNER_API Indentor
317
{
318
public:
319
    Indentor() : indent(0) {}
320
    int indent;
321
};
322
323
/**
324
*   Class that use the RAII idiom to set and unset the identation level.
325
*/
326
class GENRUNNER_API Indentation
327
{
328
public:
329
    Indentation(Indentor &indentor) : indentor(indentor)
330
    {
331
        indentor.indent++;
332
    }
333
    ~Indentation()
334
    {
335
        indentor.indent--;
336
    }
337
338
private:
339
    Indentor &indentor;
340
};
341
342
GENRUNNER_API inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor)
343
{
344
    for (int i = 0; i < indentor.indent; ++i)
345
        s << "    ";
346
    return s;
347
}
348
349
#endif // GENERATOR_H