JS/RTTI: fix cast to Any
This commit is contained in:
committed by
Alexey Andreev
parent
2b3ebc7e9f
commit
38b0effe15
+2
-1
@@ -62,5 +62,6 @@ var HasMetadata.sideEffects: Boolean by MetadataProperty(default = true)
|
|||||||
enum class TypeCheck {
|
enum class TypeCheck {
|
||||||
TYPEOF,
|
TYPEOF,
|
||||||
INSTANCEOF,
|
INSTANCEOF,
|
||||||
OR_NULL
|
OR_NULL,
|
||||||
|
IS_ANY
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ public class CastTestGenerated extends AbstractCastTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/expression/cast/cases"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/expression/cast/cases"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("castToAny.kt")
|
||||||
|
public void testCastToAny() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/castToAny.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("castToGenericType.kt")
|
@TestMetadata("castToGenericType.kt")
|
||||||
public void testCastToGenericType() throws Exception {
|
public void testCastToGenericType() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/castToGenericType.kt");
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/castToGenericType.kt");
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
|||||||
import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck;
|
import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||||
@@ -399,13 +401,23 @@ public final class Namer {
|
|||||||
return invokeFunctionAndSetTypeCheckMetadata("orNull", callable, TypeCheck.OR_NULL);
|
return invokeFunctionAndSetTypeCheckMetadata("orNull", callable, TypeCheck.OR_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsExpression isAny() {
|
||||||
|
return invokeFunctionAndSetTypeCheckMetadata("isAny", null, TypeCheck.IS_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression invokeFunctionAndSetTypeCheckMetadata(
|
private JsExpression invokeFunctionAndSetTypeCheckMetadata(
|
||||||
@NotNull String functionName,
|
@NotNull String functionName,
|
||||||
@NotNull JsExpression argument,
|
@Nullable JsExpression argument,
|
||||||
@NotNull TypeCheck metadata
|
@NotNull TypeCheck metadata
|
||||||
) {
|
) {
|
||||||
JsInvocation invocation = new JsInvocation(kotlin(functionName), argument);
|
JsInvocation invocation = new JsInvocation(kotlin(functionName));
|
||||||
|
|
||||||
|
if (argument != null) {
|
||||||
|
invocation.getArguments().add(argument);
|
||||||
|
}
|
||||||
|
|
||||||
MetadataProperties.setTypeCheck(invocation, metadata);
|
MetadataProperties.setTypeCheck(invocation, metadata);
|
||||||
MetadataProperties.setSideEffects(invocation, false);
|
MetadataProperties.setSideEffects(invocation, false);
|
||||||
return invocation;
|
return invocation;
|
||||||
|
|||||||
+3
@@ -25,6 +25,7 @@ import com.google.dart.compiler.backend.js.ast.*;
|
|||||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
|
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.js.patterns.NamePredicate;
|
import org.jetbrains.kotlin.js.patterns.NamePredicate;
|
||||||
@@ -116,6 +117,8 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression doGetIsTypeCheckCallable(@NotNull KotlinType type) {
|
private JsExpression doGetIsTypeCheckCallable(@NotNull KotlinType type) {
|
||||||
|
if (KotlinBuiltIns.isAnyOrNullableAny(type)) return namer().isAny();
|
||||||
|
|
||||||
JsExpression builtinCheck = getIsTypeCheckCallableForBuiltin(type);
|
JsExpression builtinCheck = getIsTypeCheckCallableForBuiltin(type);
|
||||||
if (builtinCheck != null) return builtinCheck;
|
if (builtinCheck != null) return builtinCheck;
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ private class TypeCheckRewritingVisitor(private val context: TranslationContext)
|
|||||||
val calleeArgument = callee?.arguments?.firstOrNull()
|
val calleeArgument = callee?.arguments?.firstOrNull()
|
||||||
val argument = x.arguments.firstOrNull()
|
val argument = x.arguments.firstOrNull()
|
||||||
|
|
||||||
if (callee != null && calleeArgument != null && argument != null) {
|
if (callee != null && argument != null) {
|
||||||
val replacement = getReplacement(callee, calleeArgument, argument)
|
val replacement = getReplacement(callee, calleeArgument, argument)
|
||||||
|
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
@@ -80,7 +80,16 @@ private class TypeCheckRewritingVisitor(private val context: TranslationContext)
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getReplacement(callee: JsInvocation, calleeArgument: JsExpression, argument: JsExpression): JsExpression? {
|
private fun getReplacement(callee: JsInvocation, calleeArgument: JsExpression?, argument: JsExpression): JsExpression? {
|
||||||
|
if (calleeArgument == null) {
|
||||||
|
// Kotlin.isAny()(argument) -> argument != null
|
||||||
|
if (callee.typeCheck == TypeCheck.IS_ANY) {
|
||||||
|
return TranslationUtils.isNotNullCheck(argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
// Kotlin.isTypeOf(calleeArgument)(argument) -> typeOf argument === calleeArgument
|
// Kotlin.isTypeOf(calleeArgument)(argument) -> typeOf argument === calleeArgument
|
||||||
if (callee.typeCheck == TypeCheck.TYPEOF) {
|
if (callee.typeCheck == TypeCheck.TYPEOF) {
|
||||||
return typeOfIs(argument, calleeArgument as JsStringLiteral)
|
return typeOfIs(argument, calleeArgument as JsStringLiteral)
|
||||||
@@ -93,8 +102,10 @@ private class TypeCheckRewritingVisitor(private val context: TranslationContext)
|
|||||||
|
|
||||||
// Kotlin.orNull(calleeArgument)(argument) -> (tmp = argument) == null || calleeArgument(tmp)
|
// Kotlin.orNull(calleeArgument)(argument) -> (tmp = argument) == null || calleeArgument(tmp)
|
||||||
if (callee.typeCheck == TypeCheck.OR_NULL) {
|
if (callee.typeCheck == TypeCheck.OR_NULL) {
|
||||||
if (calleeArgument is JsInvocation && calleeArgument.typeCheck == TypeCheck.OR_NULL) {
|
if (calleeArgument is JsInvocation) {
|
||||||
return JsInvocation(calleeArgument, argument)
|
if (calleeArgument.typeCheck == TypeCheck.OR_NULL) return JsInvocation(calleeArgument, argument)
|
||||||
|
|
||||||
|
if (calleeArgument.typeCheck == TypeCheck.IS_ANY) return argument
|
||||||
}
|
}
|
||||||
|
|
||||||
var nullCheckTarget = argument
|
var nullCheckTarget = argument
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val x = 0
|
||||||
|
val y = 1
|
||||||
|
val z = 2
|
||||||
|
val xs = arrayListOf(z, y, x)
|
||||||
|
xs.remove(x as Any)
|
||||||
|
assertEquals(listOf(z, y), xs)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -555,6 +555,12 @@ var Kotlin = {};
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Kotlin.isAny = function () {
|
||||||
|
return function (object) {
|
||||||
|
return object != null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Kotlin.kotlinModuleMetadata = function (abiVersion, moduleName, data) {
|
Kotlin.kotlinModuleMetadata = function (abiVersion, moduleName, data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user