From 9dd6c9a65c37551c5e1a3f90fae085211d9a2583 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 6 Sep 2016 18:28:15 +0300 Subject: [PATCH] KT-13664: write values of long compile-time constants as constants. Fix #KT-13664 --- .../js/test/semantics/CastTestGenerated.java | 6 ++ .../expression/ExpressionVisitor.java | 31 ++-------- .../js/translate/general/Translation.java | 56 ++++++++++++++++++- .../cast/cases/implicitCastToLong.kt | 15 +++++ 4 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 js/js.translator/testData/expression/cast/cases/implicitCastToLong.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CastTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CastTestGenerated.java index dc39ef5000d..cd712f9e415 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CastTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CastTestGenerated.java @@ -119,6 +119,12 @@ public class CastTestGenerated extends AbstractCastTest { doTest(fileName); } + @TestMetadata("implicitCastToLong.kt") + public void testImplicitCastToLong() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/implicitCastToLong.kt"); + doTest(fileName); + } + @TestMetadata("noRuntimeTypeCheck.kt") public void testNoRuntimeTypeCheck() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/noRuntimeTypeCheck.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java index 2950d825590..7c2948d1039 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java @@ -86,34 +86,13 @@ public final class ExpressionVisitor extends TranslatorVisitor { private static JsNode translateConstantExpression(@NotNull KtConstantExpression expression, @NotNull TranslationContext context) { CompileTimeConstant compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext()); assert compileTimeValue != null : message(expression, "Expression is not compile time value: " + expression.getText() + " "); - KotlinType expectedType = context.bindingContext().getType(expression); - ConstantValue constant = compileTimeValue.toConstantValue(expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE); - if (constant instanceof NullValue) { - return JsLiteral.NULL; - } - Object value = constant.getValue(); - if (value instanceof Integer || value instanceof Short || value instanceof Byte) { - return context.program().getNumberLiteral(((Number) value).intValue()); - } - else if (value instanceof Long) { - return JsAstUtils.newLong((Long) value, context); - } - else if (value instanceof Number) { - return context.program().getNumberLiteral(((Number) value).doubleValue()); - } - else if (value instanceof Boolean) { - return JsLiteral.getBoolean((Boolean) value); + + JsNode result = Translation.translateConstant(compileTimeValue, expression, context); + if (result == null) { + throw new AssertionError(message(expression, "Unsupported constant expression: " + expression.getText() + " ")); } - //TODO: test - if (value instanceof String) { - return context.program().getStringLiteral((String) value); - } - if (value instanceof Character) { - return context.program().getStringLiteral(value.toString()); - } - - throw new AssertionError(message(expression, "Unsupported constant expression: " + expression.getText() + " ")); + return result; } @Override diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java index 24029f9a4fb..341c2755ff1 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.general; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.ModuleDescriptor; import org.jetbrains.kotlin.idea.MainFunctionDetector; @@ -47,8 +48,15 @@ import org.jetbrains.kotlin.psi.KtDeclarationWithBody; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedFunction; +import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; +import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; +import org.jetbrains.kotlin.resolve.constants.ConstantValue; +import org.jetbrains.kotlin.resolve.constants.NullValue; +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; +import org.jetbrains.kotlin.types.KotlinType; +import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import java.util.ArrayList; @@ -56,8 +64,9 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.*; +import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary; import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor; +import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList; import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator.mutateLastExpression; @@ -102,6 +111,42 @@ public final class Translation { return result; } + @Nullable + public static JsExpression translateConstant( + @NotNull CompileTimeConstant compileTimeValue, + @NotNull KtExpression expression, + @NotNull TranslationContext context + ) { + KotlinType expectedType = context.bindingContext().getType(expression); + ConstantValue constant = compileTimeValue.toConstantValue(expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE); + if (constant instanceof NullValue) { + return JsLiteral.NULL; + } + Object value = constant.getValue(); + if (value instanceof Integer || value instanceof Short || value instanceof Byte) { + return context.program().getNumberLiteral(((Number) value).intValue()); + } + else if (value instanceof Long) { + return JsAstUtils.newLong((Long) value, context); + } + else if (value instanceof Number) { + return context.program().getNumberLiteral(((Number) value).doubleValue()); + } + else if (value instanceof Boolean) { + return JsLiteral.getBoolean((Boolean) value); + } + + //TODO: test + if (value instanceof String) { + return context.program().getStringLiteral((String) value); + } + if (value instanceof Character) { + return context.program().getStringLiteral(value.toString()); + } + + return null; + } + @NotNull private static JsNode doTranslateExpression(KtExpression expression, TranslationContext context) { try { @@ -129,6 +174,15 @@ public final class Translation { @NotNull TranslationContext context, @NotNull JsBlock block ) { + CompileTimeConstant compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext()); + if (compileTimeValue != null) { + KotlinType type = context.bindingContext().getType(expression); + if (type != null && KotlinBuiltIns.isLong(type)) { + JsExpression constantResult = translateConstant(compileTimeValue, expression, context); + if (constantResult != null) return constantResult; + } + } + JsNode jsNode = translateExpression(expression, context, block); if (jsNode instanceof JsExpression) { return (JsExpression) jsNode; diff --git a/js/js.translator/testData/expression/cast/cases/implicitCastToLong.kt b/js/js.translator/testData/expression/cast/cases/implicitCastToLong.kt new file mode 100644 index 00000000000..ab1b5b67ab5 --- /dev/null +++ b/js/js.translator/testData/expression/cast/cases/implicitCastToLong.kt @@ -0,0 +1,15 @@ +package foo + +fun box(): String { + var a: Long = 23 + var b: Long = 200 + 30 + var c: Long = id((2000).plus(300)) + + assertEquals(24L, a + 1) + assertEquals(231L, b + 1) + assertEquals(2301L, c + 1) + + return "OK" +} + +fun id(x: Long) = x \ No newline at end of file