KT-13664: write values of long compile-time constants as constants. Fix #KT-13664
This commit is contained in:
@@ -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");
|
||||
|
||||
+5
-26
@@ -86,34 +86,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user