diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-15 15:49:23 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-27 18:50:14 +0100 |
commit | f6e90ba533b9b4b98cfcae3d31731c1cb794ee77 (patch) | |
tree | dbde1d4f79cb8f7be325ba69b058eb7530c7394b | |
parent | c6c34db202ce504cff1e6cc71d9f809a8365e066 (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.cpp | 4 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 14 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmlparser/tst_qqmlparser.cpp | 42 |
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" |