JS Back-end does not handle complex patterns any more
#KT-2359 In Progress
This commit is contained in:
@@ -48,10 +48,6 @@ public final class PatternMatchingTest extends SingleFileTranslationTest {
|
|||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWhenNotValue() throws Exception {
|
|
||||||
fooBoxTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWhenValueOrType() throws Exception {
|
public void testWhenValueOrType() throws Exception {
|
||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-39
@@ -31,8 +31,6 @@ import org.jetbrains.k2js.translate.utils.BindingUtils;
|
|||||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getPattern;
|
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getTypeReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
@@ -51,45 +49,30 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression translateIsExpression(@NotNull JetIsExpression expression) {
|
public JsExpression translateIsExpression(@NotNull JetIsExpression expression) {
|
||||||
JsExpression left = Translation.translateAsExpression(expression.getLeftHandSide(), context());
|
JsExpression left = Translation.translateAsExpression(expression.getLeftHandSide(), context());
|
||||||
JetPattern pattern = getPattern(expression);
|
JetTypeReference typeReference = expression.getTypeRef();
|
||||||
JsExpression resultingExpression = translatePattern(pattern, left);
|
assert typeReference != null;
|
||||||
|
JsExpression result = translateIsCheck(left, typeReference);
|
||||||
if (expression.isNegated()) {
|
if (expression.isNegated()) {
|
||||||
return negated(resultingExpression);
|
return negated(result);
|
||||||
}
|
}
|
||||||
return resultingExpression;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsExpression translatePattern(@NotNull JetPattern pattern, @Nullable JsExpression expressionToMatch) {
|
public JsExpression translateIsCheck(@NotNull JsExpression subject, @NotNull JetTypeReference typeReference) {
|
||||||
if (expressionToMatch == null) {
|
JsExpression result = translateAsIntrinsicTypeCheck(subject, typeReference);
|
||||||
assert pattern instanceof JetExpressionPattern : "When using when without parameters we can have only expression patterns";
|
|
||||||
return translateExpressionForExpressionPattern((JetExpressionPattern)pattern);
|
|
||||||
}
|
|
||||||
if (pattern instanceof JetTypePattern) {
|
|
||||||
return translateTypePattern(expressionToMatch, (JetTypePattern)pattern);
|
|
||||||
}
|
|
||||||
if (pattern instanceof JetExpressionPattern) {
|
|
||||||
return translateExpressionPattern(expressionToMatch, (JetExpressionPattern)pattern);
|
|
||||||
}
|
|
||||||
throw new AssertionError("Unsupported pattern type " + pattern.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression translateTypePattern(@NotNull JsExpression expressionToMatch,
|
|
||||||
@NotNull JetTypePattern pattern) {
|
|
||||||
JsExpression result = translateAsIntrinsicTypeCheck(expressionToMatch, pattern);
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return translateAsIsCheck(expressionToMatch, pattern);
|
return translateAsIsCheck(subject, typeReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translateAsIsCheck(@NotNull JsExpression expressionToMatch,
|
private JsExpression translateAsIsCheck(@NotNull JsExpression expressionToMatch,
|
||||||
@NotNull JetTypePattern pattern) {
|
@NotNull JetTypeReference typeReference) {
|
||||||
JsInvocation isCheck = new JsInvocation(context().namer().isOperationReference(),
|
JsInvocation isCheck = new JsInvocation(context().namer().isOperationReference(),
|
||||||
expressionToMatch, getClassReference(pattern));
|
expressionToMatch, getClassReference(typeReference));
|
||||||
if (isNullable(pattern)) {
|
if (isNullable(typeReference)) {
|
||||||
return addNullCheck(expressionToMatch, isCheck);
|
return addNullCheck(expressionToMatch, isCheck);
|
||||||
}
|
}
|
||||||
return isCheck;
|
return isCheck;
|
||||||
@@ -97,9 +80,9 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsExpression translateAsIntrinsicTypeCheck(@NotNull JsExpression expressionToMatch,
|
private JsExpression translateAsIntrinsicTypeCheck(@NotNull JsExpression expressionToMatch,
|
||||||
@NotNull JetTypePattern pattern) {
|
@NotNull JetTypeReference typeReference) {
|
||||||
JsExpression result = null;
|
JsExpression result = null;
|
||||||
JsName className = getClassReference(pattern).getName();
|
JsName className = getClassReference(typeReference).getName();
|
||||||
if (className.getIdent().equals("String")) {
|
if (className.getIdent().equals("String")) {
|
||||||
result = typeof(expressionToMatch, program().getStringLiteral("string"));
|
result = typeof(expressionToMatch, program().getStringLiteral("string"));
|
||||||
}
|
}
|
||||||
@@ -114,13 +97,12 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
return or(TranslationUtils.isNullCheck(expressionToMatch), isCheck);
|
return or(TranslationUtils.isNullCheck(expressionToMatch), isCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNullable(JetTypePattern pattern) {
|
private boolean isNullable(JetTypeReference typeReference) {
|
||||||
return BindingUtils.getTypeByReference(bindingContext(), getTypeReference(pattern)).isNullable();
|
return BindingUtils.getTypeByReference(bindingContext(), typeReference).isNullable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsNameRef getClassReference(@NotNull JetTypePattern pattern) {
|
private JsNameRef getClassReference(@NotNull JetTypeReference typeReference) {
|
||||||
JetTypeReference typeReference = getTypeReference(pattern);
|
|
||||||
return getClassNameReferenceForTypeReference(typeReference);
|
return getClassNameReferenceForTypeReference(typeReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,15 +114,13 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translateExpressionPattern(@NotNull JsExpression expressionToMatch, JetExpressionPattern pattern) {
|
public JsExpression translateExpressionPattern(@NotNull JsExpression expressionToMatch, @NotNull JetExpression patternExpression) {
|
||||||
JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(pattern);
|
JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(patternExpression);
|
||||||
return equality(expressionToMatch, expressionToMatchAgainst);
|
return equality(expressionToMatch, expressionToMatchAgainst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translateExpressionForExpressionPattern(@NotNull JetExpressionPattern pattern) {
|
public JsExpression translateExpressionForExpressionPattern(@NotNull JetExpression patternExpression) {
|
||||||
JetExpression patternExpression = pattern.getExpression();
|
|
||||||
assert patternExpression != null : "Expression patter should have an expression.";
|
|
||||||
return Translation.translateAsExpression(patternExpression, context());
|
return Translation.translateAsExpression(patternExpression, context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,14 +182,49 @@ public final class WhenTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) {
|
private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) {
|
||||||
JsExpression patternMatchExpression = Translation.patternTranslator(context()).
|
JsExpression patternMatchExpression = translateWhenConditionToBooleanExpression(condition);
|
||||||
translatePattern(getPattern(condition), getExpressionToMatch());
|
|
||||||
if (isNegated(condition)) {
|
if (isNegated(condition)) {
|
||||||
return negated(patternMatchExpression);
|
return negated(patternMatchExpression);
|
||||||
}
|
}
|
||||||
return patternMatchExpression;
|
return patternMatchExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression translateWhenConditionToBooleanExpression(@NotNull JetWhenCondition condition) {
|
||||||
|
if (condition instanceof JetWhenConditionIsPattern) {
|
||||||
|
return translateIsCondition((JetWhenConditionIsPattern) condition);
|
||||||
|
}
|
||||||
|
else if (condition instanceof JetWhenConditionWithExpression) {
|
||||||
|
return translateExpressionCondition((JetWhenConditionWithExpression) condition);
|
||||||
|
}
|
||||||
|
throw new AssertionError("Wrong type of JetWhenCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression translateIsCondition(@NotNull JetWhenConditionIsPattern conditionIsPattern) {
|
||||||
|
JsExpression expressionToMatch = getExpressionToMatch();
|
||||||
|
assert expressionToMatch != null : "An is-check is not allowed in when() without subject.";
|
||||||
|
|
||||||
|
JetTypeReference typeReference = conditionIsPattern.getTypeRef();
|
||||||
|
assert typeReference != null : "An is-check must have a type reference.";
|
||||||
|
|
||||||
|
return Translation.patternTranslator(context()).translateIsCheck(expressionToMatch, typeReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression translateExpressionCondition(@NotNull JetWhenConditionWithExpression condition) {
|
||||||
|
JetExpression patternExpression = condition.getExpression();
|
||||||
|
assert patternExpression != null : "Expression pattern should have an expression.";
|
||||||
|
|
||||||
|
JsExpression expressionToMatch = getExpressionToMatch();
|
||||||
|
if (expressionToMatch == null) {
|
||||||
|
return Translation.patternTranslator(context()).translateExpressionForExpressionPattern(patternExpression);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Translation.patternTranslator(context()).translateExpressionPattern(expressionToMatch, patternExpression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsExpression getExpressionToMatch() {
|
private JsExpression getExpressionToMatch() {
|
||||||
return expressionToMatch != null ? expressionToMatch.reference() : null;
|
return expressionToMatch != null ? expressionToMatch.reference() : null;
|
||||||
@@ -202,22 +237,6 @@ public final class WhenTranslator extends AbstractTranslator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static JetPattern getPattern(@NotNull JetWhenCondition condition) {
|
|
||||||
JetPattern pattern;
|
|
||||||
if (condition instanceof JetWhenConditionIsPattern) {
|
|
||||||
pattern = ((JetWhenConditionIsPattern)condition).getPattern();
|
|
||||||
}
|
|
||||||
else if (condition instanceof JetWhenConditionWithExpression) {
|
|
||||||
pattern = ((JetWhenConditionWithExpression)condition).getPattern();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionError("Wrong type of JetWhenCondition");
|
|
||||||
}
|
|
||||||
assert pattern != null : "Condition should have a non null pattern.";
|
|
||||||
return pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsExpression translateExpressionToMatch(@NotNull JetWhenExpression expression) {
|
private JsExpression translateExpressionToMatch(@NotNull JetWhenExpression expression) {
|
||||||
JetExpression subject = expression.getSubjectExpression();
|
JetExpression subject = expression.getSubjectExpression();
|
||||||
|
|||||||
@@ -153,17 +153,4 @@ public final class PsiUtils {
|
|||||||
return rangeExpression;
|
return rangeExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JetPattern getPattern(@NotNull JetIsExpression expression) {
|
|
||||||
JetPattern pattern = expression.getPattern();
|
|
||||||
assert pattern != null : "Pattern should not be null";
|
|
||||||
return pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JetTypeReference getTypeReference(@NotNull JetTypePattern pattern) {
|
|
||||||
JetTypeReference typeReference = pattern.getTypeReference();
|
|
||||||
assert typeReference != null : "Type pattern should contain a type reference";
|
|
||||||
return typeReference;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ fun box() : Int {
|
|||||||
val d = 5
|
val d = 5
|
||||||
var z = 0
|
var z = 0
|
||||||
when(c) {
|
when(c) {
|
||||||
is 5, is 3 -> z++;
|
5, 3 -> z++;
|
||||||
else -> {z = -1000;}
|
else -> {z = -1000;}
|
||||||
}
|
}
|
||||||
|
|
||||||
when(d) {
|
when(d) {
|
||||||
is 5, is 3 -> z++;
|
5, 3 -> z++;
|
||||||
else -> {z = -1000;}
|
else -> {z = -1000;}
|
||||||
}
|
}
|
||||||
return z
|
return z
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ package foo
|
|||||||
fun box() : Boolean {
|
fun box() : Boolean {
|
||||||
|
|
||||||
return (when(1) {
|
return (when(1) {
|
||||||
is 2 -> 3
|
2 -> 3
|
||||||
is 1 -> 1
|
1 -> 1
|
||||||
else -> 5
|
else -> 5
|
||||||
} == 1)
|
} == 1)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package foo
|
|
||||||
|
|
||||||
fun box() : Boolean {
|
|
||||||
var a = 4
|
|
||||||
when(a) {
|
|
||||||
!is 3 -> {a = 10;}
|
|
||||||
!is 4 -> {a = 20;}
|
|
||||||
else -> {a = 30;}
|
|
||||||
}
|
|
||||||
return (a == 10)
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,8 @@ package foo
|
|||||||
fun box() : Boolean {
|
fun box() : Boolean {
|
||||||
var a = 4
|
var a = 4
|
||||||
when(a) {
|
when(a) {
|
||||||
is 3 -> {a = 10;}
|
3 -> {a = 10;}
|
||||||
is 4 -> {a = 20;}
|
4 -> {a = 20;}
|
||||||
else -> {a = 30;}
|
else -> {a = 30;}
|
||||||
}
|
}
|
||||||
return (a == 20)
|
return (a == 20)
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ fun box() : Boolean {
|
|||||||
var a = A() : Any?
|
var a = A() : Any?
|
||||||
var b = null : Any?
|
var b = null : Any?
|
||||||
when(a) {
|
when(a) {
|
||||||
is null -> c = 10;
|
null -> c = 10;
|
||||||
is B -> c = 10000
|
is B -> c = 10000
|
||||||
is A -> c = 20;
|
is A -> c = 20;
|
||||||
else -> c = 1000
|
else -> c = 1000
|
||||||
}
|
}
|
||||||
when(b) {
|
when(b) {
|
||||||
is null -> c += 5
|
null -> c += 5
|
||||||
is B -> c += 100
|
is B -> c += 100
|
||||||
else -> c = 1000
|
else -> c = 1000
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user