/generator/typesystem.cpp
C++ | 1618 lines | 1349 code | 204 blank | 65 comment | 319 complexity | cf3c7f87276144fc5b604834391c9a45 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /****************************************************************************
- **
- ** Copyright (C) 1992-2008 Nokia. All rights reserved.
- **
- ** This file is part of Qt Jambi.
- **
- ** * Commercial Usage
- * Licensees holding valid Qt Commercial licenses may use this file in
- * accordance with the Qt Commercial License Agreement provided with the
- * Software or, alternatively, in accordance with the terms contained in
- * a written agreement between you and Nokia.
- *
- *
- * GNU General Public License Usage
- * Alternatively, this file may be used under the terms of the GNU
- * General Public License versions 2.0 or 3.0 as published by the Free
- * Software Foundation and appearing in the file LICENSE.GPL included in
- * the packaging of this file. Please review the following information
- * to ensure GNU General Public Licensing requirements will be met:
- * http://www.fsf.org/licensing/licenses/info/GPLv2.html and
- * http://www.gnu.org/copyleft/gpl.html. In addition, as a special
- * exception, Nokia gives you certain additional rights. These rights
- * are described in the Nokia Qt GPL Exception version 1.2, included in
- * the file GPL_EXCEPTION.txt in this package.
- *
- * Qt for Windows(R) Licensees
- * As a special exception, Nokia, as the sole copyright holder for Qt
- * Designer, grants users of the Qt/Eclipse Integration plug-in the
- * right for the Qt/Eclipse Integration to link to functionality
- * provided by Qt Designer and its related libraries.
- *
- *
- * If you are unsure which license is appropriate for your use, please
- * contact the sales department at qt-sales@nokia.com.
- **
- ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- **
- ****************************************************************************/
- #include "typesystem.h"
- #include "generator.h"
- #include "customtypes.h"
- #include <reporthandler.h>
- #include <QtXml>
- QString strings_Object = QLatin1String("Object");
- QString strings_String = QLatin1String("string");
- QString strings_Thread = QLatin1String("Thread");
- QString strings_char = QLatin1String("char");
- QString strings_java_lang = QLatin1String("java.lang");
- QString strings_jchar = QLatin1String("jchar");
- QString strings_jobject = QLatin1String("jobject");
- static void addRemoveFunctionToTemplates(TypeDatabase *db);
- class StackElement
- {
- public:
- enum ElementType {
- None = 0x0,
- // Type tags (0x1, ... , 0xff)
- ObjectTypeEntry = 0x1,
- ValueTypeEntry = 0x2,
- InterfaceTypeEntry = 0x3,
- NamespaceTypeEntry = 0x4,
- ComplexTypeEntryMask = 0xf,
- // Non-complex type tags (0x10, 0x20, ... , 0xf0)
- PrimitiveTypeEntry = 0x10,
- EnumTypeEntry = 0x20,
- TypeEntryMask = 0xff,
- // Simple tags (0x100, 0x200, ... , 0xf00)
- ExtraIncludes = 0x100,
- Include = 0x200,
- ModifyFunction = 0x300,
- ModifyField = 0x400,
- Root = 0x500,
- CustomMetaConstructor = 0x600,
- CustomMetaDestructor = 0x700,
- ArgumentMap = 0x800,
- SuppressedWarning = 0x900,
- Rejection = 0xa00,
- LoadTypesystem = 0xb00,
- RejectEnumValue = 0xc00,
- Template = 0xd00,
- TemplateInstanceEnum = 0xe00,
- Replace = 0xf00,
- SimpleMask = 0xf00,
- // qtd stuff
- AddClass = 0x1100,
- // Code snip tags (0x1000, 0x2000, ... , 0xf000)
- InjectCode = 0x1000,
- InjectCodeInFunction = 0x2000,
- CodeSnipMask = 0xf000,
- // Function modifier tags (0x010000, 0x020000, ... , 0xf00000)
- Access = 0x010000,
- Removal = 0x020000,
- Rename = 0x040000,
- ModifyArgument = 0x080000,
- FunctionModifiers = 0xff0000,
- StoreResult = 0x110000,
- // Argument modifier tags (0x01000000 ... 0xf0000000)
- ConversionRule = 0x01000000,
- ReplaceType = 0x02000000,
- ReplaceDefaultExpression = 0x04000000,
- RemoveArgument = 0x08000000,
- DefineOwnership = 0x10000000,
- RemoveDefaultExpression = 0x20000000,
- NoNullPointers = 0x40000000,
- ReferenceCount = 0x80000000,
- ArgumentModifiers = 0xff000000
- };
- StackElement(StackElement *p) : entry(0), type(None), parent(p){ }
- TypeEntry *entry;
- ElementType type;
- StackElement *parent;
- union {
- TemplateInstance *templateInstance;
- TemplateEntry *templateEntry;
- CustomFunction *customFunction;
- } value;
- };
- class Handler : public QXmlDefaultHandler
- {
- public:
- Handler(TypeDatabase *database, bool generate)
- : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass)
- {
- m_current_enum = 0;
- current = 0;
- tagNames["rejection"] = StackElement::Rejection;
- tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry;
- tagNames["object-type"] = StackElement::ObjectTypeEntry;
- tagNames["value-type"] = StackElement::ValueTypeEntry;
- tagNames["interface-type"] = StackElement::InterfaceTypeEntry;
- tagNames["namespace-type"] = StackElement::NamespaceTypeEntry;
- tagNames["enum-type"] = StackElement::EnumTypeEntry;
- tagNames["extra-includes"] = StackElement::ExtraIncludes;
- tagNames["include"] = StackElement::Include;
- tagNames["inject-code"] = StackElement::InjectCode;
- tagNames["modify-function"] = StackElement::ModifyFunction;
- tagNames["modify-field"] = StackElement::ModifyField;
- tagNames["access"] = StackElement::Access;
- tagNames["remove"] = StackElement::Removal;
- tagNames["rename"] = StackElement::Rename;
- tagNames["typesystem"] = StackElement::Root;
- tagNames["custom-constructor"] = StackElement::CustomMetaConstructor;
- tagNames["custom-destructor"] = StackElement::CustomMetaDestructor;
- tagNames["argument-map"] = StackElement::ArgumentMap;
- tagNames["suppress-warning"] = StackElement::SuppressedWarning;
- tagNames["load-typesystem"] = StackElement::LoadTypesystem;
- tagNames["define-ownership"] = StackElement::DefineOwnership;
- tagNames["replace-default-expression"] = StackElement::ReplaceDefaultExpression;
- tagNames["reject-enum-value"] = StackElement::RejectEnumValue;
- tagNames["replace-type"] = StackElement::ReplaceType;
- tagNames["conversion-rule"] = StackElement::ConversionRule;
- tagNames["modify-argument"] = StackElement::ModifyArgument;
- tagNames["remove-argument"] = StackElement::RemoveArgument;
- tagNames["remove-default-expression"] = StackElement::RemoveDefaultExpression;
- tagNames["template"] = StackElement::Template;
- tagNames["insert-template"] = StackElement::TemplateInstanceEnum;
- tagNames["replace"] = StackElement::Replace;
- tagNames["no-null-pointer"] = StackElement::NoNullPointers;
- tagNames["reference-count"] = StackElement::ReferenceCount;
- // qtd
- tagNames["add-class"] = StackElement::AddClass;
- tagNames["store-result"] = StackElement::StoreResult;
- }
- bool startElement(const QString &namespaceURI, const QString &localName,
- const QString &qName, const QXmlAttributes &atts);
- bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
- QString errorString() const { return m_error; }
- bool error(const QXmlParseException &exception);
- bool fatalError(const QXmlParseException &exception);
- bool warning(const QXmlParseException &exception);
- bool characters(const QString &ch);
- private:
- void fetchAttributeValues(const QString &name, const QXmlAttributes &atts,
- QHash<QString, QString> *acceptedAttributes);
- bool importFileElement(const QXmlAttributes &atts);
- bool convertBoolean(const QString &, const QString &, bool);
- TypeDatabase *m_database;
- StackElement* current;
- QString m_defaultPackage;
- QString m_defaultSuperclass;
- QString m_error;
- TypeEntry::CodeGeneration m_generate;
- EnumTypeEntry *m_current_enum;
- CodeSnipList m_code_snips;
- FunctionModificationList m_function_mods;
- FieldModificationList m_field_mods;
- QHash<QString, StackElement::ElementType> tagNames;
- };
- bool Handler::error(const QXmlParseException &e)
- {
- qWarning("Error: line=%d, column=%d, message=%s\n",
- e.lineNumber(), e.columnNumber(), qPrintable(e.message()));
- return false;
- }
- bool Handler::fatalError(const QXmlParseException &e)
- {
- qWarning("Fatal error: line=%d, column=%d, message=%s\n",
- e.lineNumber(), e.columnNumber(), qPrintable(e.message()));
- return false;
- }
- bool Handler::warning(const QXmlParseException &e)
- {
- qWarning("Warning: line=%d, column=%d, message=%s\n",
- e.lineNumber(), e.columnNumber(), qPrintable(e.message()));
- return false;
- }
- void Handler::fetchAttributeValues(const QString &name, const QXmlAttributes &atts,
- QHash<QString, QString> *acceptedAttributes)
- {
- Q_ASSERT(acceptedAttributes != 0);
- for (int i=0; i<atts.length(); ++i) {
- QString key = atts.localName(i).toLower();
- QString val = atts.value(i);
- if (!acceptedAttributes->contains(key)) {
- ReportHandler::warning(QString("Unknown attribute for '%1': '%2'").arg(name).arg(key));
- } else {
- (*acceptedAttributes)[key] = val;
- }
- }
- }
- bool Handler::endElement(const QString &, const QString &localName, const QString &)
- {
- QString tagName = localName.toLower();
- if(tagName == "import-file")
- return true;
- if (!current)
- return true;
- switch (current->type) {
- case StackElement::ObjectTypeEntry:
- case StackElement::ValueTypeEntry:
- case StackElement::InterfaceTypeEntry:
- case StackElement::NamespaceTypeEntry:
- {
- ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(current->entry);
- centry->setFunctionModifications(m_function_mods);
- centry->setFieldModifications(m_field_mods);
- centry->setCodeSnips(m_code_snips);
- if (centry->designatedInterface()) {
- centry->designatedInterface()->setCodeSnips(m_code_snips);
- centry->designatedInterface()->setFunctionModifications(m_function_mods);
- }
- m_code_snips = CodeSnipList();
- m_function_mods = FunctionModificationList();
- m_field_mods = FieldModificationList();
- }
- break;
- case StackElement::CustomMetaConstructor:
- {
- current->entry->setCustomConstructor(*current->value.customFunction);
- delete current->value.customFunction;
- }
- break;
- case StackElement::CustomMetaDestructor:
- {
- current->entry->setCustomDestructor(*current->value.customFunction);
- delete current->value.customFunction;
- }
- break;
- case StackElement::EnumTypeEntry:
- m_current_enum = 0;
- break;
- case StackElement::Template:
- m_database->addTemplate(current->value.templateEntry);
- break;
- case StackElement::TemplateInstanceEnum:
- if(current->parent->type == StackElement::InjectCode){
- m_code_snips.last().addTemplateInstance(current->value.templateInstance);
- }else if(current->parent->type == StackElement::Template){
- current->parent->value.templateEntry->addTemplateInstance(current->value.templateInstance);
- }else if(current->parent->type == StackElement::CustomMetaConstructor || current->parent->type == StackElement::CustomMetaConstructor){
- current->parent->value.customFunction->addTemplateInstance(current->value.templateInstance);
- }else if(current->parent->type == StackElement::ConversionRule){
- m_function_mods.last().argument_mods.last().conversion_rules.last().addTemplateInstance(current->value.templateInstance);
- }else if(current->parent->type == StackElement::InjectCodeInFunction){
- m_function_mods.last().snips.last().addTemplateInstance(current->value.templateInstance);
- }
- break;
- default:
- break;
- }
- StackElement *child = current;
- current=current->parent;
- delete(child);
- return true;
- }
- bool Handler::characters(const QString &ch)
- {
- if(current->type == StackElement::Template){
- current->value.templateEntry->addCode(ch);
- return true;
- }
- if (current->type == StackElement::CustomMetaConstructor || current->type == StackElement::CustomMetaDestructor){
- current->value.customFunction->addCode(ch);
- return true;
- }
- if (current->type == StackElement::ConversionRule){
- m_function_mods.last().argument_mods.last().conversion_rules.last().addCode(ch);
- return true;
- }
- if (current->parent){
- if ((current->type & StackElement::CodeSnipMask) != 0) {
- switch (current->parent->type) {
- case StackElement::Root:
- ((TypeSystemTypeEntry *) current->parent->entry)->snips.last().addCode(ch);
- break;
- case StackElement::ModifyFunction:
- m_function_mods.last().snips.last().addCode(ch);
- break;
- case StackElement::NamespaceTypeEntry:
- case StackElement::ObjectTypeEntry:
- case StackElement::ValueTypeEntry:
- case StackElement::InterfaceTypeEntry:
- m_code_snips.last().addCode(ch);
- break;
- default:
- Q_ASSERT(false);
- };
- return true;
- }
- }
- return true;
- }
- bool Handler::importFileElement(const QXmlAttributes &atts)
- {
- QString fileName = atts.value("name");
- if(fileName.isEmpty()){
- m_error = "Required attribute 'name' missing for include-file tag.";
- return false;
- }
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- file.setFileName(":/trolltech/generator/" + fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- m_error = QString("Could not open file: '%1'").arg(fileName);
- return false;
- }
- }
- QString quoteFrom = atts.value("quote-after-line");
- bool foundFromOk = quoteFrom.isEmpty();
- bool from = quoteFrom.isEmpty();
- QString quoteTo = atts.value("quote-before-line");
- bool foundToOk = quoteTo.isEmpty();
- bool to = true;
- QTextStream in(&file);
- while (!in.atEnd()) {
- QString line = in.readLine();
- if(from && to && line.contains(quoteTo)) {
- to = false;
- foundToOk = true;
- break;
- }
- if(from && to)
- characters(line + "\n");
- if(!from && line.contains(quoteFrom)) {
- from = true;
- foundFromOk = true;
- }
- }
- if(!foundFromOk || !foundToOk){
- QString fromError = QString("Could not find quote-after-line='%1' in file '%2'.").arg(quoteFrom).arg(fileName);
- QString toError = QString("Could not find quote-before-line='%1' in file '%2'.").arg(quoteTo).arg(fileName);
- if(!foundToOk)
- m_error = toError;
- if(!foundFromOk)
- m_error = fromError;
- if(!foundFromOk && !foundToOk)
- m_error = fromError + " " + toError;
- return false;
- }
- return true;
- }
- bool Handler::convertBoolean(const QString &_value, const QString &attributeName, bool defaultValue)
- {
- QString value = _value.toLower();
- if (value == "true" || value == "yes") {
- return true;
- } else if (value == "false" || value == "no") {
- return false;
- } else {
- QString warn = QString("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.")
- .arg(value).arg(attributeName).arg(defaultValue ? "yes" : "no");
- ReportHandler::warning(warn);
- return defaultValue;
- }
- }
- bool Handler::startElement(const QString &, const QString &n,
- const QString &, const QXmlAttributes &atts)
- {
- QString tagName = n.toLower();
- if(tagName == "import-file"){
- return importFileElement(atts);
- }
- StackElement *element = new StackElement(current);
- if (!tagNames.contains(tagName)) {
- m_error = QString("Unknown tag name: '%1'").arg(tagName);
- return false;
- }
- element->type = tagNames[tagName];
- if (element->type & StackElement::TypeEntryMask) {
- if (current->type != StackElement::Root) {
- m_error = "Nested types not supported";
- return false;
- }
- QHash<QString, QString> attributes;
- attributes["name"] = QString();
- switch (element->type) {
- case StackElement::PrimitiveTypeEntry:
- attributes["java-name"] = QString();
- attributes["jni-name"] = QString();
- attributes["preferred-conversion"] = "yes";
- attributes["preferred-java-type"] = "yes";
- break;
- case StackElement::EnumTypeEntry:
- attributes["flags"] = "no";
- attributes["upper-bound"] = QString();
- attributes["lower-bound"] = QString();
- attributes["force-integer"] = "no";
- attributes["extensible"] = "no";
- break;
- case StackElement::ObjectTypeEntry:
- case StackElement::ValueTypeEntry:
- attributes["force-abstract"] = QString("no");
- attributes["deprecated"] = QString("no");
- attributes["wrap"] = QString();
- // fall throooough
- case StackElement::InterfaceTypeEntry:
- attributes["default-superclass"] = m_defaultSuperclass;
- attributes["polymorphic-id-expression"] = QString();
- attributes["delete-in-main-thread"] = QString("no");
- // fall through
- case StackElement::NamespaceTypeEntry:
- attributes["java-name"] = QString();
- attributes["package"] = m_defaultPackage;
- attributes["expense-cost"] = "1";
- attributes["expense-limit"] = "none";
- attributes["polymorphic-base"] = QString("no");
- attributes["generate"] = QString("yes");
- attributes["target-type"] = QString();
- attributes["generic-class"] = QString("no");
- break;
- default:
- ; // nada
- };
- fetchAttributeValues(tagName, atts, &attributes);
- QString name = attributes["name"];
- // We need to be able to have duplicate primitive type entries, or it's not possible to
- // cover all primitive java types (which we need to do in order to support fake
- // meta objects)
- if (element->type != StackElement::PrimitiveTypeEntry) {
- TypeEntry *tmp = m_database->findType(name);
- if (tmp != 0) {
- ReportHandler::warning(QString("Duplicate type entry: '%1'").arg(name));
- }
- }
- if (name.isEmpty()) {
- m_error = "no 'name' attribute specified";
- return false;
- }
- switch (element->type) {
- case StackElement::PrimitiveTypeEntry:
- {
- QString java_name = attributes["java-name"];
- QString jni_name = attributes["jni-name"];
- QString preferred_conversion = attributes["preferred-conversion"].toLower();
- QString preferred_java_type = attributes["preferred-java-type"].toLower();
- if (java_name.isEmpty())
- java_name = name;
- if (jni_name.isEmpty())
- jni_name = name;
- PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name);
- type->setCodeGeneration(m_generate);
- type->setTargetLangName(java_name);
- type->setJniName(jni_name);
- type->setPreferredConversion(convertBoolean(preferred_conversion, "preferred-conversion", true));
- type->setPreferredTargetLangType(convertBoolean(preferred_java_type, "preferred-java-type", true));
- element->entry = type;
- }
- break;
- case StackElement::EnumTypeEntry: {
- QStringList names = name.split(QLatin1String("::"));
- if (names.size() == 1) {
- m_current_enum = new EnumTypeEntry(QString(), name);
- }
- else
- m_current_enum =
- new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join("::"),
- names.last());
- element->entry = m_current_enum;
- m_current_enum->setCodeGeneration(m_generate);
- m_current_enum->setTargetLangPackage(m_defaultPackage);
- m_current_enum->setUpperBound(attributes["upper-bound"]);
- m_current_enum->setLowerBound(attributes["lower-bound"]);
- m_current_enum->setForceInteger(convertBoolean(attributes["force-integer"], "force-integer", false));
- m_current_enum->setExtensible(convertBoolean(attributes["extensible"], "extensible", false));
- // put in the flags parallel...
- if (!attributes["flags"].isEmpty() && attributes["flags"].toLower() != "no") {
- FlagsTypeEntry *ftype = new FlagsTypeEntry("QFlags<" + name + ">");
- ftype->setOriginator(m_current_enum);
- ftype->setOriginalName(attributes["flags"]);
- ftype->setCodeGeneration(m_generate);
- QString n = ftype->originalName();
- QStringList lst = n.split("::");
- if (QStringList(lst.mid(0, lst.size() - 1)).join("::") != m_current_enum->javaQualifier()) {
- ReportHandler::warning(QString("enum %1 and flags %2 differ in qualifiers")
- .arg(m_current_enum->javaQualifier())
- .arg(lst.at(0)));
- }
- ftype->setFlagsName(lst.last());
- m_current_enum->setFlags(ftype);
- m_database->addFlagsType(ftype);
- m_database->addType(ftype);
- }
- }
- break;
- case StackElement::InterfaceTypeEntry:
- {
- ObjectTypeEntry *otype = new ObjectTypeEntry(name);
- QString javaName = attributes["java-name"];
- if (javaName.isEmpty())
- javaName = name;
- InterfaceTypeEntry *itype =
- new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(javaName));
- if (!convertBoolean(attributes["generate"], "generate", true))
- itype->setCodeGeneration(TypeEntry::GenerateForSubclass);
- else
- itype->setCodeGeneration(m_generate);
- otype->setDesignatedInterface(itype);
- itype->setOrigin(otype);
- element->entry = otype;
- }
- // fall through
- case StackElement::NamespaceTypeEntry:
- if (element->entry == 0) {
- element->entry = new NamespaceTypeEntry(name);
- }
- // fall through
- case StackElement::ObjectTypeEntry:
- if (element->entry == 0) {
- element->entry = new ObjectTypeEntry(name);
- }
- // fall through
- case StackElement::ValueTypeEntry:
- {
- if (element->entry == 0) {
- if(name == "QVariant")
- element->entry = new VariantTypeEntry(name);
- else
- element->entry = new ValueTypeEntry(name);
- }
- ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry);
- ctype->setTargetLangPackage(attributes["package"]);
- ctype->setDefaultSuperclass(attributes["default-superclass"]);
- ctype->setGenericClass(convertBoolean(attributes["generic-class"], "generic-class", false));
- // qtd
- QString wrap = attributes["wrap"];
- ctype->setStructInD(wrap == "struct" ? true : false);
- //
- if (!convertBoolean(attributes["generate"], "generate", true))
- element->entry->setCodeGeneration(TypeEntry::GenerateForSubclass);
- else
- element->entry->setCodeGeneration(m_generate);
- QString javaName = attributes["java-name"];
- if (!javaName.isEmpty())
- ctype->setTargetLangName(javaName);
- // The expense policy
- QString limit = attributes["expense-limit"];
- if (!limit.isEmpty() && limit != "none") {
- ExpensePolicy ep;
- ep.limit = limit.toInt();
- ep.cost = attributes["expense-cost"];
- ctype->setExpensePolicy(ep);
- }
- ctype->setIsPolymorphicBase(convertBoolean(attributes["polymorphic-base"], "polymorphic-base", false));
- ctype->setPolymorphicIdValue(attributes["polymorphic-id-expression"]);
- if (element->type == StackElement::ObjectTypeEntry || element->type == StackElement::ValueTypeEntry) {
- if (convertBoolean(attributes["force-abstract"], "force-abstract", false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract);
- if (convertBoolean(attributes["deprecated"], "deprecated", false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated);
- }
- if (element->type == StackElement::InterfaceTypeEntry ||
- element->type == StackElement::ValueTypeEntry ||
- element->type == StackElement::ObjectTypeEntry) {
- if (convertBoolean(attributes["delete-in-main-thread"], "delete-in-main-thread", false))
- ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread);
- }
- QString targetType = attributes["target-type"];
- if (!targetType.isEmpty() && element->entry->isComplex())
- static_cast<ComplexTypeEntry *>(element->entry)->setTargetType(targetType);
- // ctype->setInclude(Include(Include::IncludePath, ctype->name()));
- ctype = ctype->designatedInterface();
- if (ctype != 0)
- ctype->setTargetLangPackage(attributes["package"]);
- }
- break;
- default:
- Q_ASSERT(false);
- };
- if (element->entry)
- m_database->addType(element->entry);
- else
- ReportHandler::warning(QString("Type: %1 was rejected by typesystem").arg(name));
- } else if (element->type != StackElement::None) {
- bool topLevel = element->type == StackElement::Root
- || element->type == StackElement::SuppressedWarning
- || element->type == StackElement::Rejection
- || element->type == StackElement::LoadTypesystem
- || element->type == StackElement::InjectCode
- || element->type == StackElement::Template;
- if (!topLevel && current->type == StackElement::Root) {
- m_error = QString("Tag requires parent: '%1'").arg(tagName);
- return false;
- }
- StackElement topElement = current==0 ? StackElement(0) : *current;
- element->entry = topElement.entry;
- QHash<QString, QString> attributes;
- switch (element->type) {
- case StackElement::Root:
- attributes["package"] = QString();
- attributes["default-superclass"] = QString();
- break;
- case StackElement::LoadTypesystem:
- attributes["name"] = QString();
- attributes["generate"] = "yes";
- break;
- case StackElement::NoNullPointers:
- attributes["default-value"] = QString();
- break;
- case StackElement::SuppressedWarning:
- attributes["text"] = QString();
- break;
- case StackElement::ReplaceDefaultExpression:
- attributes["with"] = QString();
- break;
- case StackElement::DefineOwnership:
- attributes["class"] = "java";
- attributes["owner"] = "";
- break;
- case StackElement::ModifyFunction:
- attributes["signature"] = QString();
- attributes["access"] = QString();
- attributes["remove"] = QString();
- attributes["rename"] = QString();
- attributes["deprecated"] = QString("no");
- attributes["associated-to"] = QString();
- attributes["virtual-slot"] = QString("no");
- break;
- case StackElement::ModifyArgument:
- attributes["index"] = QString();
- attributes["replace-value"] = QString();
- attributes["invalidate-after-use"] = QString("no");
- break;
- case StackElement::ModifyField:
- attributes["name"] = QString();
- attributes["write"] = "true";
- attributes["read"] = "true";
- break;
- case StackElement::Access:
- attributes["modifier"] = QString();
- break;
- case StackElement::Include:
- attributes["file-name"] = QString();
- attributes["location"] = QString();
- break;
- case StackElement::CustomMetaConstructor:
- attributes["name"] = topElement.entry->name().toLower() + "_create";
- attributes["param-name"] = "copy";
- break;
- case StackElement::CustomMetaDestructor:
- attributes["name"] = topElement.entry->name().toLower() + "_delete";
- attributes["param-name"] = "copy";
- break;
- case StackElement::ReplaceType:
- attributes["modified-type"] = QString();
- break;
- case StackElement::InjectCode:
- attributes["class"] = "java";
- attributes["position"] = "beginning";
- break;
- case StackElement::ConversionRule:
- attributes["class"] = "";
- break;
- case StackElement::RejectEnumValue:
- attributes["name"] = "";
- break;
- case StackElement::ArgumentMap:
- attributes["index"] = "1";
- attributes["meta-name"] = QString();
- break;
- case StackElement::Rename:
- attributes["to"] = QString();
- break;
- case StackElement::Rejection:
- attributes["class"] = "*";
- attributes["function-name"] = "*";
- attributes["field-name"] = "*";
- attributes["enum-name"] = "*";
- break;
- case StackElement::Removal:
- attributes["class"] = "all";
- break;
- case StackElement::Template:
- attributes["name"] = QString();
- break;
- case StackElement::TemplateInstanceEnum:
- attributes["name"] = QString();
- break;
- case StackElement::Replace:
- attributes["from"] = QString();
- attributes["to"] = QString();
- break;
- case StackElement::ReferenceCount:
- attributes["action"] = QString();
- attributes["variable-name"] = QString();
- attributes["thread-safe"] = QString("no");
- attributes["declare-variable"] = QString();
- attributes["access"] = QString("private");
- attributes["conditional"] = QString("");
- break;
- // qtd
- case StackElement::AddClass:
- attributes["name"] = QString();
- break;
- default:
- ; // nada
- };
- if (attributes.count() > 0)
- fetchAttributeValues(tagName, atts, &attributes);
- switch (element->type) {
- case StackElement::Root:
- m_defaultPackage = attributes["package"];
- m_defaultSuperclass = attributes["default-superclass"];
- element->type = StackElement::Root;
- element->entry = new TypeSystemTypeEntry(m_defaultPackage);
- TypeDatabase::instance()->addType(element->entry);
- break;
- case StackElement::LoadTypesystem:
- {
- QString name = attributes["name"];
- if (name.isEmpty()) {
- m_error = "No typesystem name specified";
- return false;
- }
- if (!m_database->parseFile(name, convertBoolean(attributes["generate"], "generate", true))) {
- m_error = QString("Failed to parse: '%1'").arg(name);
- return false;
- }
- }
- break;
- case StackElement::RejectEnumValue: {
- if (!m_current_enum) {
- m_error = "<reject-enum-value> node must be used inside a <enum-type> node";
- return false;
- }
- QString name = attributes["name"];
- bool added = false;
- if (!name.isEmpty()) {
- added = true;
- m_current_enum->addEnumValueRejection(name);
- }
- } break;
- case StackElement::ReplaceType:
- {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = "Type replacement can only be specified for argument modifications";
- return false;
- }
- if (attributes["modified-type"].isEmpty()) {
- m_error = "Type replacement requires 'modified-type' attribute";
- return false;
- }
- m_function_mods.last().argument_mods.last().modified_type = attributes["modified-type"];
- }
- break;
- case StackElement::ConversionRule:
- {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = "Conversion rules can only be specified for argument modification";
- return false;
- }
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames["native"] = TypeSystem::NativeCode;
- languageNames["shell"] = TypeSystem::ShellCode;
- }
- CodeSnip snip;
- QString languageAttribute = attributes["class"].toLower();
- TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QString("unsupported class attribute: '%1'").arg(languageAttribute);
- return false;
- }
- snip.language = lang;
- m_function_mods.last().argument_mods.last().conversion_rules.append(snip);
- }
- break;
- case StackElement::StoreResult:
- {
- if (topElement.type != StackElement::ModifyFunction) {
- m_error = QString::fromLatin1("result storage requires function"
- " modification as parent, was %1")
- .arg(topElement.type, 0, 16);
- return false;
- }
- m_function_mods.last().store_result = true;
- }
- break;
- case StackElement::ModifyArgument:
- {
- if (topElement.type != StackElement::ModifyFunction) {
- m_error = QString::fromLatin1("argument modification requires function"
- " modification as parent, was %1")
- .arg(topElement.type, 0, 16);
- return false;
- }
- QString index = attributes["index"];
- if (index == "return")
- index = "0";
- else if (index == "this")
- index = "-1";
- bool ok = false;
- int idx = index.toInt(&ok);
- if (!ok) {
- m_error = QString("Cannot convert '%1' to integer").arg(index);
- return false;
- }
- QString replace_value = attributes["replace-value"];
- if (!replace_value.isEmpty() && idx != 0) {
- m_error = QString("replace-value is only supported for return values (index=0).");
- return false;
- }
- ArgumentModification argumentModification = ArgumentModification(idx);
- argumentModification.replace_value = replace_value;
- argumentModification.reset_after_use = convertBoolean(attributes["invalidate-after-use"], "invalidate-after-use", false);
- m_function_mods.last().argument_mods.append(argumentModification);
- }
- break;
- case StackElement::NoNullPointers:
- {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = "no-null-pointer requires argument modification as parent";
- return false;
- }
- m_function_mods.last().argument_mods.last().no_null_pointers = true;
- if (m_function_mods.last().argument_mods.last().index == 0) {
- m_function_mods.last().argument_mods.last().null_pointer_default_value = attributes["default-value"];
- } else if (!attributes["default-value"].isEmpty()) {
- ReportHandler::warning("default values for null pointer guards are only effective for return values");
- }
- }
- break;
- case StackElement::DefineOwnership:
- {
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = "define-ownership requires argument modification as parent";
- return false;
- }
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames["java"] = TypeSystem::TargetLangCode;
- languageNames["shell"] = TypeSystem::ShellCode;
- }
- QString classAttribute = attributes["class"].toLower();
- TypeSystem::Language lang = languageNames.value(classAttribute, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QString("unsupported class attribute: '%1'").arg(classAttribute);
- return false;
- }
- static QHash<QString, TypeSystem::Ownership> ownershipNames;
- if (ownershipNames.isEmpty()) {
- ownershipNames["java"] = TypeSystem::TargetLangOwnership;
- ownershipNames["c++"] = TypeSystem::CppOwnership;
- ownershipNames["default"] = TypeSystem::DefaultOwnership;
- }
- QString ownershipAttribute = attributes["owner"].toLower();
- TypeSystem::Ownership owner = ownershipNames.value(ownershipAttribute, TypeSystem::InvalidOwnership);
- if (owner == TypeSystem::InvalidOwnership) {
- m_error = QString("unsupported owner attribute: '%1'").arg(ownershipAttribute);
- return false;
- }
- m_function_mods.last().argument_mods.last().ownerships[lang] = owner;
- }
- break;
- case StackElement::SuppressedWarning:
- if (attributes["text"].isEmpty())
- ReportHandler::warning("Suppressed warning with no text specified");
- else
- m_database->addSuppressedWarning(attributes["text"]);
- break;
- case StackElement::ArgumentMap:
- {
- if (!(topElement.type & StackElement::CodeSnipMask)) {
- m_error = "Argument maps requires code injection as parent";
- return false;
- }
- bool ok;
- int pos = attributes["index"].toInt(&ok);
- if (!ok) {
- m_error = QString("Can't convert position '%1' to integer")
- .arg(attributes["position"]);
- return false;
- }
- if (pos <= 0) {
- m_error = QString("Argument position %1 must be a positive number").arg(pos);
- return false;
- }
- QString meta_name = attributes["meta-name"];
- if (meta_name.isEmpty()) {
- ReportHandler::warning("Empty meta name in argument map");
- }
- if (topElement.type == StackElement::InjectCodeInFunction) {
- m_function_mods.last().snips.last().argumentMap[pos] = meta_name;
- } else {
- ReportHandler::warning("Argument maps are only useful for injection of code "
- "into functions.");
- }
- }
- break;
- case StackElement::Removal:
- {
- if (topElement.type != StackElement::ModifyFunction) {
- m_error = "Function modification parent required";
- return false;
- }
- static QHash<QString, TypeSystem::Language> languageNames;
- if (languageNames.isEmpty()) {
- languageNames["java"] = TypeSystem::TargetLangAndNativeCode;
- languageNames["all"] = TypeSystem::All;
- }
- QString languageAttribute = attributes["class"].toLower();
- TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage);
- if (lang == TypeSystem::NoLanguage) {
- m_error = QString("unsupported class attribute: '%1'").arg(languageAttribute);
- return false;
- }
- m_function_mods.last().removal = lang;
- }
- break;
- case StackElement::Rename:
- case StackElement::Access:
- {
- if (topElement.type != StackElement::ModifyField
- && topElement.type != StackElement::ModifyFunction) {
- m_error = "Function or field modification parent required";
- return false;
- }
- Modification *mod = 0;
- if (topElement.type == StackElement::ModifyFunction)
- mod = &m_function_mods.last();
- else
- mod = &m_field_mods.last();
- QString modifier;
- if (element->type == StackElement::Rename) {
- modifier = "rename";
- QString renamed_to = attributes["to"];
- if (renamed_to.isEmpty()) {
- m_error = "Rename modifier requires 'to' attribute";
- return false;
- }
- if (topElement.type == StackElement::ModifyFunction)
- mod->setRenamedTo(renamed_to);
- else
- mod->setRenamedTo(renamed_to);
- } else {
- modifier = attributes["modifier"].toLower();
- }
- if (modifier.isEmpty()) {
- m_error = "No access modification specified";
- return false;
- }
- static QHash<QString, FunctionModification::Modifiers> modifierNames;
- if (modifierNames.isEmpty()) {
- modifierNames["private"] = Modification::Private;
- modifierNames["public"] = Modification::Public;
- modifierNames["protected"] = Modification::Protected;
- modifierNames["friendly"] = Modification::Friendly;
- modifierNames["rename"] = Modification::Rename;
- modifierNames["final"] = Modification::Final;
- modifierNames["non-final"] = Modification::NonFinal;
- }
- if (!modifierNames.contains(modifier)) {
- m_error = QString("Unknown access modifier: '%1'").arg(modifier);
- return false;
- }
- mod->modifiers |= modifierNames[modifier];
- }
- break;
- case StackElement::RemoveArgument:
- if (topElement.type != StackElement::ModifyArgument) {
- m_error = "Removing argument requires argument modification as parent";
- return false;
- }
- m_function_mods.last().argument_mods.last().removed = true;
- break;
- case StackElement::ModifyField:
- {
- QString name = attributes["name"];
- if (name.isEmpty())
- break;
- FieldModification fm;
- fm.name = name;
- fm.modifiers = 0;
- QString read = attributes["read"];
- QString write = attributes["write"];
- if (read == "true") fm.modifiers |= FieldModification::Readable;
- if (write == "true") fm.modifiers |= FieldModification::Writable;
- m_field_mods << fm;
- }
- break;
- case StackElement::AddClass: // qtd - fully :)
- {
- if (!(topElement.type & StackElement::ComplexTypeEntryMask)) {
- m_error = QString::fromLatin1("Add class to module requires complex type as parent"
- ", was=%1").arg(topElement.type, 0, 16);
- return false;
- }
- QString class_name = attributes["name"];
- ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(topElement.entry);
- if(!class_name.isEmpty())
- ctype->includedClasses << class_name;
- }
- break;
- case StackElement::ModifyFunction:
- {
- if (!(topElement.type & StackElement::ComplexTypeEntryMask)) {
- m_error = QString::fromLatin1("Modify function requires complex type as parent"
- ", was=%1").arg(topElement.type, 0, 16);
- return false;
- }
- QString signature = attributes["signature"];
- signature = QMetaObject::normalizedSignature(signature.toLocal8Bit().constData());
- if (signature.isEmpty()) {
- m_error = "No signature for modified function";
- return false;
- }
- FunctionModification mod;
- mod.signature = signature;
- QString access = attributes["access"].toLower();
- if (!access.isEmpty()) {
- if (access == QLatin1String("private"))
- mod.modifiers |= Modification::Private;
- else if (access == QLatin1String("protected"))
- mod.modifiers |= Modification::Protected;
- else if (access == QLatin1String("public"))
- mod.modifiers |= Modification::Public;
- else if (access == QLatin1String("final"))
- mod.modifiers |= Modification::Final;
- else if (access == QLatin1String("non-final"))
- mod.modifiers |= Modification::NonFinal;
- else {
- m_error = QString::fromLatin1("Bad access type '%1'").arg(access);
- return false;
- }
- }
- if (convertBoolean(attributes["deprecated"], "deprecated", false)) {
- mod.modifiers |= Modification::Deprecated;
- }
- QString remove = attributes["remove"].toLower();
- if (!remove.isEmpty()) {
- if (remove == QLatin1String("all"))
- mod.removal = TypeSystem::All;
- else if (remove == QLatin1String("java"))
- mod.removal = TypeSystem::TargetLangAndNativeCode;
- else {
- m_error = QString::fromLatin1("Bad removal type '%1'").arg(remove);
- return false;
- }
- }
- QString rename = attributes["rename"];
- if (!rename.isEmpty()) {
- mod.renamedToName = rename;
- mod.modifiers |= Modification::Rename;
- }
- QString association = attributes["associated-to"];
- if (!association.isEmpty())
- mod.association = association;
- mod.modifiers |= (convertBoolean(attri…
Large files files are truncated, but you can click here to view the full file