From db02cd168b6a16801f97e0e20c5e18f6fdb80232 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Fri, 18 Nov 2011 18:26:29 +0400 Subject: [PATCH] Added support for nullable types in is check. --- .../google/dart/compiler/util/AstUtil.java | 8 +++++ .../k2js/translate/ExpressionVisitor.java | 5 ++-- .../k2js/translate/PatternTranslator.java | 26 ++++++++++++++-- .../k2js/translate/TranslationUtils.java | 30 +++++++++++++++++++ .../k2js/translate/WhenTranslator.java | 6 ++-- .../k2js/test/PatternMatchingTest.java | 5 ++++ .../cases/matchNullableType.kt | 13 ++++++++ 7 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 translator/src/org/jetbrains/k2js/translate/TranslationUtils.java create mode 100644 translator/testFiles/patternMatching/cases/matchNullableType.kt diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java index b238bd4e9b1..0f34308d100 100644 --- a/js/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/src/com/google/dart/compiler/util/AstUtil.java @@ -281,4 +281,12 @@ public class AstUtil { assert statement instanceof JsExprStmt : "Cannot extract exprssion form statement: " + statement; return (((JsExprStmt) statement).getExpression()); } + + public static JsBinaryOperation and(JsExpression op1, JsExpression op2) { + return new JsBinaryOperation(JsBinaryOperator.AND, op1, op2); + } + + public static JsBinaryOperation or(JsExpression op1, JsExpression op2) { + return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2); + } } diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index b05204f6ede..f74bfd8f81d 100644 --- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -342,10 +342,9 @@ public final class ExpressionVisitor extends TranslatorVisitor { @NotNull TranslationContext context) { JsExpression receiver = translateReceiver(expression, context); JsNullLiteral nullLiteral = context.program().getNullLiteral(); - JsBinaryOperation nullCheck = new JsBinaryOperation - (JsBinaryOperator.NEQ, receiver, nullLiteral); JsExpression thenExpression = translateQualifiedExpression(expression, context); - return new JsConditional(nullCheck, thenExpression, nullLiteral); + return new JsConditional(TranslationUtils.notNullCheck(receiver, context), + thenExpression, nullLiteral); } @Override diff --git a/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java b/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java index 2de2defcff8..0da4906018a 100644 --- a/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/PatternTranslator.java @@ -52,14 +52,36 @@ public final class PatternTranslator extends AbstractTranslator { @NotNull private JsExpression translateTypePattern(@NotNull JsExpression expressionToMatch, @NotNull JetTypePattern pattern) { - return AstUtil.newInvocation(Namer.isOperationReference(), expressionToMatch, getClassReference(pattern)); + + JsInvocation isCheck = AstUtil.newInvocation(Namer.isOperationReference(), + expressionToMatch, getClassReference(pattern)); + if (isNullable(pattern)) { + return addNullCheck(expressionToMatch, isCheck); + } + return isCheck; + } + + @NotNull + private JsExpression addNullCheck(@NotNull JsExpression expressionToMatch, @NotNull JsInvocation isCheck) { + return AstUtil.or(TranslationUtils.isNullCheck(expressionToMatch, translationContext()), isCheck); + } + + private boolean isNullable(JetTypePattern pattern) { + return BindingUtils.getTypeByReference(translationContext().bindingContext(), + getTypeReference(pattern)).isNullable(); } @NotNull private JsExpression getClassReference(@NotNull JetTypePattern pattern) { + JetTypeReference typeReference = getTypeReference(pattern); + return getClassNameReferenceForTypeReference(typeReference); + } + + @NotNull + private JetTypeReference getTypeReference(@NotNull JetTypePattern pattern) { JetTypeReference typeReference = pattern.getTypeReference(); assert typeReference != null : "Type pattern should contain a type reference"; - return getClassNameReferenceForTypeReference(typeReference); + return typeReference; } @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java b/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java new file mode 100644 index 00000000000..f5d36e3b248 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/TranslationUtils.java @@ -0,0 +1,30 @@ +package org.jetbrains.k2js.translate; + +import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; +import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsNullLiteral; +import org.jetbrains.annotations.NotNull; + +/** + * @author Talanov Pavel + */ +public final class TranslationUtils { + + @NotNull + static public JsBinaryOperation notNullCheck(@NotNull JsExpression expressionToCheck, + @NotNull TranslationContext context) { + JsNullLiteral nullLiteral = context.program().getNullLiteral(); + return new JsBinaryOperation + (JsBinaryOperator.NEQ, expressionToCheck, nullLiteral); + } + + @NotNull + static public JsBinaryOperation isNullCheck(@NotNull JsExpression expressionToCheck, + @NotNull TranslationContext context) { + JsNullLiteral nullLiteral = context.program().getNullLiteral(); + return new JsBinaryOperation + (JsBinaryOperator.REF_EQ, expressionToCheck, nullLiteral); + } + +} diff --git a/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java index 9f71f74af2e..4f3c467bb55 100644 --- a/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/WhenTranslator.java @@ -103,7 +103,6 @@ public class WhenTranslator extends AbstractTranslator { return Translation.translateAsStatement(expressionToExecute, translationContext()); } - //TODO: ask what these conditions mean @NotNull private JsExpression translateConditions(@NotNull JetWhenEntry entry) { List conditions = new ArrayList(); @@ -127,11 +126,10 @@ public class WhenTranslator extends AbstractTranslator { @NotNull private JsExpression addCaseCondition(@Nullable JsExpression current, @NotNull JsExpression condition) { if (current == null) { - current = condition; + return condition; } else { - current = new JsBinaryOperation(JsBinaryOperator.OR, current, condition); + return AstUtil.or(current, condition); } - return current; } diff --git a/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java index 74d0996ba70..caa059f74d5 100644 --- a/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java +++ b/translator/test/org/jetbrains/k2js/test/PatternMatchingTest.java @@ -49,4 +49,9 @@ public final class PatternMatchingTest extends IncludeLibraryTest { testFunctionOutput("multipleCases.kt", "foo", "box", 2.0); } + @Test + public void matchNullableType() throws Exception { + testFooBoxIsTrue("matchNullableType.kt"); + } + } diff --git a/translator/testFiles/patternMatching/cases/matchNullableType.kt b/translator/testFiles/patternMatching/cases/matchNullableType.kt new file mode 100644 index 00000000000..65de099135a --- /dev/null +++ b/translator/testFiles/patternMatching/cases/matchNullableType.kt @@ -0,0 +1,13 @@ +namespace foo + +class A() { + +} + +fun box() : Boolean { + var a = null : A? + when(a) { + is A? => return true + else => return false + } +} \ No newline at end of file