From 425c1eba27766b4382ace8f10daeaa548c9eb0d6 Mon Sep 17 00:00:00 2001 From: Hugo Lima Date: Thu, 20 Aug 2009 21:24:45 -0300 Subject: The current generators will be just plugins and all generator stuff in APIExtractor were moved to this project. So we need to re-think if boostpythongenerator still a good name for the project, because boostpythongenerator will be the name of the plugin to generate bindings for boost::python. Also the generators were just moved to a subdirectory (generators) and the boostpython generators to a sub-subdirectory (generators/boostpython), transform them in plugins will be a second milestone. --- generator.h | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 generator.h (limited to 'generator.h') diff --git a/generator.h b/generator.h new file mode 100644 index 000000000..14526d7f0 --- /dev/null +++ b/generator.h @@ -0,0 +1,334 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * 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 +#include +#include "abstractmetalang.h" + +class ApiExtractor; +class AbstractMetaBuilder; +class QFile; + +/** + * Base class for all generators. The default implementations does nothing, + * you must subclass this to create your own generators. + */ +class 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 + }; + + Generator(); + virtual ~Generator(); + + bool setup(const ApiExtractor& extractor, const QMap args); + + virtual QMap options() const + { + return QMap(); + } + + /// Returns the classes used to generate the binding code. + AbstractMetaClassList classes() const + { + return m_classes; + } + + AbstractMetaFunctionList globalFunctions() const + { + return m_globalFunctions; + } + + AbstractMetaEnumList globalEnums() const + { + return m_globalEnums; + } + + QList primitiveTypes() const + { + return m_primitiveTypes; + } + + QList containerTypes() const + { + return m_containerTypes; + } + + /// Returns the output directory + QString outputDirectory() const + { + return m_outDir; + } + + /// Set the output directory + void setOutputDirectory(const QString &outDir) + { + m_outDir = 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() + { + return m_numGenerated; + } + + /// Returns the number of generated items written + int numGeneratedAndWritten() + { + return m_numGeneratedWritten; + } + + 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 = 0; + + /** + * 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 + */ + virtual QString translateType(const AbstractMetaType *metatype, + const AbstractMetaClass *context, + int option = NoOption) const = 0; + + /** + * 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, + uint options = 0) const = 0; + + virtual void writeArgumentNames(QTextStream &s, + const AbstractMetaFunction *metafunction, + uint options = 0) const = 0; + + void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func); + + bool hasDefaultConstructor(const AbstractMetaType *type); + + // QtScript + QSet qtMetaTypeDeclaredTypeNames() const + { + return m_qmetatypeDeclaredTypenames; + } + + /** + * Returns the license comment to be prepended to each source file generated. + */ + QString licenseComment() + { + return m_licenseComment; + } + + /** + * Sets the license comment to be prepended to each source file generated. + */ + void setLicenseComment(const QString &licenseComment) + { + m_licenseComment = licenseComment; + } + + /** + * Returns the package name. + */ + QString packageName() + { + return m_packageName; + } + + /** + * Sets the package name. + */ + void setPackageName(const QString &packageName) + { + m_packageName = packageName; + } + + /** + * 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() + { + return QString(m_packageName).remove(0, m_packageName.lastIndexOf('.') + 1); + } + +protected: + QString m_packageName; + + /** + * 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(QMap args) = 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 + { + if (packageName.isEmpty()) + packageName = m_packageName; + return QString(packageName).replace(".", QDir::separator()); + } + + /** + * Write the bindding code for an AbstractMetaClass. + * This is called by the default implementation of 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; + + void verifyDirectoryFor(const QFile &file); + + int m_numGenerated; + int m_numGeneratedWritten; + +private: + AbstractMetaClassList m_classes; + AbstractMetaFunctionList m_globalFunctions; + AbstractMetaEnumList m_globalEnums; + QString m_outDir; + + QList m_primitiveTypes; + QList m_containerTypes; + + // QtScript + QSet m_qmetatypeDeclaredTypenames; + + // License comment + QString m_licenseComment; +}; + +/** +* Utility class to store the identation level, use it in a QTextStream. +*/ +class Indentor +{ +public: + Indentor(): + indent(0) {} + int indent; +}; + +/** +* Class that use the RAII idiom to set and unset the identation level. +*/ +class Indentation +{ +public: + Indentation(Indentor &indentor) : indentor(indentor) + { + indentor.indent++; + } + ~Indentation() + { + indentor.indent--; + } + +private: + Indentor &indentor; +}; + +inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor) +{ + for (int i = 0; i < indentor.indent; ++i) + s << " "; + return s; +} + +#endif // GENERATOR_H + -- cgit v1.2.3