forked from qt-creator/qt-creator
qmldump: Make Creator able to read qmldump's new output.
Task-number: QTCREATORBUG-3048
This commit is contained in:
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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")));
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
448
src/libs/qmljs/qmljstypedescriptionreader.cpp
Normal file
448
src/libs/qmljs/qmljstypedescriptionreader.cpp
Normal file
@@ -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);
|
||||
}
|
||||
}
|
53
src/libs/qmljs/qmljstypedescriptionreader.h
Normal file
53
src/libs/qmljs/qmljstypedescriptionreader.h
Normal file
@@ -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
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user