aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-11-15 15:49:23 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-11-27 18:50:14 +0100
commitf6e90ba533b9b4b98cfcae3d31731c1cb794ee77 (patch)
treedbde1d4f79cb8f7be325ba69b058eb7530c7394b
parentc6c34db202ce504cff1e6cc71d9f809a8365e066 (diff)
Add (and ignore for now) type assertions to QML
You can write "(something as Foo)" to give hints to any tools that you expect something to be a Foo at this place. This is not a conversion and ignored at runtime for now. Eventually the compiler will verify that the type assertions are plausible and error out if they aren't. Change-Id: I21c8705bb387f7ab2cbc153293dbf477663afe87 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/parser/qqmljs.g14
-rw-r--r--src/qml/parser/qqmljsast_p.h1
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp42
4 files changed, 60 insertions, 1 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index c43ea64e2e..fff6a2fe4c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1497,7 +1497,9 @@ bool Codegen::visit(BinaryExpression *ast)
break;
}
-
+ case QSOperator::As:
+ setExprResult(left);
+ break;
} // switch
return false;
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index f7b528ce13..ea105e7e22 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -2513,6 +2513,20 @@ RelationalExpression_In: RelationalExpression_In T_IN ShiftExpression;
} break;
./
+TypeAssertExpression_In: RelationalExpression_In T_AS Type;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+TypeAssertExpression: RelationalExpression T_AS Type;
+/.
+ case $rule_number: {
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::As, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+RelationalExpression_In: TypeAssertExpression_In;
+RelationalExpression: TypeAssertExpression;
+
EqualityExpression_In: RelationalExpression_In;
EqualityExpression: RelationalExpression;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index fcf9933e67..bc0a467f40 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -104,6 +104,7 @@ enum Op {
URShift,
InplaceURightShift,
InplaceXor,
+ As,
Invalid
};
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index 4ba6a709df..76b56bd303 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -63,6 +63,8 @@ private slots:
void disallowedTypeAnnotations_data();
void disallowedTypeAnnotations();
void semicolonPartOfExpressionStatement();
+ void typeAssertion_data();
+ void typeAssertion();
private:
QStringList excludedDirs;
@@ -479,6 +481,46 @@ void tst_qqmlparser::semicolonPartOfExpressionStatement()
QVERIFY(observer.endsWithSemicolon);
}
+void tst_qqmlparser::typeAssertion_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addRow("as A")
+ << QString::fromLatin1("A { onStuff: (b as A).happen() }");
+ QTest::addRow("as double paren")
+ << QString::fromLatin1("A { onStuff: console.log((12 as double)); }");
+ QTest::addRow("as double noparen")
+ << QString::fromLatin1("A { onStuff: console.log(12 as double); }");
+ QTest::addRow("property as double")
+ << QString::fromLatin1("A { prop: (12 as double); }");
+ QTest::addRow("property noparen as double")
+ << QString::fromLatin1("A { prop: 12 as double; }");
+
+ // rabbits cannot be discerned from types on a syntactical level.
+ // We could detect this on a semantical level, once we implement type assertions there.
+
+ QTest::addRow("as rabbit")
+ << QString::fromLatin1("A { onStuff: (b as rabbit).happen() }");
+ QTest::addRow("as rabbit paren")
+ << QString::fromLatin1("A { onStuff: console.log((12 as rabbit)); }");
+ QTest::addRow("as rabbit noparen")
+ << QString::fromLatin1("A { onStuff: console.log(12 as rabbit); }");
+ QTest::addRow("property as rabbit")
+ << QString::fromLatin1("A { prop: (12 as rabbit); }");
+ QTest::addRow("property noparen as rabbit")
+ << QString::fromLatin1("A { prop: 12 as rabbit; }");
+}
+
+void tst_qqmlparser::typeAssertion()
+{
+ QFETCH(QString, expression);
+
+ QQmlJS::Engine engine;
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(expression, 1);
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(parser.parse());
+}
+
QTEST_MAIN(tst_qqmlparser)
#include "tst_qqmlparser.moc"