diff options
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 247 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser_p.h | 5 |
4 files changed, 126 insertions, 148 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d36c7f21ac..809f0033e9 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -251,10 +251,16 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() } } + { // Sanity check property bindings - QQmlPropertyValidator validator(this, engine, *imports(), compilationUnit); - if (!validator.validate()) - return nullptr; + QQmlPropertyValidator validator(engine, *imports(), compilationUnit); + QVector<QQmlCompileError> errors = validator.validate(); + if (!errors.isEmpty()) { + for (const QQmlCompileError &error: qAsConst(errors)) + recordError(error); + return nullptr; + } + } // Collect some data for instantiation later. int bindingCount = 0; @@ -1333,9 +1339,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex) } -QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit) - : QQmlCompilePass(typeCompiler) - , enginePrivate(enginePrivate) +QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit) + : enginePrivate(enginePrivate) , imports(imports) , qmlUnit(compilationUnit->data) , resolvedTypes(compilationUnit->resolvedTypes) @@ -1345,7 +1350,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, QQm bindingPropertyDataPerObject->resize(qmlUnit->nObjects); } -bool QQmlPropertyValidator::validate() +QVector<QQmlCompileError> QQmlPropertyValidator::validate() { return validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0); } @@ -1368,7 +1373,7 @@ struct BindingFinder } }; -bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const +QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const { const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex); @@ -1381,7 +1386,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex); if (!propertyCache) - return true; + return QVector<QQmlCompileError>(); QStringList deferredPropertyNames; { @@ -1413,8 +1418,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD continue; if (populatingValueTypeGroupProperty) { - recordError(binding->location, tr("Property assignment expected")); - return false; + return recordError(binding->location, tr("Property assignment expected")); } GroupPropertyVector::const_iterator pos = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, BindingFinder()); @@ -1469,14 +1473,14 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD QString typeName = stringAt(obj->inheritedTypeNameIndex); auto *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex); if (objectType && objectType->type) { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type->module()).arg(objectType->majorVersion).arg(objectType->minorVersion)); + return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type->module()).arg(objectType->majorVersion).arg(objectType->minorVersion)); } else { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); + return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); } } } else { if (isGroupProperty) - COMPILE_EXCEPTION(binding, tr("Cannot assign a value directly to a grouped property")); + return recordError(binding->location, tr("Cannot assign a value directly to a grouped property")); pd = defaultProperty; name = defaultPropertyName; @@ -1491,16 +1495,14 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD QQmlImportNamespace *typeNamespace = 0; imports.resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace); if (typeNamespace) - recordError(binding->location, tr("Invalid use of namespace")); - else - recordError(binding->location, tr("Invalid attached object assignment")); - return false; + return recordError(binding->location, tr("Invalid use of namespace")); + return recordError(binding->location, tr("Invalid attached object assignment")); } if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) { - const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)); - if (!subObjectValid) - return false; + const QVector<QQmlCompileError> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)); + if (!subObjectValidatorErrors.isEmpty()) + return subObjectValidatorErrors; } // Signal handlers were resolved and checked earlier in the signal handler conversion pass. @@ -1510,8 +1512,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) { - recordError(binding->location, tr("Attached properties cannot be used here")); - return false; + return recordError(binding->location, tr("Attached properties cannot be used here")); } continue; } @@ -1527,10 +1528,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD ) { if (assigningToGroupProperty && binding->type < QV4::CompiledData::Binding::Type_Object) - recordError(binding->valueLocation, tr("Cannot assign a value directly to a grouped property")); - else - recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); - return false; + return recordError(binding->valueLocation, tr("Cannot assign a value directly to a grouped property")); + return recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); } if (!pd->isQList() && (binding->flags & QV4::CompiledData::Binding::IsListItem)) { @@ -1539,8 +1538,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD error = tr( "Cannot assign multiple values to a script property"); else error = tr( "Cannot assign multiple values to a singular property"); - recordError(binding->valueLocation, error); - return false; + return recordError(binding->valueLocation, error); } if (!bindingToDefaultProperty @@ -1552,33 +1550,30 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD loc = (*assignedGroupProperty)->valueLocation; if (pd && QQmlValueTypeFactory::isValueType(pd->propType)) - recordError(loc, tr("Property has already been assigned a value")); - else - recordError(loc, tr("Cannot assign a value directly to a grouped property")); - return false; + return recordError(loc, tr("Property has already been assigned a value")); + return recordError(loc, tr("Cannot assign a value directly to a grouped property")); } if (binding->type < QV4::CompiledData::Binding::Type_Script) { - if (!validateLiteralBinding(propertyCache, pd, binding)) - return false; + QQmlCompileError bindingError = validateLiteralBinding(propertyCache, pd, binding); + if (bindingError.isSet()) + return recordError(bindingError); } else if (binding->type == QV4::CompiledData::Binding::Type_Object) { - if (!validateObjectBinding(pd, name, binding)) - return false; + QQmlCompileError bindingError = validateObjectBinding(pd, name, binding); + if (bindingError.isSet()) + return recordError(bindingError); } else if (binding->isGroupProperty()) { if (QQmlValueTypeFactory::isValueType(pd->propType)) { if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)) { if (!pd->isWritable()) { - recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); - return false; + return recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); } } else { - recordError(binding->location, tr("Invalid grouped property access")); - return false; + return recordError(binding->location, tr("Invalid grouped property access")); } } else { if (!enginePrivate->propertyCacheForType(pd->propType)) { - recordError(binding->location, tr("Invalid grouped property access")); - return false; + return recordError(binding->location, tr("Invalid grouped property access")); } } } @@ -1588,9 +1583,9 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD continue; } if (bindingToDefaultProperty) { - COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent default property")); + return recordError(binding->location, tr("Cannot assign to non-existent default property")); } else { - COMPILE_EXCEPTION(binding, tr("Cannot assign to non-existent property \"%1\"").arg(name)); + return recordError(binding->location, tr("Cannot assign to non-existent property \"%1\"").arg(name)); } } } @@ -1609,29 +1604,28 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD customParser->validator = 0; customParser->engine = 0; customParser->imports = (QQmlImports*)0; - const QList<QQmlError> parserErrors = customParser->errors(); - if (!parserErrors.isEmpty()) { - foreach (const QQmlError &error, parserErrors) - compiler->recordError(error); - return false; - } + QVector<QQmlCompileError> parserErrors = customParser->errors(); + if (!parserErrors.isEmpty()) + return parserErrors; } (*bindingPropertyDataPerObject)[objectIndex] = collectedBindingPropertyData; - return true; + QVector<QQmlCompileError> noError; + return noError; } -bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const +QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const { if (property->isQList()) { - recordError(binding->valueLocation, tr("Cannot assign primitives to lists")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Cannot assign primitives to lists")); } + QQmlCompileError noError; + if (property->isEnum()) { if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) - return true; + return noError; QString value = binding->valueAsString(qmlUnit); QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex); @@ -1642,10 +1636,9 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa p.enumerator().keyToValue(value.toUtf8().constData(), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration")); } - return true; + return noError; } switch (property->propType) { @@ -1653,29 +1646,25 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa break; case QVariant::String: { if (!binding->evaluatesToString()) { - recordError(binding->valueLocation, tr("Invalid property assignment: string expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: string expected")); } } break; case QVariant::StringList: { if (!binding->evaluatesToString()) { - recordError(binding->valueLocation, tr("Invalid property assignment: string or string list expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: string or string list expected")); } } break; case QVariant::ByteArray: { if (binding->type != QV4::CompiledData::Binding::Type_String) { - recordError(binding->valueLocation, tr("Invalid property assignment: byte array expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: byte array expected")); } } break; case QVariant::Url: { if (binding->type != QV4::CompiledData::Binding::Type_String) { - recordError(binding->valueLocation, tr("Invalid property assignment: url expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: url expected")); } } break; @@ -1683,33 +1672,29 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa if (binding->type == QV4::CompiledData::Binding::Type_Number) { double d = binding->valueAsNumber(); if (double(uint(d)) == d) - return true; + return noError; } - recordError(binding->valueLocation, tr("Invalid property assignment: unsigned int expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unsigned int expected")); } break; case QVariant::Int: { if (binding->type == QV4::CompiledData::Binding::Type_Number) { double d = binding->valueAsNumber(); if (double(int(d)) == d) - return true; + return noError; } - recordError(binding->valueLocation, tr("Invalid property assignment: int expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: int expected")); } break; case QMetaType::Float: { if (binding->type != QV4::CompiledData::Binding::Type_Number) { - recordError(binding->valueLocation, tr("Invalid property assignment: number expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: number expected")); } } break; case QVariant::Double: { if (binding->type != QV4::CompiledData::Binding::Type_Number) { - recordError(binding->valueLocation, tr("Invalid property assignment: number expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: number expected")); } } break; @@ -1717,8 +1702,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::rgbaFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: color expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: color expected")); } } break; @@ -1727,8 +1711,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::dateFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: date expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: date expected")); } } break; @@ -1736,8 +1719,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::timeFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: time expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: time expected")); } } break; @@ -1745,8 +1727,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::dateTimeFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: datetime expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: datetime expected")); } } break; @@ -1755,8 +1736,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: point expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: point expected")); } } break; @@ -1764,8 +1744,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: point expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: point expected")); } } break; @@ -1773,8 +1752,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: size expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: size expected")); } } break; @@ -1782,8 +1760,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: size expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: size expected")); } } break; @@ -1791,8 +1768,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: rect expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: rect expected")); } } break; @@ -1800,15 +1776,13 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa bool ok = false; QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok); if (!ok) { - recordError(binding->valueLocation, tr("Invalid property assignment: point expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: point expected")); } } break; case QVariant::Bool: { if (binding->type != QV4::CompiledData::Binding::Type_Boolean) { - recordError(binding->valueLocation, tr("Invalid property assignment: boolean expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: boolean expected")); } } break; @@ -1819,8 +1793,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa float zy; } vec; if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) { - recordError(binding->valueLocation, tr("Invalid property assignment: 3D vector expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: 3D vector expected")); } } break; @@ -1832,20 +1805,17 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa float wp; } vec; if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) { - recordError(binding->valueLocation, tr("Invalid property assignment: 4D vector expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: 4D vector expected")); } } break; case QVariant::RegExp: - recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax")); default: { // generate single literal value assignment to a list property if required if (property->propType == qMetaTypeId<QList<qreal> >()) { if (binding->type != QV4::CompiledData::Binding::Type_Number) { - recordError(binding->valueLocation, tr("Invalid property assignment: number or array of numbers expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: number or array of numbers expected")); } break; } else if (property->propType == qMetaTypeId<QList<int> >()) { @@ -1856,24 +1826,21 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa ok = false; } if (!ok) - recordError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected")); + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected")); break; } else if (property->propType == qMetaTypeId<QList<bool> >()) { if (binding->type != QV4::CompiledData::Binding::Type_Boolean) { - recordError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected")); } break; } else if (property->propType == qMetaTypeId<QList<QUrl> >()) { if (binding->type != QV4::CompiledData::Binding::Type_String) { - recordError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected")); } break; } else if (property->propType == qMetaTypeId<QList<QString> >()) { if (!binding->evaluatesToString()) { - recordError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected")); } break; } else if (property->propType == qMetaTypeId<QJSValue>()) { @@ -1885,13 +1852,12 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa // otherwise, try a custom type assignment QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType); if (!converter) { - recordError(binding->valueLocation, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType)))); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType)))); } } break; } - return true; + return noError; } /*! @@ -1910,8 +1876,24 @@ bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo) const return false; } -bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const +QVector<QQmlCompileError> QQmlPropertyValidator::recordError(const QV4::CompiledData::Location &location, const QString &description) const { + QVector<QQmlCompileError> errors; + errors.append(QQmlCompileError(location, description)); + return errors; +} + +QVector<QQmlCompileError> QQmlPropertyValidator::recordError(const QQmlCompileError &error) const +{ + QVector<QQmlCompileError> errors; + errors.append(error); + return errors; +} + +QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const +{ + QQmlCompileError noError; + if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object); @@ -1936,40 +1918,36 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co } if (!isValueSource && !isPropertyInterceptor) { - recordError(binding->valueLocation, tr("\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName)); - return false; + return QQmlCompileError(binding->valueLocation, tr("\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName)); } - return true; + return noError; } if (QQmlMetaType::isInterface(property->propType)) { // Can only check at instantiation time if the created sub-object successfully casts to the // target interface. - return true; + return noError; } else if (property->propType == QMetaType::QVariant) { // We can convert everything to QVariant :) - return true; + return noError; } else if (property->isQList()) { const int listType = enginePrivate->listType(property->propType); if (!QQmlMetaType::isInterface(listType)) { QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex); if (!canCoerce(listType, source)) { - recordError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName)); - return false; + return QQmlCompileError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName)); } } - return true; + return noError; } else if (qmlUnit->objectAt(binding->value.objectIndex)->flags & QV4::CompiledData::Object::IsComponent) { - return true; + return noError; } else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) { - return true; + return noError; } else if (QQmlValueTypeFactory::isValueType(property->propType)) { - recordError(binding->location, tr("Unexpected object assignment")); - return false; + return QQmlCompileError(binding->location, tr("Unexpected object assignment")); } else if (property->propType == qMetaTypeId<QQmlScriptString>()) { - recordError(binding->valueLocation, tr("Invalid property assignment: script expected")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected")); } else { // We want to raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might @@ -1988,11 +1966,10 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co } if (!isAssignable) { - recordError(binding->valueLocation, tr("Cannot assign object to property")); - return false; + return QQmlCompileError(binding->valueLocation, tr("Cannot assign object to property")); } } - return true; + return noError; } QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen) diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 17125a69f0..6fddd37111 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -299,21 +299,25 @@ private: bool _seenObjectWithId; }; -class QQmlPropertyValidator : public QQmlCompilePass +class QQmlPropertyValidator { Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator) public: - QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit); + QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, QV4::CompiledData::CompilationUnit *compilationUnit); - bool validate(); + QVector<QQmlCompileError> validate(); private: - bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const; - bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const; - bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const; + QVector<QQmlCompileError> validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const; + QQmlCompileError validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const; + QQmlCompileError validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const; bool canCoerce(int to, QQmlPropertyCache *fromMo) const; + QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const Q_REQUIRED_RESULT; + QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const Q_REQUIRED_RESULT; + QString stringAt(int index) const { return qmlUnit->stringAt(index); } + QQmlEnginePrivate *enginePrivate; const QQmlImports &imports; const QV4::CompiledData::Unit *qmlUnit; diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 30eed4d551..85c91a592a 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -100,11 +100,7 @@ void QQmlCustomParser::clearErrors() */ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description) { - QQmlError error; - error.setLine(location.line); - error.setColumn(location.column); - error.setDescription(description); - exceptions << error; + exceptions << QQmlCompileError(location, description); } struct StaticQtMetaObject : public QObject diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index d1ed61defe..5eb409990d 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -54,6 +54,7 @@ #include "qqmlmetatype_p.h" #include "qqmlerror.h" #include "qqmlbinding_p.h" +#include <private/qqmltypecompiler_p.h> #include <QtCore/qbytearray.h> #include <QtCore/qxmlstream.h> @@ -83,7 +84,7 @@ public: virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) = 0; virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) = 0; - QList<QQmlError> errors() const { return exceptions; } + QVector<QQmlCompileError> errors() const { return exceptions; } protected: void error(const QV4::CompiledData::Binding *binding, const QString& description) @@ -97,7 +98,7 @@ protected: const QMetaObject *resolveType(const QString&) const; private: - QList<QQmlError> exceptions; + QVector<QQmlCompileError> exceptions; QQmlEnginePrivate *engine; const QQmlPropertyValidator *validator; Flags m_flags; |