From dd1de1b82f9f8681aec14bc4266bb1d68d11c4fd Mon Sep 17 00:00:00 2001 From: Christian Kamm <christian.d.kamm@nokia.com> Date: Tue, 8 Feb 2011 11:01:37 +0100 Subject: [PATCH] qmldump: Make Creator able to read qmldump's new output. Task-number: QTCREATORBUG-3048 --- src/libs/languageutils/componentversion.cpp | 25 + src/libs/languageutils/componentversion.h | 2 + src/libs/languageutils/fakemetaobject.cpp | 27 +- src/libs/languageutils/fakemetaobject.h | 15 +- src/libs/qmljs/qmljs-lib.pri | 6 +- src/libs/qmljs/qmljsbind.cpp | 7 +- src/libs/qmljs/qmljsinterpreter.cpp | 8 +- src/libs/qmljs/qmljsinterpreter.h | 2 +- src/libs/qmljs/qmljstypedescriptionreader.cpp | 448 ++++++++++++++++++ src/libs/qmljs/qmljstypedescriptionreader.h | 53 +++ src/plugins/qmljstools/qmljsmodelmanager.cpp | 2 +- 11 files changed, 577 insertions(+), 18 deletions(-) create mode 100644 src/libs/qmljs/qmljstypedescriptionreader.cpp create mode 100644 src/libs/qmljs/qmljstypedescriptionreader.h diff --git a/src/libs/languageutils/componentversion.cpp b/src/libs/languageutils/componentversion.cpp index ebab885ad67..94e6037030f 100644 --- a/src/libs/languageutils/componentversion.cpp +++ b/src/libs/languageutils/componentversion.cpp @@ -33,6 +33,8 @@ #include "componentversion.h" +#include <QtCore/QString> + using namespace LanguageUtils; const int ComponentVersion::NoVersion = -1; @@ -47,6 +49,23 @@ ComponentVersion::ComponentVersion(int major, int minor) { } +ComponentVersion::ComponentVersion(const QString &versionString) + : _major(NoVersion), _minor(NoVersion) +{ + int dotIdx = versionString.indexOf(QLatin1Char('.')); + if (dotIdx == -1) + return; + bool ok = false; + int maybeMajor = versionString.left(dotIdx).toInt(&ok); + if (!ok) + return; + int maybeMinor = versionString.mid(dotIdx + 1).toInt(&ok); + if (!ok) + return; + _major = maybeMajor; + _minor = maybeMinor; +} + ComponentVersion::~ComponentVersion() { } @@ -56,6 +75,12 @@ bool ComponentVersion::isValid() const return _major >= 0 && _minor >= 0; } +QString ComponentVersion::toString() const +{ + return QString("%1.%2").arg(QString::number(_major), + QString::number(_minor)); +} + namespace LanguageUtils { bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs) diff --git a/src/libs/languageutils/componentversion.h b/src/libs/languageutils/componentversion.h index d19a9689375..21a7265e32c 100644 --- a/src/libs/languageutils/componentversion.h +++ b/src/libs/languageutils/componentversion.h @@ -48,6 +48,7 @@ public: ComponentVersion(); ComponentVersion(int major, int minor); + explicit ComponentVersion(const QString &versionString); ~ComponentVersion(); int majorVersion() const @@ -56,6 +57,7 @@ public: { return _minor; } bool isValid() const; + QString toString() const; }; bool LANGUAGEUTILS_EXPORT operator<(const ComponentVersion &lhs, const ComponentVersion &rhs); diff --git a/src/libs/languageutils/fakemetaobject.cpp b/src/libs/languageutils/fakemetaobject.cpp index 1e22ecb19aa..f9f51c7236a 100644 --- a/src/libs/languageutils/fakemetaobject.cpp +++ b/src/libs/languageutils/fakemetaobject.cpp @@ -35,6 +35,9 @@ using namespace LanguageUtils; +FakeMetaEnum::FakeMetaEnum() +{} + FakeMetaEnum::FakeMetaEnum(const QString &name) : m_name(name) {} @@ -42,6 +45,9 @@ FakeMetaEnum::FakeMetaEnum(const QString &name) QString FakeMetaEnum::name() const { return m_name; } +void FakeMetaEnum::setName(const QString &name) +{ m_name = name; } + void FakeMetaEnum::addKey(const QString &key, int value) { m_keys.append(key); m_values.append(value); } @@ -61,9 +67,20 @@ FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType) , m_methodAccess(FakeMetaMethod::Public) {} +FakeMetaMethod::FakeMetaMethod() + : m_methodTy(FakeMetaMethod::Method) + , m_methodAccess(FakeMetaMethod::Public) +{} + QString FakeMetaMethod::methodName() const { return m_name; } +void FakeMetaMethod::setMethodName(const QString &name) +{ m_name = name; } + +void FakeMetaMethod::setReturnType(const QString &type) +{ m_returnType = type; } + QStringList FakeMetaMethod::parameterNames() const { return m_paramNames; } @@ -108,16 +125,20 @@ FakeMetaObject::FakeMetaObject() { } +QString FakeMetaObject::className() const +{ return m_className; } +void FakeMetaObject::setClassName(const QString &name) +{ m_className = name; } + void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version) { Export exp; exp.type = name; exp.package = package; exp.version = version; - exp.packageNameVersion = QString::fromLatin1("%1.%2 %3.%4").arg( + exp.packageNameVersion = QString::fromLatin1("%1.%2 %3").arg( package, name, - QString::number(version.majorVersion()), - QString::number(version.minorVersion())); + version.toString()); m_exports.append(exp); } QList<FakeMetaObject::Export> FakeMetaObject::exports() const diff --git a/src/libs/languageutils/fakemetaobject.h b/src/libs/languageutils/fakemetaobject.h index 60f77aee207..4449a1e27e6 100644 --- a/src/libs/languageutils/fakemetaobject.h +++ b/src/libs/languageutils/fakemetaobject.h @@ -51,9 +51,11 @@ class LANGUAGEUTILS_EXPORT FakeMetaEnum { QList<int> m_values; public: - FakeMetaEnum(const QString &name); + FakeMetaEnum(); + explicit FakeMetaEnum(const QString &name); QString name() const; + void setName(const QString &name); void addKey(const QString &key, int value); QString key(int index) const; @@ -76,9 +78,14 @@ public: }; public: - FakeMetaMethod(const QString &name, const QString &returnType = QString()); + FakeMetaMethod(); + explicit FakeMetaMethod(const QString &name, const QString &returnType = QString()); QString methodName() const; + void setMethodName(const QString &name); + + void setReturnType(const QString &type); + QStringList parameterNames() const; QStringList parameterTypes() const; void addParameter(const QString &name, const QString &type); @@ -131,6 +138,7 @@ public: }; private: + QString m_className; QList<Export> m_exports; ConstPtr m_super; QString m_superName; @@ -144,6 +152,9 @@ private: public: FakeMetaObject(); + QString className() const; + void setClassName(const QString &name); + void addExport(const QString &name, const QString &package, ComponentVersion version); QList<Export> exports() const; diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri index b4e4b5810aa..7bd069c63ac 100644 --- a/src/libs/qmljs/qmljs-lib.pri +++ b/src/libs/qmljs/qmljs-lib.pri @@ -27,7 +27,8 @@ HEADERS += \ $$PWD/qmljspropertyreader.h \ $$PWD/qmljsrewriter.h \ $$PWD/qmljsicons.h \ - $$PWD/qmljsdelta.h + $$PWD/qmljsdelta.h \ + $$PWD/qmljstypedescriptionreader.h SOURCES += \ $$PWD/qmljsbind.cpp \ @@ -45,7 +46,8 @@ SOURCES += \ $$PWD/qmljspropertyreader.cpp \ $$PWD/qmljsrewriter.cpp \ $$PWD/qmljsicons.cpp \ - $$PWD/qmljsdelta.cpp + $$PWD/qmljsdelta.cpp \ + $$PWD/qmljstypedescriptionreader.cpp RESOURCES += \ $$PWD/qmljs.qrc diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp index 0ed4ea5e8da..073d9b69337 100644 --- a/src/libs/qmljs/qmljsbind.cpp +++ b/src/libs/qmljs/qmljsbind.cpp @@ -254,11 +254,8 @@ bool Bind::visit(UiImport *ast) if (ast->versionToken.isValid()) { const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length); - const int dotIdx = versionString.indexOf(QLatin1Char('.')); - if (dotIdx != -1) { - version = ComponentVersion(versionString.left(dotIdx).toInt(), - versionString.mid(dotIdx + 1).toInt()); - } else { + version = ComponentVersion(versionString); + if (!version.isValid()) { _diagnosticMessages->append( errorMessage(ast->versionToken, tr("expected two numbers separated by a dot"))); } diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 034b8f82189..2e540f37b70 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -1945,7 +1945,7 @@ const Value *Function::invoke(const Activation *activation) const QList<FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects; -QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles) +QStringList CppQmlTypesLoader::loadXml(const QFileInfoList &xmlFiles) { QMap<QString, FakeMetaObject::Ptr> newObjects; QStringList errorMsgs; @@ -2117,10 +2117,10 @@ bool CppQmlTypes::hasPackage(const QString &package) const QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, ComponentVersion version) { - return QString("%1.%2 %3.%4").arg( + return QString("%1.%2 %3").arg( package, type, - QString::number(version.majorVersion()), - QString::number(version.minorVersion())); + version.toString()); + } QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index d80ecddd61b..2090dc71db0 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -585,7 +585,7 @@ class QMLJS_EXPORT CppQmlTypesLoader { public: /** \return an empty list when successful, error messages otherwise. */ - static QStringList load(const QFileInfoList &xmlFiles); + static QStringList loadXml(const QFileInfoList &xmlFiles); static QList<LanguageUtils::FakeMetaObject::ConstPtr> builtinObjects; // parses the xml string and fills the newObjects map diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp new file mode 100644 index 00000000000..0c2b5f318a7 --- /dev/null +++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp @@ -0,0 +1,448 @@ +#include "qmljstypedescriptionreader.h" + +#include "parser/qmljsparser_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsengine_p.h" +#include "parser/qmljsnodepool_p.h" +#include "parser/qmljsast_p.h" +#include "parser/qmljsastvisitor_p.h" + +#include "qmljsbind.h" + +#include <QtCore/QIODevice> +#include <QtCore/QBuffer> + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace LanguageUtils; + +TypeDescriptionReader::TypeDescriptionReader(const QString &data) + : _source(data) + , _objects(0) +{ +} + +TypeDescriptionReader::~TypeDescriptionReader() +{ +} + +bool TypeDescriptionReader::operator()(QMap<QString, FakeMetaObject::Ptr> *objects) +{ + QString fileName("typeDescription"); + Engine engine; + NodePool pool(fileName, &engine); + + Lexer lexer(&engine); + Parser parser(&engine); + + lexer.setCode(_source, /*line = */ 1); + + if (!parser.parse()) { + _errorMessage = QString("%1:%2: %3").arg( + QString::number(parser.errorLineNumber()), + QString::number(parser.errorColumnNumber()), + parser.errorMessage()); + return false; + } + + _objects = objects; + readDocument(parser.ast()); + + return _errorMessage.isEmpty(); +} + +QString TypeDescriptionReader::errorMessage() const +{ + return _errorMessage; +} + +void TypeDescriptionReader::readDocument(UiProgram *ast) +{ + if (!ast) { + addError(SourceLocation(), "Could not parse document"); + return; + } + + if (!ast->imports || ast->imports->next) { + addError(SourceLocation(), "Expected a single import"); + return; + } + + UiImport *import = ast->imports->import; + if (Bind::toString(import->importUri) != QLatin1String("QtQuick.tooling")) { + addError(import->importToken, "Expected import of QtQuick.tooling"); + return; + } + + ComponentVersion version; + const QString versionString = _source.mid(import->versionToken.offset, import->versionToken.length); + const int dotIdx = versionString.indexOf(QLatin1Char('.')); + if (dotIdx != -1) { + version = ComponentVersion(versionString.left(dotIdx).toInt(), + versionString.mid(dotIdx + 1).toInt()); + } + if (version != ComponentVersion(1, 0)) { + addError(import->versionToken, "Expected version 1.0"); + return; + } + + if (!ast->members || !ast->members->member || ast->members->next) { + addError(SourceLocation(), "Expected document to contain a single object definition"); + return; + } + + UiObjectDefinition *module = dynamic_cast<UiObjectDefinition *>(ast->members->member); + if (!module) { + addError(SourceLocation(), "Expected document to contain a single object definition"); + return; + } + + if (Bind::toString(module->qualifiedTypeNameId) != "Module") { + addError(SourceLocation(), "Expected document to contain a Module {} member"); + return; + } + + readModule(module); +} + +void TypeDescriptionReader::readModule(UiObjectDefinition *ast) +{ + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member); + if (!component || Bind::toString(component->qualifiedTypeNameId) != "Component") { + addError(member->firstSourceLocation(), "Expected only 'Component' object definitions"); + return; + } + + readComponent(component); + } +} + +void TypeDescriptionReader::addError(const SourceLocation &loc, const QString &message) +{ + _errorMessage += QString("%1:%2: %3\n").arg( + QString::number(loc.startLine), + QString::number(loc.startColumn), + message); +} + +void TypeDescriptionReader::readComponent(UiObjectDefinition *ast) +{ + FakeMetaObject::Ptr fmo(new FakeMetaObject); + + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member); + UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); + if (component) { + QString name = Bind::toString(component->qualifiedTypeNameId); + if (name == "Property") { + readProperty(component, fmo); + } else if (name == "Method" || name == "Signal") { + readSignalOrMethod(component, name == "Method", fmo); + } else if (name == "Enum") { + readEnum(component, fmo); + } else { + addError(component->firstSourceLocation(), "Expected only Property, Method, Signal and Enum object definitions"); + return; + } + } else if (script) { + QString name = Bind::toString(script->qualifiedId); + if (name == "name") { + fmo->setClassName(readStringBinding(script)); + } else if (name == "prototype") { + fmo->setSuperclassName(readStringBinding(script)); + } else if (name == "defaultProperty") { + fmo->setDefaultPropertyName(readStringBinding(script)); + } else if (name == "exports") { + readExports(script, fmo); + } else { + addError(script->firstSourceLocation(), "Expected only name, prototype, defaultProperty and exports script bindings"); + return; + } + } else { + addError(member->firstSourceLocation(), "Expected only script bindings and object definitions"); + return; + } + } + + if (fmo->className().isEmpty()) { + addError(ast->firstSourceLocation(), "Component definition is missing a name binding"); + return; + } + + _objects->insert(fmo->className(), fmo); +} + +void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isMethod, FakeMetaObject::Ptr fmo) +{ + FakeMetaMethod fmm; + // ### confusion between Method and Slot. Method should be removed. + if (isMethod) + fmm.setMethodType(FakeMetaMethod::Slot); + else + fmm.setMethodType(FakeMetaMethod::Signal); + + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member); + UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); + if (component) { + QString name = Bind::toString(component->qualifiedTypeNameId); + if (name == "Parameter") { + readParameter(component, &fmm); + } else { + addError(component->firstSourceLocation(), "Expected only Parameter object definitions"); + return; + } + } else if (script) { + QString name = Bind::toString(script->qualifiedId); + if (name == "name") { + fmm.setMethodName(readStringBinding(script)); + } else if (name == "type") { + fmm.setReturnType(readStringBinding(script)); + } else { + addError(script->firstSourceLocation(), "Expected only name and type script bindings"); + return; + } + + } else { + addError(member->firstSourceLocation(), "Expected only script bindings and object definitions"); + return; + } + } + + if (fmm.methodName().isEmpty()) { + addError(ast->firstSourceLocation(), "Method or Signal is missing a name script binding"); + return; + } + + fmo->addMethod(fmm); +} + +void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject::Ptr fmo) +{ + QString name; + QString type; + bool isPointer = false; + bool isReadonly = false; + bool isList = false; + + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); + if (!script) { + addError(member->firstSourceLocation(), "Expected script binding"); + return; + } + + QString id = Bind::toString(script->qualifiedId); + if (id == "name") { + name = readStringBinding(script); + } else if (id == "type") { + type = readStringBinding(script); + } else if (id == "isPointer") { + isPointer = readBoolBinding(script); + } else if (id == "isReadonly") { + isReadonly = readBoolBinding(script); + } else if (id == "isList") { + isList = readBoolBinding(script); + } else { + addError(script->firstSourceLocation(), "Expected only type, name, isPointer, isReadonly and isList script bindings"); + return; + } + } + + if (name.isEmpty() || type.isEmpty()) { + addError(ast->firstSourceLocation(), "Property object is missing a name or type script binding"); + return; + } + + fmo->addProperty(FakeMetaProperty(name, type, isList, !isReadonly, isPointer)); +} + +void TypeDescriptionReader::readEnum(UiObjectDefinition *ast, FakeMetaObject::Ptr fmo) +{ + FakeMetaEnum fme; + + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); + if (!script) { + addError(member->firstSourceLocation(), "Expected script binding"); + return; + } + + QString name = Bind::toString(script->qualifiedId); + if (name == "name") { + fme.setName(readStringBinding(script)); + } else if (name == "values") { + readEnumValues(script, &fme); + } else { + addError(script->firstSourceLocation(), "Expected only name and values script bindings"); + return; + } + } + + fmo->addEnum(fme); +} + +void TypeDescriptionReader::readParameter(UiObjectDefinition *ast, FakeMetaMethod *fmm) +{ + QString name; + QString type; + + for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); + if (!script) { + addError(member->firstSourceLocation(), "Expected script binding"); + return; + } + + QString id = Bind::toString(script->qualifiedId); + if (id == "name") { + id = readStringBinding(script); + } else if (id == "type") { + type = readStringBinding(script); + } else if (id == "isPointer") { + // ### unhandled + } else if (id == "isReadonly") { + // ### unhandled + } else if (id == "isList") { + // ### unhandled + } else { + addError(script->firstSourceLocation(), "Expected only name and type script bindings"); + return; + } + } + + fmm->addParameter(name, type); +} + +QString TypeDescriptionReader::readStringBinding(UiScriptBinding *ast) +{ + if (!ast || !ast->statement) { + addError(ast->colonToken, "Expected string after colon"); + return QString(); + } + + ExpressionStatement *expStmt = dynamic_cast<ExpressionStatement *>(ast->statement); + if (!expStmt) { + addError(ast->statement->firstSourceLocation(), "Expected string after colon"); + return QString(); + } + + StringLiteral *stringLit = dynamic_cast<StringLiteral *>(expStmt->expression); + if (!stringLit) { + addError(expStmt->firstSourceLocation(), "Expected string after colon"); + return QString(); + } + + return stringLit->value->asString(); +} + +bool TypeDescriptionReader::readBoolBinding(AST::UiScriptBinding *ast) +{ + if (!ast || !ast->statement) { + addError(ast->colonToken, "Expected boolean after colon"); + return false; + } + + ExpressionStatement *expStmt = dynamic_cast<ExpressionStatement *>(ast->statement); + if (!expStmt) { + addError(ast->statement->firstSourceLocation(), "Expected boolean after colon"); + return false; + } + + TrueLiteral *trueLit = dynamic_cast<TrueLiteral *>(expStmt->expression); + FalseLiteral *falseLit = dynamic_cast<FalseLiteral *>(expStmt->expression); + if (!trueLit && !falseLit) { + addError(expStmt->firstSourceLocation(), "Expected true or false after colon"); + return false; + } + + return trueLit; +} + +void TypeDescriptionReader::readExports(UiScriptBinding *ast, FakeMetaObject::Ptr fmo) +{ + if (!ast || !ast->statement) { + addError(ast->colonToken, "Expected array of strings after colon"); + return; + } + + ExpressionStatement *expStmt = dynamic_cast<ExpressionStatement *>(ast->statement); + if (!expStmt) { + addError(ast->statement->firstSourceLocation(), "Expected array of strings after colon"); + return; + } + + ArrayLiteral *arrayLit = dynamic_cast<ArrayLiteral *>(expStmt->expression); + if (!arrayLit) { + addError(expStmt->firstSourceLocation(), "Expected array of strings after colon"); + return; + } + + for (ElementList *it = arrayLit->elements; it; it = it->next) { + StringLiteral *stringLit = dynamic_cast<StringLiteral *>(it->expression); + if (!stringLit) { + addError(arrayLit->firstSourceLocation(), "Expected array literal with only string literal members"); + return; + } + QString exp = stringLit->value->asString(); + int slashIdx = exp.indexOf(QLatin1Char('/')); + int spaceIdx = exp.indexOf(QLatin1Char(' ')); + ComponentVersion version(exp.mid(spaceIdx + 1)); + + if (spaceIdx == -1 || !version.isValid()) { + addError(stringLit->firstSourceLocation(), "Expected string literal to contain 'Package/Name major.minor' or 'Name major.minor'"); + continue; + } + QString package; + if (slashIdx != -1) + package = exp.left(slashIdx); + QString name = exp.mid(slashIdx + 1, spaceIdx - (slashIdx+1)); + + // ### relocatable exports where package is empty? + fmo->addExport(name, package, version); + } +} + +void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaEnum *fme) +{ + if (!ast || !ast->statement) { + addError(ast->colonToken, "Expected object literal after colon"); + return; + } + + ExpressionStatement *expStmt = dynamic_cast<ExpressionStatement *>(ast->statement); + if (!expStmt) { + addError(ast->statement->firstSourceLocation(), "Expected object literal after colon"); + return; + } + + ObjectLiteral *objectLit = dynamic_cast<ObjectLiteral *>(expStmt->expression); + if (!objectLit) { + addError(expStmt->firstSourceLocation(), "Expected object literal after colon"); + return; + } + + for (PropertyNameAndValueList *it = objectLit->properties; it; it = it->next) { + StringLiteralPropertyName *propName = dynamic_cast<StringLiteralPropertyName *>(it->name); + NumericLiteral *value = dynamic_cast<NumericLiteral *>(it->value); + UnaryMinusExpression *minus = dynamic_cast<UnaryMinusExpression *>(it->value); + if (minus) + value = dynamic_cast<NumericLiteral *>(minus->expression); + if (!propName || !value) { + addError(objectLit->firstSourceLocation(), "Expected object literal to contain only 'string: number' elements"); + continue; + } + + double v = value->value; + if (minus) + v = -v; + fme->addKey(propName->id->asString(), v); + } +} diff --git a/src/libs/qmljs/qmljstypedescriptionreader.h b/src/libs/qmljs/qmljstypedescriptionreader.h new file mode 100644 index 00000000000..1b7d38c9a58 --- /dev/null +++ b/src/libs/qmljs/qmljstypedescriptionreader.h @@ -0,0 +1,53 @@ +#ifndef QMLJSTYPEDESCRIPTIONREADER_H +#define QMLJSTYPEDESCRIPTIONREADER_H + +#include <languageutils/fakemetaobject.h> + +#include <QtCore/QScopedPointer> + +QT_BEGIN_NAMESPACE +class QIODevice; +class QBuffer; +QT_END_NAMESPACE + +namespace QmlJS { + +namespace AST { +class UiProgram; +class UiObjectDefinition; +class UiScriptBinding; +class SourceLocation; +} + +class TypeDescriptionReader +{ +public: + explicit TypeDescriptionReader(const QString &data); + ~TypeDescriptionReader(); + + bool operator()(QMap<QString, LanguageUtils::FakeMetaObject::Ptr> *objects); + QString errorMessage() const; + +private: + void readDocument(AST::UiProgram *ast); + void readModule(AST::UiObjectDefinition *ast); + void readComponent(AST::UiObjectDefinition *ast); + void readSignalOrMethod(AST::UiObjectDefinition *ast, bool isMethod, LanguageUtils::FakeMetaObject::Ptr fmo); + void readProperty(AST::UiObjectDefinition *ast, LanguageUtils::FakeMetaObject::Ptr fmo); + void readEnum(AST::UiObjectDefinition *ast, LanguageUtils::FakeMetaObject::Ptr fmo); + void readParameter(AST::UiObjectDefinition *ast, LanguageUtils::FakeMetaMethod *fmm); + + QString readStringBinding(AST::UiScriptBinding *ast); + bool readBoolBinding(AST::UiScriptBinding *ast); + void readExports(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaObject::Ptr fmo); + void readEnumValues(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaEnum *fme); + void addError(const AST::SourceLocation &loc, const QString &message); + + QString _source; + QString _errorMessage; + QMap<QString, LanguageUtils::FakeMetaObject::Ptr> *_objects; +}; + +} // namespace QmlJS + +#endif // QMLJSTYPEDESCRIPTIONREADER_H diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index f8a0ba251ae..187007f0437 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -117,7 +117,7 @@ void ModelManager::loadQmlTypeDescriptions(const QString &resourcePath) QDir::Files, QDir::Name); - const QStringList errors = Interpreter::CppQmlTypesLoader::load(xmlFiles); + const QStringList errors = Interpreter::CppQmlTypesLoader::loadXml(xmlFiles); foreach (const QString &error, errors) qWarning() << qPrintable(error); -- GitLab