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 "componentversion.h"
|
||||||
|
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
using namespace LanguageUtils;
|
using namespace LanguageUtils;
|
||||||
|
|
||||||
const int ComponentVersion::NoVersion = -1;
|
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()
|
ComponentVersion::~ComponentVersion()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -56,6 +75,12 @@ bool ComponentVersion::isValid() const
|
|||||||
return _major >= 0 && _minor >= 0;
|
return _major >= 0 && _minor >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ComponentVersion::toString() const
|
||||||
|
{
|
||||||
|
return QString("%1.%2").arg(QString::number(_major),
|
||||||
|
QString::number(_minor));
|
||||||
|
}
|
||||||
|
|
||||||
namespace LanguageUtils {
|
namespace LanguageUtils {
|
||||||
|
|
||||||
bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs)
|
bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs)
|
||||||
|
@@ -48,6 +48,7 @@ public:
|
|||||||
|
|
||||||
ComponentVersion();
|
ComponentVersion();
|
||||||
ComponentVersion(int major, int minor);
|
ComponentVersion(int major, int minor);
|
||||||
|
explicit ComponentVersion(const QString &versionString);
|
||||||
~ComponentVersion();
|
~ComponentVersion();
|
||||||
|
|
||||||
int majorVersion() const
|
int majorVersion() const
|
||||||
@@ -56,6 +57,7 @@ public:
|
|||||||
{ return _minor; }
|
{ return _minor; }
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
QString toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LANGUAGEUTILS_EXPORT operator<(const ComponentVersion &lhs, const ComponentVersion &rhs);
|
bool LANGUAGEUTILS_EXPORT operator<(const ComponentVersion &lhs, const ComponentVersion &rhs);
|
||||||
|
@@ -35,6 +35,9 @@
|
|||||||
|
|
||||||
using namespace LanguageUtils;
|
using namespace LanguageUtils;
|
||||||
|
|
||||||
|
FakeMetaEnum::FakeMetaEnum()
|
||||||
|
{}
|
||||||
|
|
||||||
FakeMetaEnum::FakeMetaEnum(const QString &name)
|
FakeMetaEnum::FakeMetaEnum(const QString &name)
|
||||||
: m_name(name)
|
: m_name(name)
|
||||||
{}
|
{}
|
||||||
@@ -42,6 +45,9 @@ FakeMetaEnum::FakeMetaEnum(const QString &name)
|
|||||||
QString FakeMetaEnum::name() const
|
QString FakeMetaEnum::name() const
|
||||||
{ return m_name; }
|
{ return m_name; }
|
||||||
|
|
||||||
|
void FakeMetaEnum::setName(const QString &name)
|
||||||
|
{ m_name = name; }
|
||||||
|
|
||||||
void FakeMetaEnum::addKey(const QString &key, int value)
|
void FakeMetaEnum::addKey(const QString &key, int value)
|
||||||
{ m_keys.append(key); m_values.append(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)
|
, m_methodAccess(FakeMetaMethod::Public)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
FakeMetaMethod::FakeMetaMethod()
|
||||||
|
: m_methodTy(FakeMetaMethod::Method)
|
||||||
|
, m_methodAccess(FakeMetaMethod::Public)
|
||||||
|
{}
|
||||||
|
|
||||||
QString FakeMetaMethod::methodName() const
|
QString FakeMetaMethod::methodName() const
|
||||||
{ return m_name; }
|
{ 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
|
QStringList FakeMetaMethod::parameterNames() const
|
||||||
{ return m_paramNames; }
|
{ 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)
|
void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version)
|
||||||
{
|
{
|
||||||
Export exp;
|
Export exp;
|
||||||
exp.type = name;
|
exp.type = name;
|
||||||
exp.package = package;
|
exp.package = package;
|
||||||
exp.version = version;
|
exp.version = version;
|
||||||
exp.packageNameVersion = QString::fromLatin1("%1.%2 %3.%4").arg(
|
exp.packageNameVersion = QString::fromLatin1("%1.%2 %3").arg(
|
||||||
package, name,
|
package, name,
|
||||||
QString::number(version.majorVersion()),
|
version.toString());
|
||||||
QString::number(version.minorVersion()));
|
|
||||||
m_exports.append(exp);
|
m_exports.append(exp);
|
||||||
}
|
}
|
||||||
QList<FakeMetaObject::Export> FakeMetaObject::exports() const
|
QList<FakeMetaObject::Export> FakeMetaObject::exports() const
|
||||||
|
@@ -51,9 +51,11 @@ class LANGUAGEUTILS_EXPORT FakeMetaEnum {
|
|||||||
QList<int> m_values;
|
QList<int> m_values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeMetaEnum(const QString &name);
|
FakeMetaEnum();
|
||||||
|
explicit FakeMetaEnum(const QString &name);
|
||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
void setName(const QString &name);
|
||||||
|
|
||||||
void addKey(const QString &key, int value);
|
void addKey(const QString &key, int value);
|
||||||
QString key(int index) const;
|
QString key(int index) const;
|
||||||
@@ -76,9 +78,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeMetaMethod(const QString &name, const QString &returnType = QString());
|
FakeMetaMethod();
|
||||||
|
explicit FakeMetaMethod(const QString &name, const QString &returnType = QString());
|
||||||
|
|
||||||
QString methodName() const;
|
QString methodName() const;
|
||||||
|
void setMethodName(const QString &name);
|
||||||
|
|
||||||
|
void setReturnType(const QString &type);
|
||||||
|
|
||||||
QStringList parameterNames() const;
|
QStringList parameterNames() const;
|
||||||
QStringList parameterTypes() const;
|
QStringList parameterTypes() const;
|
||||||
void addParameter(const QString &name, const QString &type);
|
void addParameter(const QString &name, const QString &type);
|
||||||
@@ -131,6 +138,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString m_className;
|
||||||
QList<Export> m_exports;
|
QList<Export> m_exports;
|
||||||
ConstPtr m_super;
|
ConstPtr m_super;
|
||||||
QString m_superName;
|
QString m_superName;
|
||||||
@@ -144,6 +152,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
FakeMetaObject();
|
FakeMetaObject();
|
||||||
|
|
||||||
|
QString className() const;
|
||||||
|
void setClassName(const QString &name);
|
||||||
|
|
||||||
void addExport(const QString &name, const QString &package, ComponentVersion version);
|
void addExport(const QString &name, const QString &package, ComponentVersion version);
|
||||||
QList<Export> exports() const;
|
QList<Export> exports() const;
|
||||||
|
|
||||||
|
@@ -27,7 +27,8 @@ HEADERS += \
|
|||||||
$$PWD/qmljspropertyreader.h \
|
$$PWD/qmljspropertyreader.h \
|
||||||
$$PWD/qmljsrewriter.h \
|
$$PWD/qmljsrewriter.h \
|
||||||
$$PWD/qmljsicons.h \
|
$$PWD/qmljsicons.h \
|
||||||
$$PWD/qmljsdelta.h
|
$$PWD/qmljsdelta.h \
|
||||||
|
$$PWD/qmljstypedescriptionreader.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmljsbind.cpp \
|
$$PWD/qmljsbind.cpp \
|
||||||
@@ -45,7 +46,8 @@ SOURCES += \
|
|||||||
$$PWD/qmljspropertyreader.cpp \
|
$$PWD/qmljspropertyreader.cpp \
|
||||||
$$PWD/qmljsrewriter.cpp \
|
$$PWD/qmljsrewriter.cpp \
|
||||||
$$PWD/qmljsicons.cpp \
|
$$PWD/qmljsicons.cpp \
|
||||||
$$PWD/qmljsdelta.cpp
|
$$PWD/qmljsdelta.cpp \
|
||||||
|
$$PWD/qmljstypedescriptionreader.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
$$PWD/qmljs.qrc
|
$$PWD/qmljs.qrc
|
||||||
|
@@ -254,11 +254,8 @@ bool Bind::visit(UiImport *ast)
|
|||||||
|
|
||||||
if (ast->versionToken.isValid()) {
|
if (ast->versionToken.isValid()) {
|
||||||
const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length);
|
const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length);
|
||||||
const int dotIdx = versionString.indexOf(QLatin1Char('.'));
|
version = ComponentVersion(versionString);
|
||||||
if (dotIdx != -1) {
|
if (!version.isValid()) {
|
||||||
version = ComponentVersion(versionString.left(dotIdx).toInt(),
|
|
||||||
versionString.mid(dotIdx + 1).toInt());
|
|
||||||
} else {
|
|
||||||
_diagnosticMessages->append(
|
_diagnosticMessages->append(
|
||||||
errorMessage(ast->versionToken, tr("expected two numbers separated by a dot")));
|
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;
|
QList<FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects;
|
||||||
|
|
||||||
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
|
QStringList CppQmlTypesLoader::loadXml(const QFileInfoList &xmlFiles)
|
||||||
{
|
{
|
||||||
QMap<QString, FakeMetaObject::Ptr> newObjects;
|
QMap<QString, FakeMetaObject::Ptr> newObjects;
|
||||||
QStringList errorMsgs;
|
QStringList errorMsgs;
|
||||||
@@ -2117,10 +2117,10 @@ bool CppQmlTypes::hasPackage(const QString &package) const
|
|||||||
|
|
||||||
QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, ComponentVersion version)
|
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,
|
package, type,
|
||||||
QString::number(version.majorVersion()),
|
version.toString());
|
||||||
QString::number(version.minorVersion()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const
|
QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const
|
||||||
|
@@ -585,7 +585,7 @@ class QMLJS_EXPORT CppQmlTypesLoader
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** \return an empty list when successful, error messages otherwise. */
|
/** \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;
|
static QList<LanguageUtils::FakeMetaObject::ConstPtr> builtinObjects;
|
||||||
|
|
||||||
// parses the xml string and fills the newObjects map
|
// 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::Files,
|
||||||
QDir::Name);
|
QDir::Name);
|
||||||
|
|
||||||
const QStringList errors = Interpreter::CppQmlTypesLoader::load(xmlFiles);
|
const QStringList errors = Interpreter::CppQmlTypesLoader::loadXml(xmlFiles);
|
||||||
foreach (const QString &error, errors)
|
foreach (const QString &error, errors)
|
||||||
qWarning() << qPrintable(error);
|
qWarning() << qPrintable(error);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user