Customize JVM signature for Collection's members

- Do not write signature for `contains`
- Write signature for `containsAll` as it's declared like `containsAll(Collection<?>)`
This commit is contained in:
Denis Zharkov
2015-10-07 21:34:13 +03:00
parent 1f52dfccdb
commit 80da320c2c
10 changed files with 361 additions and 2 deletions
@@ -529,8 +529,11 @@ public class FunctionCodegen {
);
if (!bridgesToGenerate.isEmpty()) {
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
boolean isSpecialBridge =
BuiltinsPropertiesUtilKt.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) != null;
for (Bridge<Method> bridge : bridgesToGenerate) {
generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), false, false);
generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false);
}
}
}
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.load.java.BuiltinsPropertiesUtilKt;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.SpecialSignatureInfo;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope;
@@ -941,7 +942,19 @@ public class JetTypeMapper {
sw.writeReturnTypeEnd();
}
return sw.makeJvmMethodSignature(mapFunctionName(f));
JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
if (kind != OwnerKind.DEFAULT_IMPLS) {
SpecialSignatureInfo specialSignatureInfo = BuiltinsPropertiesUtilKt.getSpecialSignatureInfo(f);
if (specialSignatureInfo != null) {
return new JvmMethodSignature(
signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
}
}
return signature;
}
@NotNull
@@ -0,0 +1,13 @@
import java.util.*;
public class J {
private static class MyList<E> extends KList<E> {}
public static String foo() {
Collection<String> collection = new MyList<String>();
if (!collection.contains("ABCDE")) return "fail 1";
if (!collection.containsAll(Arrays.asList(1, 2, 3))) return "fail 2";
return "OK";
}
}
@@ -0,0 +1,81 @@
open class KList<E> : MutableList<E> {
override fun add(e: E): Boolean {
throw UnsupportedOperationException()
}
override fun remove(o: Any?): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(c: Collection<E>): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(index: Int, c: Collection<E>): Boolean {
throw UnsupportedOperationException()
}
override fun removeAll(c: Collection<Any?>): Boolean {
throw UnsupportedOperationException()
}
override fun retainAll(c: Collection<Any?>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
throw UnsupportedOperationException()
}
override fun set(index: Int, element: E): E {
throw UnsupportedOperationException()
}
override fun add(index: Int, element: E) {
throw UnsupportedOperationException()
}
override fun remove(index: Int): E {
throw UnsupportedOperationException()
}
override fun listIterator(): MutableListIterator<E> {
throw UnsupportedOperationException()
}
override fun listIterator(index: Int): MutableListIterator<E> {
throw UnsupportedOperationException()
}
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
throw UnsupportedOperationException()
}
override fun iterator(): MutableIterator<E> {
throw UnsupportedOperationException()
}
override val size: Int
get() = throw UnsupportedOperationException()
override fun isEmpty(): Boolean {
throw UnsupportedOperationException()
}
override fun contains(o: E) = true
override fun containsAll(c: Collection<E>) = true
override fun get(index: Int): E {
throw UnsupportedOperationException()
}
override fun indexOf(o: Any?): Int {
throw UnsupportedOperationException()
}
override fun lastIndexOf(o: Any?): Int {
throw UnsupportedOperationException()
}
}
fun box() = J.foo()
@@ -0,0 +1,13 @@
import java.util.*;
public class J {
private static class MyList extends KList {}
public static String foo() {
Collection<String> collection = new MyList();
if (!collection.contains("ABCDE")) return "fail 1";
if (!collection.containsAll(Arrays.asList(1, 2, 3))) return "fail 2";
return "OK";
}
}
@@ -0,0 +1,81 @@
open class KList : MutableList<String> {
override val size: Int
get() = throw UnsupportedOperationException()
override fun isEmpty(): Boolean {
throw UnsupportedOperationException()
}
override fun contains(o: String) = true
override fun containsAll(c: Collection<String>) = true
override fun get(index: Int): String {
throw UnsupportedOperationException()
}
override fun indexOf(o: Any?): Int {
throw UnsupportedOperationException()
}
override fun lastIndexOf(o: Any?): Int {
throw UnsupportedOperationException()
}
override fun iterator(): MutableIterator<String> {
throw UnsupportedOperationException()
}
override fun add(e: String): Boolean {
throw UnsupportedOperationException()
}
override fun remove(o: Any?): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(c: Collection<String>): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(index: Int, c: Collection<String>): Boolean {
throw UnsupportedOperationException()
}
override fun removeAll(c: Collection<Any?>): Boolean {
throw UnsupportedOperationException()
}
override fun retainAll(c: Collection<Any?>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
throw UnsupportedOperationException()
}
override fun set(index: Int, element: String): String {
throw UnsupportedOperationException()
}
override fun add(index: Int, element: String) {
throw UnsupportedOperationException()
}
override fun remove(index: Int): String {
throw UnsupportedOperationException()
}
override fun listIterator(): MutableListIterator<String> {
throw UnsupportedOperationException()
}
override fun listIterator(index: Int): MutableListIterator<String> {
throw UnsupportedOperationException()
}
override fun subList(fromIndex: Int, toIndex: Int): MutableList<String> {
throw UnsupportedOperationException()
}
}
fun box() = J.foo()
@@ -0,0 +1,110 @@
abstract class A1<Q> : MutableCollection<Q> {
override fun contains(o: Q): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<Q>): Boolean {
throw UnsupportedOperationException()
}
}
abstract class A2 : MutableCollection<String> {
override fun contains(o: String): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<String>): Boolean {
throw UnsupportedOperationException()
}
}
abstract class A3<W> : java.util.AbstractList<W>()
abstract class A4<W> : java.util.AbstractList<W>() {
override fun contains(o: W): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<W>): Boolean {
throw UnsupportedOperationException()
}
}
abstract class A5 : java.util.AbstractList<String>()
abstract class A6 : java.util.AbstractList<String>() {
override fun contains(o: String): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<String>): Boolean {
throw UnsupportedOperationException()
}
}
interface I1<R> : MutableSet<R> {
override fun contains(o: R): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<R>): Boolean {
throw UnsupportedOperationException()
}
}
interface I2 : MutableSet<String> {
override fun contains(o: String): Boolean {
throw UnsupportedOperationException()
}
override fun containsAll(c: Collection<String>): Boolean {
throw UnsupportedOperationException()
}
}
abstract class A7 : MutableCollection<Int> {
override fun contains(o: Int): Boolean {
throw UnsupportedOperationException()
}
}
abstract class A8 : MutableCollection<Any?> {
override fun contains(o: Any?): Boolean {
throw UnsupportedOperationException()
}
}
fun foo(
a1: A1<String>,
a2: A2,
a3: A3<String>,
a4: A4<String>,
a5: A5,
a6: A6,
a7: A7,
i1: I1<String>,
i2: I2,
c: Collection<String>
) {
a1.contains("")
a2.contains("")
a3.contains("")
a4.contains("")
a5.contains("")
a6.contains("")
a7.contains(1)
i1.contains("")
i2.contains("")
c.contains("")
}
// 0 signature \(TQ;\)Z
// 0 signature \(TW;\)Z
// 0 signature \(TR;\)Z
// 6 signature \(Ljava/util/Collection<\+Ljava/lang/Object;>;\)Z
// 3 public final bridge contains\(Ljava/lang/Object;\)Z
// 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/String;\)Z
// 4 INVOKEVIRTUAL A[0-9]\.contains \(Ljava/lang/Object;\)Z
// 2 INVOKEVIRTUAL A7\.contains \(I\)Z
// 1 INVOKEINTERFACE java/util/Collection.contains \(Ljava/lang/Object;\)Z
// 1 INVOKEINTERFACE I1.contains \(Ljava/lang/Object;\)Z
// 1 INVOKEINTERFACE I2.contains \(Ljava/lang/String;\)Z
@@ -367,6 +367,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/builtinFunctions"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("contains.kt")
public void testContains() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/builtinFunctions/contains.kt");
doTest(fileName);
}
@TestMetadata("size.kt")
public void testSize() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/builtinFunctions/size.kt");
@@ -165,6 +165,28 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
}
@TestMetadata("compiler/testData/codegen/boxWithJava/collections")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Collections extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInCollections() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/collections"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("mutableList")
public void testMutableList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/mutableList/");
doTestWithJava(fileName);
}
@TestMetadata("strList")
public void testStrList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/strList/");
doTestWithJava(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxWithJava/fileClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -126,3 +126,20 @@ private fun CallableMemberDescriptor.firstOverridden(
val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean
get () = this in BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_SHORT_NAMES
enum class SpecialSignatureInfo(val signature: String?) {
ONE_COLLECTION_PARAMETER("(Ljava/util/Collection<+Ljava/lang/Object;>;)Z"),
GENERIC_PARAMETER(null)
}
val CallableMemberDescriptor.specialSignatureInfo: SpecialSignatureInfo?
get() {
val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull()
?: return null
return when (builtinFqName) {
in BUILTIN_METHODS_ERASED_COLLECTION_PARAMETER_FQ_NAMES -> SpecialSignatureInfo.ONE_COLLECTION_PARAMETER
in BUILTIN_METHODS_GENERIC_PARAMETERS_FQ_NAMES -> SpecialSignatureInfo.GENERIC_PARAMETER
else -> error("Unexpected kind of special builtin: $builtinFqName")
}
}