Fix invalid alias error reporting in new compiler
authorSimon Hausmann <simon.hausmann@digia.com>
Mon, 30 Sep 2013 07:41:35 +0000 (09:41 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 30 Sep 2013 16:23:17 +0000 (18:23 +0200)
Match exactly the VME code path by reporting the right type of error
as well as the right hand side of the alias binding if necessary.

Change-Id: I35d192a20641e0acbf25d20f3dc5fb53cc7cbae5
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qqmlcodegenerator.cpp
src/qml/compiler/qqmlcodegenerator_p.h
src/qml/compiler/qv4compileddata_p.h
src/qml/qml/qqmlobjectcreator.cpp

index b257d2d..2394b07 100644 (file)
@@ -634,15 +634,33 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
             if (!node->statement && !node->binding)
                 COMPILE_EXCEPTION(loc, tr("No property alias location"));
 
+            AST::SourceLocation rhsLoc;
+            if (node->binding)
+                rhsLoc = node->binding->firstSourceLocation();
+            else if (node->statement)
+                rhsLoc = node->statement->firstSourceLocation();
+            else
+                rhsLoc = node->semicolonToken;
+            property->aliasLocation.line = rhsLoc.startLine;
+            property->aliasLocation.column = rhsLoc.startColumn;
+
             QStringList alias;
-            if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement*>(node->statement))
-                alias = astNodeToStringList(stmt->expression);
 
-            if (node->binding || alias.isEmpty())
-                COMPILE_EXCEPTION(loc, tr("Invalid alias location"));
+            if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement*>(node->statement)) {
+                alias = astNodeToStringList(stmt->expression);
+                if (alias.isEmpty()) {
+                    if (isStatementNodeScript(node->statement)) {
+                        COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+                    } else {
+                        COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
+                    }
+                }
+            } else {
+                COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+            }
 
-             if (alias.count() < 1 || alias.count() > 3)
-                COMPILE_EXCEPTION(loc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+            if (alias.count() < 1 || alias.count() > 3)
+                COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
 
              property->aliasIdValueIndex = registerString(alias.first());
 
@@ -987,6 +1005,31 @@ QQmlScript::LocationSpan QQmlCodeGenerator::location(AST::SourceLocation start,
     return rv;
 }
 
+bool QQmlCodeGenerator::isStatementNodeScript(AST::Statement *statement)
+{
+    if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(statement)) {
+        AST::ExpressionNode *expr = stmt->expression;
+        if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr))
+            return false;
+        else if (expr->kind == AST::Node::Kind_TrueLiteral)
+            return false;
+        else if (expr->kind == AST::Node::Kind_FalseLiteral)
+            return false;
+        else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr))
+            return false;
+        else {
+
+            if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
+               if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+                   return false;
+               }
+            }
+        }
+    }
+
+    return true;
+}
+
 QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output)
 {
     jsUnitGenerator = &output.jsGenerator;
index 9273892..ec75c38 100644 (file)
@@ -247,6 +247,8 @@ public:
 
     QString stringAt(int index) const { return jsGenerator->strings.at(index); }
 
+    static bool isStatementNodeScript(AST::Statement *statement);
+
     QList<QQmlError> errors;
 
     QList<QV4::CompiledData::Import*> _imports;
index 9186086..5159ac5 100644 (file)
@@ -336,6 +336,7 @@ struct Property
     quint32 aliasPropertyValueIndex;
     quint32 flags; // readonly
     Location location;
+    Location aliasLocation; // If type == Alias
 };
 
 struct Object
index 1882d35..e41248b 100644 (file)
@@ -1552,8 +1552,10 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
 
             const int idIndex = p->aliasIdValueIndex;
             const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
-            if (targetObjectIndex == -1)
-                COMPILE_EXCEPTION(p, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
+            if (targetObjectIndex == -1) {
+                recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
+                return false;
+            }
             const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
             Q_ASSERT(targetId != -1);
 
@@ -1596,8 +1598,10 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
                 QtQml::PropertyResolver resolver(targetCache);
 
                 QQmlPropertyData *targetProperty = resolver.property(property.toString());
-                if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF)
-                    COMPILE_EXCEPTION(p, tr("Invalid alias location"));
+                if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
+                    recordError(p->aliasLocation, tr("Invalid alias location"));
+                    return false;
+                }
 
                 propIdx = targetProperty->coreIndex;
                 type = targetProperty->propType;
@@ -1608,15 +1612,19 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
 
                 if (!subProperty.isEmpty()) {
                     QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
-                    if (!valueType)
-                        COMPILE_EXCEPTION(p, tr("Invalid alias location"));
+                    if (!valueType) {
+                        recordError(p->aliasLocation, tr("Invalid alias location"));
+                        return false;
+                    }
 
                     propType = type;
 
                     int valueTypeIndex =
                         valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
-                    if (valueTypeIndex == -1)
-                        COMPILE_EXCEPTION(p, tr("Invalid alias location"));
+                    if (valueTypeIndex == -1) {
+                        recordError(p->aliasLocation, tr("Invalid alias location"));
+                        return false;
+                    }
                     Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
 
                     propIdx |= (valueTypeIndex << 16);