diff options
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 182 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 13 |
2 files changed, 87 insertions, 108 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 89a1774..c5ffeda 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -194,45 +194,76 @@ bool QmlCompiler::isAttachedProperty(const QByteArray &name) return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z'; } -QmlCompiler::StoreInstructionResult -QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, - QmlInstruction &instr, - const QMetaProperty &prop, - int coreIdx, int primitive, - const QString *string) +#define COMPILE_EXCEPTION2(token, desc) \ + { \ + QString exceptionDescription; \ + QmlError error; \ + error.setUrl(output->url); \ + error.setLine(token->location.start.line); \ + error.setColumn(token->location.start.column); \ + QDebug d(&exceptionDescription); \ + d << desc; \ + error.setDescription(exceptionDescription.trimmed()); \ + exceptions << error; \ + return false; \ + } + +#define COMPILE_EXCEPTION(desc) \ + { \ + QString exceptionDescription; \ + QmlError error; \ + error.setUrl(output->url); \ + error.setLine(obj->location.start.line); \ + error.setColumn(obj->location.start.column); \ + QDebug d(&exceptionDescription); \ + d << desc; \ + error.setDescription(exceptionDescription.trimmed()); \ + exceptions << error; \ + return false; \ + } + +#define COMPILE_CHECK(a) \ + { \ + if (!a) return false; \ + } + +bool QmlCompiler::generateStoreInstruction(QmlInstruction &instr, + const QMetaProperty &prop, + int coreIdx, + QmlParser::Value *v) { + QString string = v->value.asScript(); + if (!prop.isWritable()) - return ReadOnly; + COMPILE_EXCEPTION2(v, "Cannot assign literal value to read-only property" << prop.name()); + if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string->toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toLatin1().constData()); } else - value = prop.enumerator().keyToValue(string->toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toLatin1().constData()); if (value == -1) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot assign unknown enumeration to property" << prop.name()); instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = coreIdx; instr.storeInteger.value = value; - return Ok; + return true; } int type = prop.type(); switch(type) { case -1: + { instr.type = QmlInstruction::StoreVariant; instr.storeString.propertyIndex = coreIdx; - if (primitive == -1) - primitive = cdata.indexForString(*string); - instr.storeString.value = primitive; - break; + instr.storeString.value = output->indexForString(string); + } break; case QVariant::String: { instr.type = QmlInstruction::StoreString; instr.storeString.propertyIndex = coreIdx; - if (primitive == -1) - primitive = cdata.indexForString(*string); - instr.storeString.value = primitive; + instr.storeString.value = output->indexForString(string); } break; case QVariant::UInt: @@ -240,9 +271,9 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = coreIdx; bool ok; - int value = string->toUInt(&ok); + int value = string.toUInt(&ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to unsigned integer"); instr.storeInteger.value = value; } break; @@ -251,9 +282,9 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = coreIdx; bool ok; - int value = string->toInt(&ok); + int value = string.toInt(&ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to integer"); instr.storeInteger.value = value; } break; @@ -263,17 +294,17 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, instr.type = QmlInstruction::StoreReal; instr.storeReal.propertyIndex = coreIdx; bool ok; - float value = string->toFloat(&ok); + float value = string.toFloat(&ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to real number"); instr.storeReal.value = value; } break; case QVariant::Color: { - QColor c = QmlStringConverters::colorFromString(*string); + QColor c = QmlStringConverters::colorFromString(string); if (!c.isValid()) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to color"); instr.type = QmlInstruction::StoreColor; instr.storeColor.propertyIndex = coreIdx; instr.storeColor.value = c.rgba(); @@ -281,9 +312,9 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, break; case QVariant::Date: { - QDate d = QDate::fromString(*string, Qt::ISODate); + QDate d = QDate::fromString(string, Qt::ISODate); if (!d.isValid()) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date"); instr.type = QmlInstruction::StoreDate; instr.storeDate.propertyIndex = coreIdx; instr.storeDate.value = d.toJulianDay(); @@ -291,11 +322,11 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, break; case QVariant::Time: { - QTime time = QTime::fromString(*string, Qt::ISODate); + QTime time = QTime::fromString(string, Qt::ISODate); if (!time.isValid()) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to time"); int data[] = { time.hour(), time.minute(), time.second(), time.msec() }; - int index = cdata.indexForInt(data, 4); + int index = output->indexForInt(data, 4); instr.type = QmlInstruction::StoreTime; instr.storeTime.propertyIndex = coreIdx; instr.storeTime.valueIndex = index; @@ -303,15 +334,15 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, break; case QVariant::DateTime: { - QDateTime dateTime = QDateTime::fromString(*string, Qt::ISODate); + QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); if (!dateTime.isValid()) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to date and time"); int data[] = { dateTime.date().toJulianDay(), dateTime.time().hour(), dateTime.time().minute(), dateTime.time().second(), dateTime.time().msec() }; - int index = cdata.indexForInt(data, 5); + int index = output->indexForInt(data, 5); instr.type = QmlInstruction::StoreDateTime; instr.storeDateTime.propertyIndex = coreIdx; instr.storeDateTime.valueIndex = index; @@ -321,11 +352,11 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, case QVariant::PointF: { bool ok; - QPointF point = QmlStringConverters::pointFFromString(*string, &ok); + QPointF point = QmlStringConverters::pointFFromString(string, &ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to point"); float data[] = { point.x(), point.y() }; - int index = cdata.indexForFloat(data, 2); + int index = output->indexForFloat(data, 2); if (type == QVariant::PointF) instr.type = QmlInstruction::StorePointF; else @@ -338,11 +369,11 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, case QVariant::SizeF: { bool ok; - QSizeF size = QmlStringConverters::sizeFFromString(*string, &ok); + QSizeF size = QmlStringConverters::sizeFFromString(string, &ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to size"); float data[] = { size.width(), size.height() }; - int index = cdata.indexForFloat(data, 2); + int index = output->indexForFloat(data, 2); if (type == QVariant::SizeF) instr.type = QmlInstruction::StoreSizeF; else @@ -355,12 +386,12 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, case QVariant::RectF: { bool ok; - QRectF rect = QmlStringConverters::rectFFromString(*string, &ok); + QRectF rect = QmlStringConverters::rectFFromString(string, &ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to rect"); float data[] = { rect.x(), rect.y(), rect.width(), rect.height() }; - int index = cdata.indexForFloat(data, 4); + int index = output->indexForFloat(data, 4); if (type == QVariant::RectF) instr.type = QmlInstruction::StoreRectF; else @@ -372,9 +403,9 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, case QVariant::Bool: { bool ok; - bool b = QmlStringConverters::boolFromString(*string, &ok); + bool b = QmlStringConverters::boolFromString(string, &ok); if (!ok) - return InvalidData; + COMPILE_EXCEPTION2(v, "Cannot convert value" << string << "to boolean"); instr.type = QmlInstruction::StoreBool; instr.storeBool.propertyIndex = coreIdx; instr.storeBool.value = b; @@ -388,24 +419,22 @@ QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata, QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(t); if (converter) { - int index = cdata.customTypeData.count(); + int index = output->customTypeData.count(); instr.type = QmlInstruction::AssignCustomType; instr.assignCustomType.propertyIndex = coreIdx; instr.assignCustomType.valueIndex = index; QmlCompiledData::CustomTypeData data; - if (primitive == -1) - primitive = cdata.indexForString(*string); - data.index = primitive; + data.index = output->indexForString(string); data.type = t; - cdata.customTypeData << data; + output->customTypeData << data; break; } } - return UnknownType; + COMPILE_EXCEPTION2(v, "Cannot assign to property" << prop.name() << "of unknown type" << prop.type()); break; } - return Ok; + return true; } void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory) @@ -424,39 +453,6 @@ void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory) cc->bytecode.clear(); } -#define COMPILE_EXCEPTION2(token, desc) \ - { \ - QString exceptionDescription; \ - QmlError error; \ - error.setUrl(output->url); \ - error.setLine(token->location.start.line); \ - error.setColumn(token->location.start.column); \ - QDebug d(&exceptionDescription); \ - d << desc; \ - error.setDescription(exceptionDescription.trimmed()); \ - exceptions << error; \ - return false; \ - } - -#define COMPILE_EXCEPTION(desc) \ - { \ - QString exceptionDescription; \ - QmlError error; \ - error.setUrl(output->url); \ - error.setLine(obj->location.start.line); \ - error.setColumn(obj->location.start.column); \ - QDebug d(&exceptionDescription); \ - d << desc; \ - error.setDescription(exceptionDescription.trimmed()); \ - exceptions << error; \ - return false; \ - } - -#define COMPILE_CHECK(a) \ - { \ - if (!a) return false; \ - } - bool QmlCompiler::compile(QmlEngine *engine, QmlCompositeTypeData *unit, QmlCompiledComponent *out) @@ -1226,21 +1222,7 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, assign.line = v->location.start.line; if (prop->index != -1) { - QString value = v->primitive(); - StoreInstructionResult r = - generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &value); - - if (r == Ok) { - } else if (r == InvalidData) { - //### we are restricted to a rather generic message here. If we can find a way to move - // the exception into generateStoreInstruction we could potentially have better messages. - // (the problem is that both compile and run exceptions can be generated, though) - COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to property" << obj->metaObject()->property(prop->index).name()); - } else if (r == ReadOnly) { - COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to the read-only property" << obj->metaObject()->property(prop->index).name()); - } else { - COMPILE_EXCEPTION2(prop, "Cannot assign value to property" << obj->metaObject()->property(prop->index).name() << "of unknown type"); - } + COMPILE_CHECK(generateStoreInstruction(assign, obj->metaObject()->property(prop->index), prop->index, v)); } else { COMPILE_EXCEPTION2(prop, "Cannot assign value to non-existant property" << prop->name); } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 3280866..27c4dd2 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -121,14 +121,6 @@ public: static bool isValidId(const QString &); static bool isAttachedProperty(const QByteArray &); - enum StoreInstructionResult { Ok, UnknownType, InvalidData, ReadOnly }; - static StoreInstructionResult - generateStoreInstruction(QmlCompiledData &data, - QmlInstruction &instr, - const QMetaProperty &prop, - int index, - int primitive, - const QString *string); private: void reset(QmlCompiledComponent *, bool); @@ -163,6 +155,11 @@ private: QmlParser::Value *value, int ctxt); + bool generateStoreInstruction(QmlInstruction &instr, + const QMetaProperty &prop, + int index, + QmlParser::Value *value); + bool compileDynamicMeta(QmlParser::Object *obj); bool compileBinding(const QString &, QmlParser::Property *prop, int ctxt, const QMetaObject *, qint64); |