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:
@@ -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");
|
||||
|
||||
+22
@@ -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)
|
||||
|
||||
+17
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user