JS: fix char boxing in elvis expressions (#KT-17700 fixed)
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// see KT-17700
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@@ -410,6 +410,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("charElvis.kt")
|
||||
public void testCharElvis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/char/charElvis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("charEquals.kt")
|
||||
public void testCharEquals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/char/charEquals.kt");
|
||||
|
||||
+1
-7
@@ -15222,13 +15222,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("forInUntilChar.kt")
|
||||
public void testForInUntilChar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("forInUntilChar0.kt")
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBlock
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsConditional
|
||||
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.js.backend.ast.JsLiteral
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -105,11 +103,7 @@ fun TranslationContext.getCallInfo(
|
||||
}
|
||||
|
||||
private fun boxIfNeedeed(v: ReceiverValue?, d: ReceiverParameterDescriptor?, r: JsExpression?): JsExpression? {
|
||||
if (r != null && v != null && KotlinBuiltIns.isCharOrNullableChar(v.type) &&
|
||||
(d == null || !KotlinBuiltIns.isCharOrNullableChar(d.type))) {
|
||||
return JsAstUtils.charToBoxedChar(r)
|
||||
}
|
||||
return r
|
||||
return r?.let { TranslationUtils.boxCastIfNeeded(it, v?.type, d?.type) }
|
||||
}
|
||||
|
||||
private fun TranslationContext.getDispatchReceiver(receiverValue: ReceiverValue): JsExpression {
|
||||
|
||||
+2
-6
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.js.translate.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
|
||||
@@ -29,12 +28,12 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -85,10 +84,7 @@ public class DestructuringDeclarationTranslator extends AbstractTranslator {
|
||||
setInlineCallMetadata(entryInitializer, entry, entryInitCall, context());
|
||||
}
|
||||
|
||||
KotlinType returnType = candidateDescriptor.getReturnType();
|
||||
if (returnType != null && KotlinBuiltIns.isCharOrNullableChar(returnType) && !KotlinBuiltIns.isCharOrNullableChar(descriptor.getType())) {
|
||||
entryInitializer = JsAstUtils.charToBoxedChar(entryInitializer);
|
||||
}
|
||||
entryInitializer = TranslationUtils.boxCastIfNeeded(entryInitializer, candidateDescriptor.getReturnType(), descriptor.getType());
|
||||
|
||||
JsName name = context().getNameForDescriptor(descriptor);
|
||||
if (isVarCapturedInClosure(context().bindingContext(), descriptor)) {
|
||||
|
||||
+9
-2
@@ -123,10 +123,17 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateElvis() {
|
||||
JsExpression leftExpression = Translation.translateAsExpression(leftKtExpression, context());
|
||||
KotlinType expressionType = context().bindingContext().getType(expression);
|
||||
|
||||
JsExpression leftExpression = TranslationUtils.boxCastIfNeeded(Translation.translateAsExpression(leftKtExpression, context()),
|
||||
context().bindingContext().getType(leftKtExpression),
|
||||
expressionType);
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
JsExpression rightExpression = Translation.translateAsExpression(rightKtExpression, context(), rightBlock);
|
||||
JsExpression rightExpression =
|
||||
TranslationUtils.boxCastIfNeeded(Translation.translateAsExpression(rightKtExpression, context(), rightBlock),
|
||||
context().bindingContext().getType(rightKtExpression),
|
||||
expressionType);
|
||||
|
||||
if (rightBlock.isEmpty()) {
|
||||
return TranslationUtils.notNullConditional(leftExpression, rightExpression, context());
|
||||
|
||||
+9
-9
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.translate.reference
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineOrReturn
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -183,19 +184,18 @@ class CallArgumentTranslator private constructor(
|
||||
val parenthisedArgumentExpression = arg.getArgumentExpression()
|
||||
|
||||
val param = argsToParameters[arg]!!.original
|
||||
val parameterType = param.varargElementType ?: param.type
|
||||
val parameterType = if (resolvedCall.call.callType == Call.CallType.INVOKE) {
|
||||
DefaultBuiltIns.Instance.anyType
|
||||
}
|
||||
else {
|
||||
param.varargElementType ?: param.type
|
||||
}
|
||||
|
||||
val argType = context.bindingContext().getType(parenthisedArgumentExpression!!)
|
||||
|
||||
val argJs = Translation.translateAsExpression(parenthisedArgumentExpression, argumentContext)
|
||||
val jsExpr = if (argType != null && KotlinBuiltIns.isCharOrNullableChar(argType) &&
|
||||
(!KotlinBuiltIns.isCharOrNullableChar(parameterType) || resolvedCall.call.callType == Call.CallType.INVOKE)) {
|
||||
JsAstUtils.charToBoxedChar(argJs)
|
||||
}
|
||||
else {
|
||||
argJs
|
||||
}
|
||||
|
||||
arg to jsExpr
|
||||
arg to TranslationUtils.boxCastIfNeeded(argJs, argType, parameterType)
|
||||
}
|
||||
|
||||
val resolvedOrder = resolvedCall.valueArgumentsByIndex.orEmpty()
|
||||
|
||||
@@ -200,9 +200,7 @@ public final class TranslationUtils {
|
||||
KotlinType propertyType = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.VARIABLE, declaration).getType();
|
||||
KotlinType initType = context.bindingContext().getType(initializer);
|
||||
|
||||
if (initType != null && KotlinBuiltIns.isCharOrNullableChar(initType) && !KotlinBuiltIns.isCharOrNullableChar(propertyType)) {
|
||||
jsInitExpression = JsAstUtils.charToBoxedChar(jsInitExpression);
|
||||
}
|
||||
jsInitExpression = boxCastIfNeeded(jsInitExpression, initType, propertyType);
|
||||
}
|
||||
return jsInitExpression;
|
||||
}
|
||||
@@ -402,4 +400,14 @@ public final class TranslationUtils {
|
||||
public static boolean shouldBoxReturnValue(CallableDescriptor c) {
|
||||
return overridesReturnAny(c) || c instanceof CallableMemberDescriptor && ModalityKt.isOverridable((CallableMemberDescriptor)c);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression boxCastIfNeeded(@NotNull JsExpression e, @Nullable KotlinType castFrom, @Nullable KotlinType castTo) {
|
||||
if (castFrom != null && KotlinBuiltIns.isCharOrNullableChar(castFrom) &&
|
||||
castTo != null && !KotlinBuiltIns.isCharOrNullableChar(castTo)
|
||||
) {
|
||||
return JsAstUtils.charToBoxedChar(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package foo
|
||||
|
||||
fun box(): String {
|
||||
|
||||
assertEquals("1", "" + ('1' ?: return "fail1"))
|
||||
assertEquals("2", "" + (null ?: '2'))
|
||||
val c3: Char? = '3'
|
||||
assertEquals("3", "" + (c3 ?: return "fail3"))
|
||||
|
||||
val c4: Char? = null
|
||||
assertEquals("4", "" + (c4 ?: "4"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user