Make nullable check less verbose in JS-backend.
For check what variable is equal null or undefined enough to compare with null (or undefined). See ECMAScript specification 11.9.1, 11.9.2, 11.9.3
This commit is contained in:
@@ -45,4 +45,8 @@ public final class EqualsTest extends AbstractExpressionTest {
|
|||||||
public void testKt2370() throws Exception {
|
public void testKt2370() throws Exception {
|
||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEqualsNullOrUndefined() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -33,7 +33,7 @@ import static org.jetbrains.k2js.translate.general.Translation.translateAsExpres
|
|||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
|
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
|
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.notNullConditionalTestExpression;
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNotNullCheck;
|
||||||
|
|
||||||
|
|
||||||
public final class UnaryOperationTranslator {
|
public final class UnaryOperationTranslator {
|
||||||
@@ -59,7 +59,7 @@ public final class UnaryOperationTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
|
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
|
||||||
TemporaryVariable cachedValue = context.declareTemporary(translateAsExpression(getBaseExpression(expression), context));
|
TemporaryVariable cachedValue = context.declareTemporary(translateAsExpression(getBaseExpression(expression), context));
|
||||||
return new JsConditional(notNullConditionalTestExpression(cachedValue), cachedValue.reference(), context.namer().throwNPEFunctionCall());
|
return new JsConditional(isNotNullCheck(cachedValue.assignmentExpression()), cachedValue.reference(), context.namer().throwNPEFunctionCall());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression;
|
|||||||
import org.jetbrains.k2js.translate.context.TemporaryVariable;
|
import org.jetbrains.k2js.translate.context.TemporaryVariable;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.notNullConditionalTestExpression;
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNotNullCheck;
|
||||||
|
|
||||||
public enum CallType {
|
public enum CallType {
|
||||||
SAFE {
|
SAFE {
|
||||||
@@ -37,7 +37,7 @@ public enum CallType {
|
|||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
assert receiver != null;
|
assert receiver != null;
|
||||||
TemporaryVariable cachedValue = context.declareTemporary(receiver);
|
TemporaryVariable cachedValue = context.declareTemporary(receiver);
|
||||||
return new JsConditional(notNullConditionalTestExpression(cachedValue), constructor.construct(cachedValue.reference()), JsLiteral.NULL);
|
return new JsConditional(isNotNullCheck(cachedValue.assignmentExpression()), constructor.construct(cachedValue.reference()), JsLiteral.NULL);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//TODO: bang qualifier is not implemented in frontend for now
|
//TODO: bang qualifier is not implemented in frontend for now
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.k2js.translate.context.TemporaryVariable;
|
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.general.Translation;
|
import org.jetbrains.k2js.translate.general.Translation;
|
||||||
|
|
||||||
@@ -32,7 +31,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
|
||||||
|
|
||||||
public final class TranslationUtils {
|
public final class TranslationUtils {
|
||||||
private TranslationUtils() {
|
private TranslationUtils() {
|
||||||
@@ -64,19 +64,15 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsBinaryOperation notNullConditionalTestExpression(@NotNull TemporaryVariable cachedValue) {
|
public static JsBinaryOperation isNotNullCheck(@NotNull JsExpression expressionToCheck) {
|
||||||
return and(inequality(cachedValue.assignmentExpression(), JsLiteral.NULL),
|
return nullCheck(expressionToCheck, true);
|
||||||
inequality(cachedValue.reference(), JsLiteral.UNDEFINED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsBinaryOperation nullCheck(@NotNull JsExpression expressionToCheck, boolean isNegated) {
|
public static JsBinaryOperation nullCheck(@NotNull JsExpression expressionToCheck, boolean isNegated) {
|
||||||
JsBinaryOperator operator = isNegated ? JsBinaryOperator.REF_NEQ : JsBinaryOperator.REF_EQ;
|
JsBinaryOperator operator = isNegated ? JsBinaryOperator.NEQ : JsBinaryOperator.EQ;
|
||||||
return new JsBinaryOperation(isNegated ? JsBinaryOperator.AND : JsBinaryOperator.OR,
|
return new JsBinaryOperation(operator, expressionToCheck, JsLiteral.NULL);
|
||||||
new JsBinaryOperation(operator, expressionToCheck, JsLiteral.NULL),
|
|
||||||
new JsBinaryOperation(operator, expressionToCheck, JsLiteral.UNDEFINED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
|
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
|
||||||
@NotNull List<? extends ValueArgument> jetArguments) {
|
@NotNull List<? extends ValueArgument> jetArguments) {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val a: Int? = null
|
||||||
|
val r = a == null
|
||||||
|
if (!r || a != null)
|
||||||
|
return "wrong result on simple nullable check"
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
fun foo(): Int? = ++i;
|
||||||
|
if (foo() == null)
|
||||||
|
return "wrong result on nullable check with side effects"
|
||||||
|
|
||||||
|
if (i != 1)
|
||||||
|
return "wrong affects when using nullable check with side effects"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user