diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-08-17 17:32:08 -0300 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2009-08-17 17:32:08 -0300 |
commit | 9732e0c744e45a67094fc6ce08bdadb1f9a08d4a (patch) | |
tree | 566e389f406515b040317bffa075f4e5021020f7 /typesystem.h |
The genesis...
Diffstat (limited to 'typesystem.h')
-rw-r--r-- | typesystem.h | 1958 |
1 files changed, 1958 insertions, 0 deletions
diff --git a/typesystem.h b/typesystem.h new file mode 100644 index 000000000..f03fd04ee --- /dev/null +++ b/typesystem.h @@ -0,0 +1,1958 @@ +/* + * 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 TYPESYSTEM_H +#define TYPESYSTEM_H + +#include <QtCore/QHash> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QMap> +#include <QtCore/QDebug> + +class Indentor; + +class AbstractMetaType; +class QTextStream; + +class EnumTypeEntry; +class FlagsTypeEntry; + +extern QString strings_Object; +extern QString strings_String; +extern QString strings_Thread; +extern QString strings_char; +extern QString stringsJavaLang; +extern QString strings_jchar; +extern QString strings_jobject; + +struct Include +{ + enum IncludeType { + IncludePath, + LocalPath, + TargetLangImport + }; + + Include() : type(IncludePath) {} + Include(IncludeType t, const QString &nam) : type(t), name(nam) {}; + + bool isValid() + { + return !name.isEmpty(); + } + + IncludeType type; + QString name; + + QString toString() const; + + bool operator<(const Include &other) const + { + return name < other.name; + } +}; +typedef QList<Include> IncludeList; + +typedef QMap<int, QString> ArgumentMap; + +class TemplateInstance; + +namespace TypeSystem +{ +enum Language { + NoLanguage = 0x0000, + TargetLangCode = 0x0001, + NativeCode = 0x0002, + ShellCode = 0x0004, + ShellDeclaration = 0x0008, + PackageInitializer = 0x0010, + DestructorFunction = 0x0020, + Constructors = 0x0040, + Interface = 0x0080, + + // masks + All = TargetLangCode + | NativeCode + | ShellCode + | ShellDeclaration + | PackageInitializer + | Constructors + | Interface + | DestructorFunction, + + TargetLangAndNativeCode = TargetLangCode | NativeCode +}; + +enum Ownership { + InvalidOwnership, + DefaultOwnership, + TargetLangOwnership, + CppOwnership +}; +}; + +struct ReferenceCount +{ + ReferenceCount() {} + enum Action { // 0x01 - 0xff + Invalid = 0x00, + Add = 0x01, + AddAll = 0x02, + Remove = 0x04, + Set = 0x08, + Ignore = 0x10, + + ActionsMask = 0xff, + + Padding = 0xffffffff + }; + + Action action; +}; + +struct ArgumentOwner +{ + enum Action { + Invalid = 0x00, + Add = 0x01, + Remove = 0x02 + }; + ArgumentOwner() : action(ArgumentOwner::Invalid), index(-2) {} + + Action action; + int index; +}; + +class CodeSnipFragment +{ +private: + const QString m_code; + TemplateInstance *m_instance; + +public: + CodeSnipFragment(const QString &code) + : m_code(code), + m_instance(0) {} + + CodeSnipFragment(TemplateInstance *instance) + : m_instance(instance) {} + + QString code() const; +}; + +class CodeSnipAbstract +{ +public: + QString code() const; + + void addCode(const QString &code) + { + codeList.append(new CodeSnipFragment(code)); + } + + void addTemplateInstance(TemplateInstance *ti) + { + codeList.append(new CodeSnipFragment(ti)); + } + + QList<CodeSnipFragment*> codeList; +}; + +class CustomFunction : public CodeSnipAbstract +{ +public: + CustomFunction(const QString &n = QString()) : name(n) { } + + QString name; + QString paramName; +}; + +class TemplateEntry : public CodeSnipAbstract +{ +public: + TemplateEntry(const QString &name) + : m_name(name) + { + }; + + QString name() const + { + return m_name; + }; + +private: + QString m_name; +}; + +typedef QHash<QString, TemplateEntry *> TemplateEntryHash; + +class TemplateInstance +{ +public: + TemplateInstance(const QString &name) + : m_name(name) {} + + void addReplaceRule(const QString &name, const QString &value) + { + replaceRules[name] = value; + } + + QString expandCode() const; + + QString name() const + { + return m_name; + } + +private: + const QString m_name; + QHash<QString, QString> replaceRules; +}; + + +class CodeSnip : public CodeSnipAbstract +{ +public: + enum Position { + Beginning, + End, + AfterThis, + // QtScript + Declaration, + PrototypeInitialization, + ConstructorInitialization, + Constructor + }; + + CodeSnip() : language(TypeSystem::TargetLangCode) { } + CodeSnip(TypeSystem::Language lang) : language(lang) { } + + // Very simple, easy to make code ugly if you try + QTextStream &formattedCode(QTextStream &s, Indentor &indentor) const; + + TypeSystem::Language language; + Position position; + ArgumentMap argumentMap; +}; +typedef QList<CodeSnip> CodeSnipList; + +struct ArgumentModification +{ + ArgumentModification(int idx) + : removedDefaultExpression(false), removed(false), + noNullPointers(false), index(idx) {} + + // Should the default expression be removed? + uint removedDefaultExpression : 1; + uint removed : 1; + uint noNullPointers : 1; + uint resetAfterUse : 1; + + // The index of this argument + int index; + + // Reference count flags for this argument + QList<ReferenceCount> referenceCounts; + + // The text given for the new type of the argument + QString modified_type; + + QString replace_value; + + // The code to be used to construct a return value when noNullPointers is true and + // the returned value is null. If noNullPointers is true and this string is + // empty, then the base class implementation will be used (or a default construction + // if there is no implementation) + QString nullPointerDefaultValue; + + // The text of the new default expression of the argument + QString replacedDefaultExpression; + + // The new definition of ownership for a specific argument + QHash<TypeSystem::Language, TypeSystem::Ownership> ownerships; + + // Different conversion rules + CodeSnipList conversion_rules; + + //QObject parent(owner) of this argument + ArgumentOwner owner; +}; + +struct Modification +{ + enum Modifiers { + Private = 0x0001, + Protected = 0x0002, + Public = 0x0003, + Friendly = 0x0004, + AccessModifierMask = 0x000f, + + Final = 0x0010, + NonFinal = 0x0020, + FinalMask = Final | NonFinal, + + Readable = 0x0100, + Writable = 0x0200, + + CodeInjection = 0x1000, + Rename = 0x2000, + Deprecated = 0x4000, + ReplaceExpression = 0x8000, + VirtualSlot = 0x10000 | NonFinal + }; + + Modification() : modifiers(0) { } + + bool isAccessModifier() const + { + return modifiers & AccessModifierMask; + } + Modifiers accessModifier() const + { + return Modifiers(modifiers & AccessModifierMask); + } + bool isPrivate() const + { + return accessModifier() == Private; + } + bool isProtected() const + { + return accessModifier() == Protected; + } + bool isPublic() const + { + return accessModifier() == Public; + } + bool isFriendly() const + { + return accessModifier() == Friendly; + } + bool isFinal() const + { + return modifiers & Final; + } + bool isNonFinal() const + { + return modifiers & NonFinal; + } + bool isVirtualSlot() const + { + return (modifiers & VirtualSlot) == VirtualSlot; + } + QString accessModifierString() const; + + bool isDeprecated() const + { + return modifiers & Deprecated; + } + + void setRenamedTo(const QString &name) + { + renamedToName = name; + } + QString renamedTo() const + { + return renamedToName; + } + bool isRenameModifier() const + { + return modifiers & Rename; + } + + uint modifiers; + QString renamedToName; +}; + +struct FunctionModification: public Modification +{ + FunctionModification() : removal(TypeSystem::NoLanguage), m_thread(false), m_allowThread(false) {} + + bool isCodeInjection() const + { + return modifiers & CodeInjection; + } + bool isRemoveModifier() const + { + return removal != TypeSystem::NoLanguage; + } + void setIsThread(bool flag) + { + m_thread = flag; + } + bool isThread() const + { + return m_thread; + } + bool allowThread() const + { + return m_allowThread; + } + void setAllowThread(bool allow) + { + m_allowThread = allow; + } + + QString toString() const; + + QString signature; + QString association; + CodeSnipList snips; + TypeSystem::Language removal; + + QList<ArgumentModification> argument_mods; + +private: + bool m_thread; + bool m_allowThread; + +}; +typedef QList<FunctionModification> FunctionModificationList; + +struct FieldModification: public Modification +{ + bool isReadable() const + { + return modifiers & Readable; + } + bool isWritable() const + { + return modifiers & Writable; + } + + QString name; +}; +typedef QList<FieldModification> FieldModificationList; + +struct ExpensePolicy +{ + ExpensePolicy() : limit(-1) {} + int limit; + QString cost; + bool isValid() const + { + return limit >= 0; + } +}; + +class InterfaceTypeEntry; +class ObjectTypeEntry; + +class DocModification +{ +public: + enum Mode { + Append, + Prepend, + Replace, + XPathReplace + }; + + DocModification(const QString& xpath, const QString& signature) + : format(TypeSystem::NativeCode), m_mode(XPathReplace), + m_xpath(xpath), m_signature(signature) {} + DocModification(Mode mode, const QString& signature) + : m_mode(mode), m_signature(signature) {} + + void setCode(const QString& code) + { + m_code = code; + } + QString code() const + { + return m_code; + } + QString xpath() const + { + return m_xpath; + } + QString signature() const + { + return m_signature; + } + Mode mode() const + { + return m_mode; + } + + TypeSystem::Language format; + +private: + Mode m_mode; + QString m_code; + QString m_xpath; + QString m_signature; +}; + +typedef QList<DocModification> DocModificationList; + +class TypeEntry +{ +public: + enum Type { + PrimitiveType, + VoidType, + FlagsType, + EnumType, + TemplateArgumentType, + ThreadType, + BasicValueType, + StringType, + ContainerType, + InterfaceType, + ObjectType, + NamespaceType, + VariantType, + JObjectWrapperType, + CharType, + ArrayType, + TypeSystemType, + CustomType, + }; + + enum CodeGeneration { + GenerateTargetLang = 0x0001, + GenerateCpp = 0x0002, + GenerateForSubclass = 0x0004, + + GenerateNothing = 0, + GenerateAll = 0xffff, + GenerateCode = GenerateTargetLang | GenerateCpp + }; + + TypeEntry(const QString &name, Type t) + : m_name(name), + m_type(t), + m_codeGeneration(GenerateAll), + m_preferredConversion(true) + { + }; + + virtual ~TypeEntry() { } + + Type type() const + { + return m_type; + } + bool isPrimitive() const + { + return m_type == PrimitiveType; + } + bool isEnum() const + { + return m_type == EnumType; + } + bool isFlags() const + { + return m_type == FlagsType; + } + bool isInterface() const + { + return m_type == InterfaceType; + } + bool isObject() const + { + return m_type == ObjectType; + } + bool isString() const + { + return m_type == StringType; + } + bool isChar() const + { + return m_type == CharType; + } + bool isNamespace() const + { + return m_type == NamespaceType; + } + bool isContainer() const + { + return m_type == ContainerType; + } + bool isVariant() const + { + return m_type == VariantType; + } + bool isJObjectWrapper() const + { + return m_type == JObjectWrapperType; + } + bool isArray() const + { + return m_type == ArrayType; + } + bool isTemplateArgument() const + { + return m_type == TemplateArgumentType; + } + bool isVoid() const + { + return m_type == VoidType; + } + bool isThread() const + { + return m_type == ThreadType; + } + bool isCustom() const + { + return m_type == CustomType; + } + bool isBasicValue() const + { + return m_type == BasicValueType; + } + bool isTypeSystem() const + { + return m_type == TypeSystemType; + } + + virtual bool preferredConversion() const + { + return m_preferredConversion; + } + virtual void setPreferredConversion(bool b) + { + m_preferredConversion = b; + } + + // The type's name in C++, fully qualified + QString name() const + { + return m_name; + } + + uint codeGeneration() const + { + return m_codeGeneration; + } + void setCodeGeneration(uint cg) + { + m_codeGeneration = cg; + } + + // Returns true if code must be generated for this entry, + // it will return false in case of types coming from typesystems + // included for reference only. + // NOTE: 'GenerateForSubclass' means 'generate="no"' + // on 'load-typesystem' tag + inline bool generateCode() const + { + return m_codeGeneration != TypeEntry::GenerateForSubclass + && m_codeGeneration != TypeEntry::GenerateNothing; + } + + virtual QString qualifiedCppName() const + { + return m_name; + } + + /** + * Its type's name in target language API + * The target language API name represents how this type is + * referred on low level code for the target language. + * Examples: for Java this would be a JNI name, for Python + * it should represent the CPython type name. + * /return string representing the target language API name + * for this type entry + */ + virtual QString targetLangApiName() const + { + return m_name; + } + + // The type's name in TargetLang + virtual QString targetLangName() const + { + return m_name; + } + + // The type to lookup when converting to TargetLang + virtual QString lookupName() const + { + return targetLangName(); + } + + // The package + virtual QString targetLangPackage() const + { + return QString(); + } + + virtual QString qualifiedTargetLangName() const + { + QString pkg = targetLangPackage(); + if (pkg.isEmpty()) + return targetLangName(); + return pkg + '.' + targetLangName(); + } + + virtual InterfaceTypeEntry *designatedInterface() const + { + return 0; + } + + void setCustomConstructor(const CustomFunction &func) + { + m_customConstructor = func; + } + CustomFunction customConstructor() const + { + return m_customConstructor; + } + + void setCustomDestructor(const CustomFunction &func) + { + m_customDestructor = func; + } + CustomFunction customDestructor() const + { + return m_customDestructor; + } + + virtual bool isValue() const + { + return false; + } + virtual bool isComplex() const + { + return false; + } + + virtual bool isNativeIdBased() const + { + return false; + } + + CodeSnipList codeSnips() const + { + return m_codeSnips; + } + void setCodeSnips(const CodeSnipList &codeSnips) + { + m_codeSnips = codeSnips; + } + void addCodeSnip(const CodeSnip &codeSnip) + { + m_codeSnips << codeSnip; + } + + void setDocModification(const DocModificationList& docMods) + { + m_docModifications << docMods; + } + DocModificationList docModifications() const + { + return m_docModifications; + } + +private: + QString m_name; + Type m_type; + uint m_codeGeneration; + CustomFunction m_customConstructor; + CustomFunction m_customDestructor; + bool m_preferredConversion; + CodeSnipList m_codeSnips; + DocModificationList m_docModifications; +}; +typedef QHash<QString, QList<TypeEntry *> > TypeEntryHash; +typedef QHash<QString, TypeEntry *> SingleTypeEntryHash; + + +class TypeSystemTypeEntry : public TypeEntry +{ +public: + TypeSystemTypeEntry(const QString &name) + : TypeEntry(name, TypeSystemType) + { + }; +}; + + +class ThreadTypeEntry : public TypeEntry +{ +public: + ThreadTypeEntry() : TypeEntry("QThread", ThreadType) + { + setCodeGeneration(GenerateNothing); + } + + QString targetLangApiName() const + { + return strings_jobject; + } + QString targetLangName() const + { + return strings_Thread; + } + QString targetLangPackage() const + { + return stringsJavaLang; + } +}; + +class VoidTypeEntry : public TypeEntry +{ +public: + VoidTypeEntry() : TypeEntry("void", VoidType) { } +}; + +class TemplateArgumentEntry : public TypeEntry +{ +public: + TemplateArgumentEntry(const QString &name) + : TypeEntry(name, TemplateArgumentType), m_ordinal(0) + { + } + + int ordinal() const + { + return m_ordinal; + } + void setOrdinal(int o) + { + m_ordinal = o; + } + +private: + int m_ordinal; +}; + +class ArrayTypeEntry : public TypeEntry +{ +public: + ArrayTypeEntry(const TypeEntry *nested_type) + : TypeEntry("Array", ArrayType), m_nestedType(nested_type) + { + Q_ASSERT(m_nestedType); + } + + void setNestedTypeEntry(TypeEntry *nested) + { + m_nestedType = nested; + } + const TypeEntry *nestedTypeEntry() const + { + return m_nestedType; + } + + QString targetLangName() const + { + return m_nestedType->targetLangName() + "[]"; + } + QString targetLangApiName() const + { + if (m_nestedType->isPrimitive()) + return m_nestedType->targetLangApiName() + "Array"; + else + return "jobjectArray"; + } + +private: + const TypeEntry *m_nestedType; +}; + + +class PrimitiveTypeEntry : public TypeEntry +{ +public: + PrimitiveTypeEntry(const QString &name) + : TypeEntry(name, PrimitiveType), + m_preferredConversion(true), + m_preferredTargetLangType(true), + m_aliasedTypeEntry(0) + { + } + + QString targetLangName() const + { + return m_targetLangName; + } + void setTargetLangName(const QString &targetLangName) + { + m_targetLangName = targetLangName; + } + + QString targetLangApiName() const + { + return m_targetLangApiName; + } + void setTargetLangApiName(const QString &targetLangApiName) + { + m_targetLangApiName = targetLangApiName; + } + + /** + * The PrimitiveTypeEntry pointed by this type entry if it + * represents an alias (i.e. a typedef). + * /return the type pointed by the alias, or a null pointer + * if the current object is not an alias + */ + PrimitiveTypeEntry* aliasedTypeEntry() const { return m_aliasedTypeEntry; } + + /** + * Defines type aliased by this entry. + * /param aliasedTypeEntry type aliased by this entry + */ + void setAliasedTypeEntry(PrimitiveTypeEntry* aliasedTypeEntry) + { + m_aliasedTypeEntry = aliasedTypeEntry; + } + + /** + * Finds the most basic primitive type that the typedef represents, + * i.e. a type that is not an alias. + * /return the most basic non-aliased primitive type represented + * by this typedef + */ + PrimitiveTypeEntry* basicAliasedTypeEntry() const; + + QString javaObjectFullName() const + { + return javaObjectPackage() + "." + javaObjectName(); + } + QString javaObjectName() const; + QString javaObjectPackage() const + { + return stringsJavaLang; + } + + virtual bool preferredConversion() const + { + return m_preferredConversion; + } + virtual void setPreferredConversion(bool b) + { + m_preferredConversion = b; + } + + virtual bool preferredTargetLangType() const + { + return m_preferredTargetLangType; + } + virtual void setPreferredTargetLangType(bool b) + { + m_preferredTargetLangType = b; + } + +private: + QString m_targetLangName; + QString m_targetLangApiName; + uint m_preferredConversion : 1; + uint m_preferredTargetLangType : 1; + PrimitiveTypeEntry* m_aliasedTypeEntry; +}; + + + + +struct EnumValueRedirection +{ + EnumValueRedirection(const QString &rej, const QString &us) + : rejected(rej), + used(us) + { + } + QString rejected; + QString used; +}; + +class EnumTypeEntry : public TypeEntry +{ +public: + EnumTypeEntry(const QString &nspace, const QString &enumName) + : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, + EnumType), + m_flags(0), + m_extensible(false) + { + m_qualifier = nspace; + m_targetLangName = enumName; + } + + QString targetLangPackage() const + { + return m_packageName; + } + void setTargetLangPackage(const QString &package) + { + m_packageName = package; + } + + QString targetLangName() const + { + return m_targetLangName; + } + QString targetLangQualifier() const; + QString qualifiedTargetLangName() const + { + QString qualifiedName; + QString pkg = targetLangPackage(); + QString qualifier = targetLangQualifier(); + + if (!pkg.isEmpty()) + qualifiedName += pkg + '.'; + if (!qualifier.isEmpty()) + qualifiedName += qualifier + '.'; + qualifiedName += targetLangName(); + + return qualifiedName; + } + + QString targetLangApiName() const; + + QString qualifier() const + { + return m_qualifier; + } + void setQualifier(const QString &q) + { + m_qualifier = q; + } + + virtual bool preferredConversion() const + { + return false; + } + + bool isBoundsChecked() const + { + return m_lowerBound.isEmpty() && m_upperBound.isEmpty(); + } + + QString upperBound() const + { + return m_upperBound; + } + void setUpperBound(const QString &bound) + { + m_upperBound = bound; + } + + QString lowerBound() const + { + return m_lowerBound; + } + void setLowerBound(const QString &bound) + { + m_lowerBound = bound; + } + + void setFlags(FlagsTypeEntry *flags) + { + m_flags = flags; + } + FlagsTypeEntry *flags() const + { + return m_flags; + } + + bool isExtensible() const + { + return m_extensible; + } + void setExtensible(bool is) + { + m_extensible = is; + } + + bool isEnumValueRejected(const QString &name) + { + return m_rejectedEnums.contains(name); + } + void addEnumValueRejection(const QString &name) + { + m_rejectedEnums << name; + } + QStringList enumValueRejections() const + { + return m_rejectedEnums; + } + + void addEnumValueRedirection(const QString &rejected, const QString &usedValue); + QString enumValueRedirection(const QString &value) const; + + bool forceInteger() const + { + return m_forceInteger; + } + void setForceInteger(bool force) + { + m_forceInteger = force; + } + +private: + QString m_packageName; + QString m_qualifier; + QString m_targetLangName; + + QString m_lowerBound; + QString m_upperBound; + + QStringList m_rejectedEnums; + QList<EnumValueRedirection> m_enumRedirections; + + FlagsTypeEntry *m_flags; + + bool m_extensible; + bool m_forceInteger; +}; + +class FlagsTypeEntry : public TypeEntry +{ +public: + FlagsTypeEntry(const QString &name) : TypeEntry(name, FlagsType), m_enum(0) + { + } + + QString qualifiedTargetLangName() const; + QString targetLangName() const + { + return m_targetLangName; + } + QString targetLangApiName() const; + virtual bool preferredConversion() const + { + return false; + } + + QString originalName() const + { + return m_originalName; + } + void setOriginalName(const QString &s) + { + m_originalName = s; + } + + QString flagsName() const + { + return m_targetLangName; + } + void setFlagsName(const QString &name) + { + m_targetLangName = name; + } + + bool forceInteger() const + { + return m_enum->forceInteger(); + } + + EnumTypeEntry *originator() const + { + return m_enum; + } + void setOriginator(EnumTypeEntry *e) + { + m_enum = e; + } + + QString targetLangPackage() const + { + return m_enum->targetLangPackage(); + } + +private: + QString m_originalName; + QString m_targetLangName; + EnumTypeEntry *m_enum; +}; + + +class ComplexTypeEntry : public TypeEntry +{ +public: + enum TypeFlag { + ForceAbstract = 0x1, + DeleteInMainThread = 0x2, + Deprecated = 0x4 + }; + typedef QFlags<TypeFlag> TypeFlags; + + enum CopyableFlag { + CopyableSet, + NonCopyableSet, + Unknown + }; + + ComplexTypeEntry(const QString &name, Type t) + : TypeEntry(QString(name).replace(".*::", ""), t), + m_qualifiedCppName(name), + m_qobject(false), + m_polymorphicBase(false), + m_genericClass(false), + m_typeFlags(0), + m_copyableFlag(Unknown), + m_hashFunction("") + { + } + + bool isComplex() const + { + return true; + } + + IncludeList extraIncludes() const + { + return m_extraIncludes; + } + void setExtraIncludes(const IncludeList &includes) + { + m_extraIncludes = includes; + } + void addExtraInclude(const Include &include) + { + if (!m_includesUsed.value(include.name, false)) { + m_extraIncludes << include; + m_includesUsed[include.name] = true; + } + } + + ComplexTypeEntry *copy() const + { + ComplexTypeEntry *centry = new ComplexTypeEntry(name(), type()); + centry->setInclude(include()); + centry->setExtraIncludes(extraIncludes()); + centry->setFunctionModifications(functionModifications()); + centry->setFieldModifications(fieldModifications()); + centry->setQObject(isQObject()); + centry->setDefaultSuperclass(defaultSuperclass()); + centry->setCodeSnips(codeSnips()); + centry->setTargetLangPackage(targetLangPackage()); + + return centry; + } + + void setLookupName(const QString &name) + { + m_lookupName = name; + } + + virtual QString lookupName() const + { + return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; + } + + QString targetLangApiName() const + { + return strings_jobject; + } + + + Include include() const + { + return m_include; + } + void setInclude(const Include &inc) + { + m_include = inc; + } + + void setTypeFlags(TypeFlags flags) + { + m_typeFlags = flags; + } + + TypeFlags typeFlags() const + { + return m_typeFlags; + } + + FunctionModificationList functionModifications() const + { + return m_functionMods; + } + void setFunctionModifications(const FunctionModificationList &functionModifications) + { + m_functionMods = functionModifications; + } + void addFunctionModification(const FunctionModification &functionModification) + { + m_functionMods << functionModification; + } + FunctionModificationList functionModifications(const QString &signature) const; + + FieldModification fieldModification(const QString &name) const; + void setFieldModifications(const FieldModificationList &mods) + { + m_fieldMods = mods; + } + FieldModificationList fieldModifications() const + { + return m_fieldMods; + } + + QString targetLangPackage() const + { + return m_package; + } + void setTargetLangPackage(const QString &package) + { + m_package = package; + } + + bool isQObject() const + { + return m_qobject; + } + void setQObject(bool qobject) + { + m_qobject = qobject; + } + + QString defaultSuperclass() const + { + return m_defaultSuperclass; + } + void setDefaultSuperclass(const QString &sc) + { + m_defaultSuperclass = sc; + } + + virtual QString qualifiedCppName() const + { + return m_qualifiedCppName; + } + + + void setIsPolymorphicBase(bool on) + { + m_polymorphicBase = on; + } + bool isPolymorphicBase() const + { + return m_polymorphicBase; + } + + void setPolymorphicIdValue(const QString &value) + { + m_polymorphicIdValue = value; + } + QString polymorphicIdValue() const + { + return m_polymorphicIdValue; + } + + void setHeldType(const QString &value) + { + m_heldTypeValue = value; + } + QString heldTypeValue() const + { + return m_heldTypeValue; + } + + + void setExpensePolicy(const ExpensePolicy &policy) + { + m_expensePolicy = policy; + } + const ExpensePolicy &expensePolicy() const + { + return m_expensePolicy; + } + + QString targetType() const + { + return m_targetType; + } + void setTargetType(const QString &code) + { + m_targetType = code; + } + + QString targetLangName() const + { + return m_targetLangName.isEmpty() + ? TypeEntry::targetLangName() + : m_targetLangName; + } + void setTargetLangName(const QString &name) + { + m_targetLangName = name; + } + + bool isGenericClass() const + { + return m_genericClass; + } + void setGenericClass(bool isGeneric) + { + m_genericClass = isGeneric; + } + + CopyableFlag copyable() const + { + return m_copyableFlag; + } + void setCopyable(CopyableFlag flag) + { + m_copyableFlag = flag; + } + + QString hashFunction() const + { + return m_hashFunction; + } + void setHashFunction(QString hashFunction) + { + m_hashFunction = hashFunction; + } + + +private: + IncludeList m_extraIncludes; + Include m_include; + QHash<QString, bool> m_includesUsed; + FunctionModificationList m_functionMods; + FieldModificationList m_fieldMods; + QString m_package; + QString m_defaultSuperclass; + QString m_qualifiedCppName; + QString m_targetLangName; + + uint m_qobject : 1; + uint m_polymorphicBase : 1; + uint m_genericClass : 1; + + QString m_polymorphicIdValue; + QString m_heldTypeValue; + QString m_lookupName; + QString m_targetType; + ExpensePolicy m_expensePolicy; + TypeFlags m_typeFlags; + CopyableFlag m_copyableFlag; + QString m_hashFunction; +}; + +class ContainerTypeEntry : public ComplexTypeEntry +{ +public: + enum Type { + NoContainer, + ListContainer, + StringListContainer, + LinkedListContainer, + VectorContainer, + StackContainer, + QueueContainer, + SetContainer, + MapContainer, + MultiMapContainer, + HashContainer, + MultiHashContainer, + PairContainer, + }; + + ContainerTypeEntry(const QString &name, Type type) + : ComplexTypeEntry(name, ContainerType), m_type(type) + { + setCodeGeneration(GenerateForSubclass); + } + + Type type() const + { + return m_type; + } + QString targetLangName() const; + QString targetLangPackage() const; + QString qualifiedCppName() const; + + static Type containerTypeFromString(QString typeName) + { + static QHash<QString, Type> m_stringToContainerType; + if (m_stringToContainerType.isEmpty()) { + m_stringToContainerType["list"] = ListContainer; + m_stringToContainerType["string-list"] = StringListContainer; + m_stringToContainerType["linked-list"] = LinkedListContainer; + m_stringToContainerType["vector"] = VectorContainer; + m_stringToContainerType["stack"] = StackContainer; + m_stringToContainerType["queue"] = QueueContainer; + m_stringToContainerType["set"] = SetContainer; + m_stringToContainerType["map"] = MapContainer; + m_stringToContainerType["multi-map"] = MultiMapContainer; + m_stringToContainerType["hash"] = HashContainer; + m_stringToContainerType["multi-hash"] = MultiHashContainer; + m_stringToContainerType["pair"] = PairContainer; + } + return m_stringToContainerType.value(typeName, NoContainer); + } + +private: + Type m_type; +}; + + +class NamespaceTypeEntry : public ComplexTypeEntry +{ +public: + NamespaceTypeEntry(const QString &name) : ComplexTypeEntry(name, NamespaceType) { } +}; + + +class ValueTypeEntry : public ComplexTypeEntry +{ +public: + ValueTypeEntry(const QString &name) : ComplexTypeEntry(name, BasicValueType) { } + + bool isValue() const + { + return true; + } + + virtual bool isNativeIdBased() const + { + return true; + } + +protected: + ValueTypeEntry(const QString &name, Type t) : ComplexTypeEntry(name, t) { } +}; + + +class StringTypeEntry : public ValueTypeEntry +{ +public: + StringTypeEntry(const QString &name) + : ValueTypeEntry(name, StringType) + { + setCodeGeneration(GenerateNothing); + } + + QString targetLangApiName() const + { + return strings_jobject; + } + QString targetLangName() const + { + return strings_String; + } + QString targetLangPackage() const + { + return stringsJavaLang; + } + + virtual bool isNativeIdBased() const + { + return false; + } +}; + +class CharTypeEntry : public ValueTypeEntry +{ +public: + CharTypeEntry(const QString &name) : ValueTypeEntry(name, CharType) + { + setCodeGeneration(GenerateNothing); + } + + QString targetLangApiName() const + { + return strings_jchar; + } + QString targetLangName() const + { + return strings_char; + } + QString targetLangPackage() const + { + return QString(); + } + + virtual bool isNativeIdBased() const + { + return false; + } +}; + +class JObjectWrapperTypeEntry: public ValueTypeEntry +{ +public: + JObjectWrapperTypeEntry(const QString &name) : ValueTypeEntry(name, JObjectWrapperType) { } + + QString targetLangApiName() const + { + return strings_jobject; + } + QString targetLangName() const + { + return strings_Object; + } + QString targetLangPackage() const + { + return stringsJavaLang; + } + + bool isNativeIdBased() const + { + return false; + } +}; + +class VariantTypeEntry: public ValueTypeEntry +{ +public: + VariantTypeEntry(const QString &name) : ValueTypeEntry(name, VariantType) { } + + QString targetLangApiName() const + { + return strings_jobject; + } + QString targetLangName() const + { + return strings_Object; + } + QString targetLangPackage() const + { + return stringsJavaLang; + } + + virtual bool isNativeIdBased() const + { + return false; + } +}; + + +class InterfaceTypeEntry : public ComplexTypeEntry +{ +public: + InterfaceTypeEntry(const QString &name) + : ComplexTypeEntry(name, InterfaceType) {} + + static QString interfaceName(const QString &name) + { + return name + "Interface"; + } + + ObjectTypeEntry *origin() const + { + return m_origin; + } + void setOrigin(ObjectTypeEntry *origin) + { + m_origin = origin; + } + + virtual bool isNativeIdBased() const + { + return true; + } + virtual QString qualifiedCppName() const + { + return ComplexTypeEntry::qualifiedCppName().left(ComplexTypeEntry::qualifiedCppName().length() - interfaceName("").length()); + } + +private: + ObjectTypeEntry *m_origin; +}; + + +class ObjectTypeEntry : public ComplexTypeEntry +{ +public: + ObjectTypeEntry(const QString &name) + : ComplexTypeEntry(name, ObjectType), m_interface(0) {} + + InterfaceTypeEntry *designatedInterface() const + { + return m_interface; + } + void setDesignatedInterface(InterfaceTypeEntry *entry) + { + m_interface = entry; + } + + virtual bool isNativeIdBased() const + { + return true; + } + +private: + InterfaceTypeEntry *m_interface; +}; + +class CustomTypeEntry : public ComplexTypeEntry +{ +public: + CustomTypeEntry(const QString &name) : ComplexTypeEntry(name, CustomType) {} + + virtual void generateCppTargetLangToQt(QTextStream &s, + const AbstractMetaType* targetLangType, + const QString &envName, + const QString &qtName, + const QString &targetLangName) const = 0; + + virtual void generateCppQtToTargetLang(QTextStream &s, + const AbstractMetaType* targetLangType, + const QString &envName, + const QString &qtName, + const QString &targetLangName) const = 0; +}; + +struct TypeRejection +{ + QString class_name; + QString function_name; + QString field_name; + QString enum_name; +}; + +class TypeDatabase +{ +public: + TypeDatabase(); + + static TypeDatabase *instance(); + + QStringList requiredTargetImports() + { + return m_requiredTargetImports; + } + + void addRequiredTargetImport(const QString &moduleName) + { + if (!m_requiredTargetImports.contains(moduleName)) + m_requiredTargetImports << moduleName; + } + + QStringList typesystemPaths() + { + return m_typesystemPaths; + } + void addTypesystemPath(const QString &typesystem_paths) + { +#if defined(Q_OS_WIN32) + char *path_splitter = const_cast<char *>(";"); +#else + char *path_splitter = const_cast<char *>(":"); +#endif + m_typesystemPaths += typesystem_paths.split(path_splitter); + } + + IncludeList extraIncludes(const QString &className); + + inline PrimitiveTypeEntry *findPrimitiveType(const QString &name); + inline ComplexTypeEntry *findComplexType(const QString &name); + inline ObjectTypeEntry *findObjectType(const QString &name); + inline NamespaceTypeEntry *findNamespaceType(const QString &name); + ContainerTypeEntry *findContainerType(const QString &name); + + TypeEntry *findType(const QString &name) const + { + QList<TypeEntry *> entries = findTypes(name); + foreach (TypeEntry *entry, entries) { + if (entry && + (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) { + return entry; + } + } + return 0; + } + QList<TypeEntry *> findTypes(const QString &name) const + { + return m_entries.value(name); + } + TypeEntryHash allEntries() + { + return m_entries; + } + + SingleTypeEntryHash entries() + { + TypeEntryHash entries = allEntries(); + + SingleTypeEntryHash returned; + QList<QString> keys = entries.keys(); + + foreach (QString key, keys) + returned[key] = findType(key); + + return returned; + } + + PrimitiveTypeEntry *findTargetLangPrimitiveType(const QString &targetLangName); + + QList<const PrimitiveTypeEntry*> primitiveTypes() { + TypeEntryHash entries = allEntries(); + QList<const PrimitiveTypeEntry*> returned; + foreach(QString key, entries.keys()) { + foreach(const TypeEntry* typeEntry, entries[key]) { + if (typeEntry->isPrimitive()) + returned.append((PrimitiveTypeEntry*) typeEntry); + } + } + return returned; + } + QList<const ContainerTypeEntry*> containerTypes() { + TypeEntryHash entries = allEntries(); + QList<const ContainerTypeEntry*> returned; + foreach(QString key, entries.keys()) { + foreach(const TypeEntry* typeEntry, entries[key]) { + if (typeEntry->isContainer()) + returned.append((ContainerTypeEntry*) typeEntry); + } + } + return returned; + } + + void addRejection(const QString &class_name, const QString &function_name, + const QString &field_name, const QString &enum_name); + bool isClassRejected(const QString &class_name); + bool isFunctionRejected(const QString &class_name, const QString &function_name); + bool isFieldRejected(const QString &class_name, const QString &field_name); + bool isEnumRejected(const QString &class_name, const QString &enum_name); + + void addType(TypeEntry *e) + { + m_entries[e->qualifiedCppName()].append(e); + } + + SingleTypeEntryHash flagsEntries() const + { + return m_flagsEntries; + } + FlagsTypeEntry *findFlagsType(const QString &name) const; + void addFlagsType(FlagsTypeEntry *fte) + { + m_flagsEntries[fte->originalName()] = fte; + } + + TemplateEntry *findTemplate(const QString &name) + { + return m_templates[name]; + } + void addTemplate(TemplateEntry *t) + { + m_templates[t->name()] = t; + } + + void setSuppressWarnings(bool on) + { + m_suppressWarnings = on; + } + void addSuppressedWarning(const QString &s) + { + m_suppressedWarnings.append(s); + } + + bool isSuppressedWarning(const QString &s) + { + if (!m_suppressWarnings) + return false; + + foreach (const QString &_warning, m_suppressedWarnings) { + QString warning(QString(_warning).replace("\\*", "&place_holder_for_asterisk;")); + + QStringList segs = warning.split("*", QString::SkipEmptyParts); + if (!segs.size()) + continue; + + int i = 0; + int pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*")); + //qDebug() << "s == " << s << ", warning == " << segs; + while (pos != -1) { + if (i == segs.size()) + return true; + pos = s.indexOf(QString(segs.at(i++)).replace("&place_holder_for_asterisk;", "*"), pos); + } + } + + return false; + } + + void setRebuildClasses(const QStringList &cls) + { + m_rebuildClasses = cls; + } + + static QString globalNamespaceClassName(const TypeEntry *te); + QString filename() const + { + return "typesystem.txt"; + } + + QString modifiedTypesystemFilepath(const QString &ts_file); + bool parseFile(const QString &filename, bool generate = true); + bool parseFile(QIODevice* device, bool generate = true); + +private: + bool m_suppressWarnings; + TypeEntryHash m_entries; + SingleTypeEntryHash m_flagsEntries; + TemplateEntryHash m_templates; + QStringList m_suppressedWarnings; + + QStringList m_requiredTargetImports; + + QStringList m_typesystemPaths; + QHash<QString, bool> m_parsedTypesystemFiles; + + QList<TypeRejection> m_rejections; + QStringList m_rebuildClasses; +}; + +inline PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString &name) +{ + QList<TypeEntry *> entries = findTypes(name); + + foreach (TypeEntry *entry, entries) { + if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType()) + return static_cast<PrimitiveTypeEntry *>(entry); + } + + return 0; +} + +inline ComplexTypeEntry *TypeDatabase::findComplexType(const QString &name) +{ + TypeEntry *entry = findType(name); + if (entry && entry->isComplex()) + return static_cast<ComplexTypeEntry *>(entry); + else + return 0; +} + +inline ObjectTypeEntry *TypeDatabase::findObjectType(const QString &name) +{ + TypeEntry *entry = findType(name); + if (entry && entry->isObject()) + return static_cast<ObjectTypeEntry *>(entry); + else + return 0; +} + +inline NamespaceTypeEntry *TypeDatabase::findNamespaceType(const QString &name) +{ + TypeEntry *entry = findType(name); + if (entry && entry->isNamespace()) + return static_cast<NamespaceTypeEntry *>(entry); + else + return 0; +} + +QString fixCppTypeName(const QString &name); + +#endif // TYPESYSTEM_H |