Commit cf7663b2 authored by Christian Kamm's avatar Christian Kamm
Browse files

QmlJS: Read the 'revision' property generated by qmldump.

Change-Id: Ia31b1845b1e1e5aabc347dc115e580c72e36f4e3
Reviewed-on: http://codereview.qt.nokia.com/200

Reviewed-by: default avatarRoberto Raggi <roberto.raggi@nokia.com>
parent 6e327424
......@@ -64,11 +64,13 @@ FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType)
, m_returnType(returnType)
, m_methodTy(FakeMetaMethod::Method)
, m_methodAccess(FakeMetaMethod::Public)
, m_revision(0)
{}
FakeMetaMethod::FakeMetaMethod()
: m_methodTy(FakeMetaMethod::Method)
, m_methodAccess(FakeMetaMethod::Public)
, m_revision(0)
{}
QString FakeMetaMethod::methodName() const
......@@ -98,9 +100,21 @@ void FakeMetaMethod::setMethodType(int methodType)
int FakeMetaMethod::access() const
{ return m_methodAccess; }
int FakeMetaMethod::revision() const
{ return m_revision; }
FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer)
: m_propertyName(name), m_type(type), m_isList(isList), m_isWritable(isWritable), m_isPointer(isPointer)
void FakeMetaMethod::setRevision(int r)
{ m_revision = r; }
FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList,
bool isWritable, bool isPointer, int revision)
: m_propertyName(name)
, m_type(type)
, m_isList(isList)
, m_isWritable(isWritable)
, m_isPointer(isPointer)
, m_revision(revision)
{}
QString FakeMetaProperty::name() const
......@@ -118,6 +132,9 @@ bool FakeMetaProperty::isWritable() const
bool FakeMetaProperty::isPointer() const
{ return m_isPointer; }
int FakeMetaProperty::revision() const
{ return m_revision; }
FakeMetaObject::FakeMetaObject()
{
......
......@@ -94,6 +94,9 @@ public:
int access() const;
int revision() const;
void setRevision(int r);
private:
QString m_name;
QString m_returnType;
......@@ -101,6 +104,7 @@ private:
QStringList m_paramTypes;
int m_methodTy;
int m_methodAccess;
int m_revision;
};
class LANGUAGEUTILS_EXPORT FakeMetaProperty {
......@@ -109,9 +113,10 @@ class LANGUAGEUTILS_EXPORT FakeMetaProperty {
bool m_isList;
bool m_isWritable;
bool m_isPointer;
int m_revision;
public:
FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer);
FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer, int revision);
QString name() const;
QString typeName() const;
......@@ -119,6 +124,7 @@ public:
bool isList() const;
bool isWritable() const;
bool isPointer() const;
int revision() const;
};
class LANGUAGEUTILS_EXPORT FakeMetaObject {
......
......@@ -151,438 +151,6 @@ public:
}
};
class QmlXmlReader
{
Q_DECLARE_TR_FUNCTIONS(QmlJS::Interpreter::QmlXmlReader)
public:
QmlXmlReader(QIODevice *dev)
: _xml(dev)
, _objects(0)
{}
QmlXmlReader(const QByteArray &data)
: _xml(data)
{}
bool operator()(QMap<QString, FakeMetaObject::Ptr> *objects) {
Q_ASSERT(objects);
_objects = objects;
if (_xml.readNextStartElement()) {
if (_xml.name() == "module")
readModule();
else
_xml.raiseError(tr("The file is not module file."));
}
return !_xml.error();
}
QString errorMessage() const {
return _xml.errorString();
}
private:
void unexpectedElement(const QStringRef &child, const QString &parent) {
_xml.raiseError(tr("Unexpected element <%1> in <%2>").arg(child.toString(), parent));
}
void ignoreAttr(const QXmlStreamAttribute &attr) {
qDebug() << "** ignoring attribute" << attr.name().toString()
<< "in tag" << _xml.name();
}
void invalidAttr(const QString &value, const QString &attrName, const QString &tag) {
_xml.raiseError(tr("invalid value '%1' for attribute %2 in <%3>").arg(value, attrName, tag));
}
void noValidAttr(const QString &attrName, const QString &tag) {
_xml.raiseError(tr("<%1> has no valid %2 attribute").arg(tag, attrName));
}
void readModule()
{
Q_ASSERT(_xml.isStartElement() && _xml.name() == QLatin1String("module"));
foreach (const QXmlStreamAttribute &attr, _xml.attributes())
ignoreAttr(attr);
while (_xml.readNextStartElement()) {
if (_xml.name() == QLatin1String("type"))
readType();
else
unexpectedElement(_xml.name(), QLatin1String("module"));
}
}
void readType()
{
const QLatin1String tag("type");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
bool doInsert = true;
QString name, defaultPropertyName;
ComponentVersion version;
QString extends;
QString id;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
id = attr.value().toString();
if (id.isEmpty()) {
invalidAttr(name, QLatin1String("name"), tag);
return;
}
} else if (attr.name() == QLatin1String("defaultProperty")) {
defaultPropertyName = attr.value().toString();
} else if (attr.name() == QLatin1String("extends")) {
if (! attr.value().isEmpty())
extends = attr.value().toString();
if (extends == name) {
invalidAttr(extends, QLatin1String("extends"), tag);
doInsert = false;
}
} else {
ignoreAttr(attr);
}
}
FakeMetaObject::Ptr metaObject = FakeMetaObject::Ptr(new FakeMetaObject);
if (! extends.isEmpty())
metaObject->setSuperclassName(extends);
if (! defaultPropertyName.isEmpty())
metaObject->setDefaultPropertyName(defaultPropertyName);
while (_xml.readNextStartElement()) {
if (_xml.name() == QLatin1String("property"))
readProperty(metaObject);
else if (_xml.name() == QLatin1String("enum"))
readEnum(metaObject);
else if (_xml.name() == QLatin1String("signal"))
readSignal(metaObject);
else if (_xml.name() == QLatin1String("method"))
readMethod(metaObject);
else if (_xml.name() == QLatin1String("exports"))
readExports(metaObject);
else
unexpectedElement(_xml.name(), tag);
}
metaObject->addExport(id, QString(), ComponentVersion());
if (doInsert)
_objects->insert(id, metaObject);
}
bool split(const QString &name, QString *packageName, QString *className) {
int dotIdx = name.lastIndexOf(QLatin1Char('.'));
if (dotIdx != -1) {
if (packageName)
*packageName = name.left(dotIdx);
if (className)
*className = name.mid(dotIdx + 1);
return true;
} else {
if (packageName)
packageName->clear();
if (className)
*className = name;
return false;
}
}
void readProperty(FakeMetaObject::Ptr metaObject)
{
const QLatin1String tag("property");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name, type;
bool isList = false;
bool isWritable = false;
bool isPointer = false;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else if (attr.name() == QLatin1String("type")) {
type = attr.value().toString();
} else if (attr.name() == QLatin1String("isList")) {
if (attr.value() == QLatin1String("true")) {
isList = true;
} else if (attr.value() == QLatin1String("false")) {
isList = false;
} else {
invalidAttr(attr.value().toString(), QLatin1String("isList"), tag);
return;
}
} else if (attr.name() == QLatin1String("isWritable")) {
if (attr.value() == QLatin1String("true")) {
isWritable = true;
} else if (attr.value() == QLatin1String("false")) {
isWritable = false;
} else {
invalidAttr(attr.value().toString(), QLatin1String("isWritable"), tag);
return;
}
} else if (attr.name() == QLatin1String("isPointer")) {
if (attr.value() == QLatin1String("true")) {
isPointer = true;
} else if (attr.value() == QLatin1String("false")) {
isPointer = false;
} else {
invalidAttr(attr.value().toString(), QLatin1String("isPointer"), tag);
return;
}
} else {
ignoreAttr(attr);
}
}
if (name.isEmpty())
noValidAttr(QLatin1String("name"), tag);
else if (type.isEmpty())
noValidAttr(QLatin1String("type"), tag);
else
createProperty(metaObject, name, type, isList, isWritable, isPointer);
while (_xml.readNextStartElement()) {
unexpectedElement(_xml.name(), tag);
}
}
void createProperty(FakeMetaObject::Ptr metaObject, const QString &name,
const QString &type, bool isList, bool isWritable, bool isPointer) {
Q_ASSERT(metaObject);
metaObject->addProperty(FakeMetaProperty(name, type, isList, isWritable, isPointer));
}
void readEnum(FakeMetaObject::Ptr metaObject)
{
Q_ASSERT(metaObject);
QLatin1String tag("enum");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else {
ignoreAttr(attr);
}
}
if (name.isEmpty()) {
noValidAttr(QLatin1String("name"), tag);
return;
}
FakeMetaEnum metaEnum(name);
while (_xml.readNextStartElement()) {
if (_xml.name() == QLatin1String("enumerator"))
readEnumerator(&metaEnum);
else
unexpectedElement(_xml.name(), tag);
}
metaObject->addEnum(metaEnum);
}
void readEnumerator(FakeMetaEnum *metaEnum)
{
Q_ASSERT(metaEnum);
QLatin1String tag("enumerator");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name;
int value = 0;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else if (attr.name() == QLatin1String("value")) {
const QString valueStr = attr.value().toString();
bool ok = false;
value = valueStr.toInt(&ok);
if (!ok) {
invalidAttr(valueStr, QLatin1String("value"), tag);
}
} else {
ignoreAttr(attr);
}
}
if (name.isEmpty())
noValidAttr(QLatin1String("name"), tag);
else
metaEnum->addKey(name, value);
while (_xml.readNextStartElement()) {
unexpectedElement(_xml.name(), tag);
}
}
void readSignal(FakeMetaObject::Ptr metaObject)
{
Q_ASSERT(metaObject);
QLatin1String tag("signal");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else {
ignoreAttr(attr);
}
}
if (name.isEmpty()) {
noValidAttr(QLatin1String("name"), tag);
return;
}
FakeMetaMethod method(name);
method.setMethodType(FakeMetaMethod::Signal);
while (_xml.readNextStartElement()) {
if (_xml.name() == QLatin1String("param")) {
readParam(&method);
} else {
unexpectedElement(_xml.name(), tag);
}
}
metaObject->addMethod(method);
}
void readParam(FakeMetaMethod *method)
{
Q_ASSERT(method);
QLatin1String tag("param");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name, type;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else if (attr.name() == QLatin1String("type")) {
type = attr.value().toString();
} else if (attr.name() == QLatin1String("isPointer")) {
} else {
ignoreAttr(attr);
}
}
// note: name attribute is optional
if (type.isEmpty())
noValidAttr(QLatin1String("type"), tag);
method->addParameter(name, type);
while (_xml.readNextStartElement()) {
unexpectedElement(_xml.name(), tag);
}
}
void readMethod(FakeMetaObject::Ptr metaObject)
{
Q_ASSERT(metaObject);
QLatin1String tag("method");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
QString name, type;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("name")) {
name = attr.value().toString();
} else if (attr.name() == QLatin1String("type")) {
type = attr.value().toString();
} else {
ignoreAttr(attr);
}
}
// note: type attribute is optional, in which case it's a void method.
if (name.isEmpty()) {
noValidAttr(QLatin1String("name"), tag);
return;
}
FakeMetaMethod method(name, type);
method.setMethodType(FakeMetaMethod::Slot);
while (_xml.readNextStartElement()) {
if (_xml.name() == QLatin1String("param")) {
readParam(&method);
} else {
unexpectedElement(_xml.name(), tag);
}
}
metaObject->addMethod(method);
}
void readExports(FakeMetaObject::Ptr metaObject)
{
Q_ASSERT(metaObject);
QLatin1String tag("exports");
QLatin1String childTag("export");
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
while (_xml.readNextStartElement()) {
if (_xml.name() == childTag) {
QString type;
QString package;
ComponentVersion version;
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
if (attr.name() == QLatin1String("module")) {
package = attr.value().toString();
} else if (attr.name() == QLatin1String("type")) {
type = attr.value().toString();
} else if (attr.name() == QLatin1String("version")) {
QString versionStr = attr.value().toString();
int dotIdx = versionStr.indexOf('.');
if (dotIdx == -1) {
bool ok = false;
const int major = versionStr.toInt(&ok);
if (!ok) {
invalidAttr(versionStr, QLatin1String("version"), childTag);
continue;
}
version = ComponentVersion(major, ComponentVersion::NoVersion);
} else {
bool ok = false;
const int major = versionStr.left(dotIdx).toInt(&ok);
if (!ok) {
invalidAttr(versionStr, QLatin1String("version"), childTag);
continue;
}
const int minor = versionStr.mid(dotIdx + 1).toInt(&ok);
if (!ok) {
invalidAttr(versionStr, QLatin1String("version"), childTag);
continue;
}
version = ComponentVersion(major, minor);
}
} else {
ignoreAttr(attr);
}
}
metaObject->addExport(type, package, version);
} else {
unexpectedElement(_xml.name(), childTag);
}
_xml.skipCurrentElement(); // the <export> tag should be empty anyhow
}
}
private:
QXmlStreamReader _xml;
QMap<QString, FakeMetaObject::Ptr> *_objects;
};
} // end of anonymous namespace
QmlObjectValue::QmlObjectValue(FakeMetaObject::ConstPtr metaObject, const QString &className,
......
......@@ -239,6 +239,8 @@ void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isM
fmm.setMethodName(readStringBinding(script));
} else if (name == "type") {
fmm.setReturnType(readStringBinding(script));
} else if (name == "revision") {
fmm.setRevision(readIntBinding(script));
} else {
addError(script->firstSourceLocation(), "Expected only name and type script bindings");
return;
......@@ -265,6 +267,7 @@ void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject
bool isPointer = false;
bool isReadonly = false;
bool isList = false;
int revision = 0;
for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) {
UiObjectMember *member = it->member;
......@@ -285,8 +288,10 @@ void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject
isReadonly = readBoolBinding(script);
} else if (id == "isList") {
isList = readBoolBinding(script);
} else if (id == "revision") {
revision = readIntBinding(script);
} else {
addError(script->firstSourceLocation(), "Expected only type, name, isPointer, isReadonly and isList script bindings");
addError(script->firstSourceLocation(), "Expected only type, name, revision, isPointer, isReadonly and isList script bindings");
return;
}
}
......@@ -296,7 +301,7 @@ void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject
return;
}
fmo->addProperty(FakeMetaProperty(name, type, isList, !isReadonly, isPointer));
fmo->addProperty(FakeMetaProperty(name, type, isList, !isReadonly, isPointer, revision));
}
void TypeDescriptionReader::readEnum(UiObjectDefinition *ast, FakeMetaObject::Ptr fmo)
......@@ -403,6 +408,41 @@ bool TypeDescriptionReader::readBoolBinding(AST::UiScriptBinding *ast)
return trueLit;
}
double TypeDescriptionReader::readNumericBinding(AST::UiScriptBinding *ast)
{
if (!ast || !ast->statement) {
addError(ast->colonToken, "Expected numeric literal after colon");
return 0;
}
ExpressionStatement *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
if (!expStmt) {
addError(ast->statement->firstSourceLocation(), "Expected numeric literal after colon");
return 0;
}
NumericLiteral *numericLit = AST::cast<NumericLiteral *>(expStmt->expression);
if (!numericLit) {
addError(expStmt->firstSourceLocation(), "Expected numeric literal after colon");
return 0;
}
return numericLit->value;
}
int TypeDescriptionReader::readIntBinding(AST::UiScriptBinding *ast)
{
double v = readNumericBinding(ast);
int i = (int)v;
if (i != v) {
addError(ast->firstSourceLocation(), "Expected integer after colon");
return 0;
}
return i;