[new compiler] Implement compile time error handling for lists
authorSimon Hausmann <simon.hausmann@digia.com>
Mon, 10 Feb 2014 19:55:20 +0000 (20:55 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 17 Feb 2014 07:49:01 +0000 (08:49 +0100)
Change-Id: Ic26e8a01995c296ab9cd4deb8714a5cf17cfdf2b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qqmltypecompiler.cpp
src/qml/compiler/qqmltypecompiler_p.h

index dae57fe..ce755d1 100644 (file)
@@ -1564,6 +1564,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
 
 bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
 {
+    if (property->isQList()) {
+        recordError(binding->valueLocation, tr("Cannot assign primitives to lists"));
+        return false;
+    }
+
     if (property->isEnum()) {
         if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum)
             return true;
@@ -1829,6 +1834,22 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
     return true;
 }
 
+/*!
+    Returns true if from can be assigned to a (QObject) property of type
+    to.
+*/
+bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
+{
+    QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
+
+    while (fromMo) {
+        if (fromMo == toMo)
+            return true;
+        fromMo = fromMo->parent();
+    }
+    return false;
+}
+
 bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding)
 {
     if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
@@ -1873,7 +1894,14 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
         // We can convert everything to QVariant :)
         return true;
     } else if (property->isQList()) {
-        // ### TODO: list error handling
+        const int listType = enginePrivate->listType(property->propType);
+        if (!QQmlMetaType::isInterface(listType)) {
+            QQmlPropertyCache *source = propertyCaches.value(binding->value.objectIndex);
+            if (!canCoerce(listType, source)) {
+                recordError(binding->valueLocation, tr("Cannot assign object to list"));
+                return false;
+            }
+        }
         return true;
     } else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
         return true;
index 2e97d13..0a20e0d 100644 (file)
@@ -232,6 +232,8 @@ private:
 
     bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
 
+    bool canCoerce(int to, QQmlPropertyCache *fromMo);
+
     QQmlEnginePrivate *enginePrivate;
     const QV4::CompiledData::QmlUnit *qmlUnit;
     const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;