diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.kt new file mode 100644 index 00000000000..7d025c439ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.kt @@ -0,0 +1,25 @@ +// FILE: A.java +abstract public class A implements CharSequence { + public char charAt(int x) { } +} + +// FILE: C.java +abstract public class C implements CharSequence { + public char get(int x) { } +} + +// FILE: main.kt + +abstract class B : A(), CharSequence { + override operator fun get(index: Int) = '1' +} + +fun main(a: A, b: B, c: C) { + a[0] + b[0] + c[0] + + a.get(0) + b.get(0) + c.get(0) +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt new file mode 100644 index 00000000000..602cf8d2133 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt @@ -0,0 +1,33 @@ +package + +public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: C): kotlin.Unit + +public abstract class A : kotlin.CharSequence { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun get(/*0*/ x: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun length(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun subSequence(/*0*/ start: kotlin.Int, /*1*/ end: kotlin.Int): kotlin.CharSequence + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class B : A, kotlin.CharSequence { + public constructor B() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*2*/ /*fake_override*/ fun length(): kotlin.Int + public abstract override /*2*/ /*fake_override*/ fun subSequence(/*0*/ start: kotlin.Int, /*1*/ end: kotlin.Int): kotlin.CharSequence + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class C : kotlin.CharSequence { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun length(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun subSequence(/*0*/ start: kotlin.Int, /*1*/ end: kotlin.Int): kotlin.CharSequence + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.kt new file mode 100644 index 00000000000..5440046b5d8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.kt @@ -0,0 +1,22 @@ +// FILE: A.java +abstract public class A extends B { + public F remove(int x) { } + public boolean remove(Object x) { } +} + +// FILE: main.kt +import java.util.*; + +abstract class B : MutableList, AbstractList() { + override fun removeAt(index: Int): T = null!! + override fun remove(o: T): Boolean = null!! +} + +fun main(a: A, b: B, c: ArrayList) { + a.remove("") + a.removeAt(0) + b.remove("") + b.removeAt(0) + c.remove("") + c.removeAt(0) +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.txt new file mode 100644 index 00000000000..737a2f391ef --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.txt @@ -0,0 +1,76 @@ +package + +public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: java.util.ArrayList): kotlin.Unit + +public abstract class A : B { + public constructor A() + public open override /*1*/ /*fake_override*/ val isEmpty: kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ var modCount: kotlin.Int + public abstract override /*1*/ /*fake_override*/ val size: kotlin.Int + public open override /*1*/ /*fake_override*/ fun add(/*0*/ e: F!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun add(/*0*/ index: kotlin.Int, /*1*/ element: F!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun contains(/*0*/ o: F!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): F! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*fake_override*/ fun iterator(): kotlin.MutableIterator + public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator + public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator + invisible_fake open override /*1*/ /*fake_override*/ fun outOfBoundsMsg(/*0*/ p0: kotlin.Int): kotlin.String! + invisible_fake open override /*1*/ /*fake_override*/ fun rangeCheckForAdd(/*0*/ p0: kotlin.Int): kotlin.Unit + public open override /*1*/ /*synthesized*/ fun remove(/*0*/ o: F!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ fun removeAt(/*0*/ x: kotlin.Int): F! + protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: F!): F! + public open override /*1*/ /*fake_override*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.MutableList + public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>! + public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + invisible_fake const final override /*1*/ /*fake_override*/ val MAX_ARRAY_SIZE: kotlin.Int + invisible_fake open override /*1*/ /*fake_override*/ fun finishToArray(/*0*/ p0: kotlin.Array<(out) T!>!, /*1*/ p1: kotlin.(Mutable)Iterator<*>!): kotlin.Array<(out) T!>! + invisible_fake open override /*1*/ /*fake_override*/ fun hugeCapacity(/*0*/ p0: kotlin.Int): kotlin.Int +} + +public abstract class B : kotlin.MutableList, java.util.AbstractList { + public constructor B() + public open override /*2*/ /*fake_override*/ val isEmpty: kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ var modCount: kotlin.Int + public abstract override /*2*/ /*fake_override*/ val size: kotlin.Int + public open override /*2*/ /*fake_override*/ fun add(/*0*/ e: T!): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun add(/*0*/ index: kotlin.Int, /*1*/ element: T!): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun clear(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun contains(/*0*/ o: T!): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*2*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): T! + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*2*/ /*fake_override*/ fun iterator(): kotlin.MutableIterator + public open override /*2*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*2*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator + public open override /*2*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator + invisible_fake open override /*1*/ /*fake_override*/ fun outOfBoundsMsg(/*0*/ p0: kotlin.Int): kotlin.String! + invisible_fake open override /*1*/ /*fake_override*/ fun rangeCheckForAdd(/*0*/ p0: kotlin.Int): kotlin.Unit + public open override /*2*/ fun remove(/*0*/ o: T): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun removeAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ fun removeAt(/*0*/ index: kotlin.Int): T + protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun retainAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: T!): T! + public open override /*2*/ /*fake_override*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.MutableList + public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>! + public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>! + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt new file mode 100644 index 00000000000..d0a956f3a4d --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt @@ -0,0 +1,22 @@ +// FILE: A.java +abstract public class A extends B { + public Integer remove(int x) { } + public boolean remove(Object x) { } +} + +// FILE: main.kt +import java.util.*; + +abstract class B : MutableList, AbstractList() { + override fun removeAt(index: Int): Int = null!! + override fun remove(o: Int): Boolean = null!! +} + +fun main(a: A, b: B, c: ArrayList) { + a.remove(1) + a.removeAt(0) + b.remove(1) + b.removeAt(0) + c.remove(1) + c.removeAt(0) +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt new file mode 100644 index 00000000000..46d44a5a973 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt @@ -0,0 +1,76 @@ +package + +public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: java.util.ArrayList): kotlin.Unit + +public abstract class A : B { + public constructor A() + public open override /*1*/ /*fake_override*/ val isEmpty: kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ var modCount: kotlin.Int + public abstract override /*1*/ /*fake_override*/ val size: kotlin.Int + public open override /*1*/ /*fake_override*/ fun add(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.Int!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun add(/*0*/ e: kotlin.Int!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun contains(/*0*/ o: kotlin.Int!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.Int! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*fake_override*/ fun iterator(): kotlin.MutableIterator + public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator + public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator + invisible_fake open override /*1*/ /*fake_override*/ fun outOfBoundsMsg(/*0*/ p0: kotlin.Int): kotlin.String! + invisible_fake open override /*1*/ /*fake_override*/ fun rangeCheckForAdd(/*0*/ p0: kotlin.Int): kotlin.Unit + public open override /*1*/ /*synthesized*/ fun remove(/*0*/ x: kotlin.Int): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ fun removeAt(/*0*/ x: kotlin.Int): kotlin.Int + protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.Int!): kotlin.Int! + public open override /*1*/ /*fake_override*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.MutableList + public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>! + public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + invisible_fake const final override /*1*/ /*fake_override*/ val MAX_ARRAY_SIZE: kotlin.Int + invisible_fake open override /*1*/ /*fake_override*/ fun finishToArray(/*0*/ p0: kotlin.Array<(out) T!>!, /*1*/ p1: kotlin.(Mutable)Iterator<*>!): kotlin.Array<(out) T!>! + invisible_fake open override /*1*/ /*fake_override*/ fun hugeCapacity(/*0*/ p0: kotlin.Int): kotlin.Int +} + +public abstract class B : kotlin.MutableList, java.util.AbstractList { + public constructor B() + public open override /*2*/ /*fake_override*/ val isEmpty: kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ var modCount: kotlin.Int + public abstract override /*2*/ /*fake_override*/ val size: kotlin.Int + public open override /*2*/ /*fake_override*/ fun add(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.Int!): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun add(/*0*/ e: kotlin.Int!): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun clear(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun contains(/*0*/ o: kotlin.Int!): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*2*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.Int! + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*2*/ /*fake_override*/ fun iterator(): kotlin.MutableIterator + public open override /*2*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*2*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator + public open override /*2*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator + invisible_fake open override /*1*/ /*fake_override*/ fun outOfBoundsMsg(/*0*/ p0: kotlin.Int): kotlin.String! + invisible_fake open override /*1*/ /*fake_override*/ fun rangeCheckForAdd(/*0*/ p0: kotlin.Int): kotlin.Unit + public open override /*2*/ fun remove(/*0*/ o: kotlin.Int): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun removeAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.Int + protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun retainAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.Int!): kotlin.Int! + public open override /*2*/ /*fake_override*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.MutableList + public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>! + public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>! + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 988140e48c3..6e3273c9031 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -9085,6 +9085,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.kt"); doTest(fileName); } + + @TestMetadata("getCharSequence.kt") + public void testGetCharSequence() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.kt"); + doTest(fileName); + } + + @TestMetadata("removeAt.kt") + public void testRemoveAt() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAt.kt"); + doTest(fileName); + } + + @TestMetadata("removeAtInt.kt") + public void testRemoveAtInt() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/j+k/properties") diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/builtinsPropertiesUtil.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/builtinsPropertiesUtil.kt index ac54a5a0035..27f2e3b6963 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/builtinsPropertiesUtil.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/builtinsPropertiesUtil.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.java import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -32,7 +33,9 @@ private val BUILTIN_SPECIAL_PROPERTIES_SHORT_NAMES = BUILTIN_SPECIAL_PROPERTIES_ private val BUILTIN_METHODS_ERASED_COLLECTION_PARAMETER_FQ_NAMES = setOf(FqName("kotlin.Collection.containsAll")) -private val BUILTIN_METHODS_GENERIC_PARAMETERS_FQ_NAMES = setOf(FqName("kotlin.Collection.contains")) +private val BUILTIN_METHODS_GENERIC_PARAMETERS_FQ_NAMES = setOf( + FqName("kotlin.Collection.contains"), FqName("kotlin.MutableCollection.remove") +) private val BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_FQ_NAMES = BUILTIN_METHODS_GENERIC_PARAMETERS_FQ_NAMES + BUILTIN_METHODS_ERASED_COLLECTION_PARAMETER_FQ_NAMES @@ -40,20 +43,40 @@ private val BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_FQ_NAMES = private val BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_SHORT_NAMES = BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_FQ_NAMES.map { it.shortName() }.toSet() -public fun CallableDescriptor.hasBuiltinSpecialPropertyFqName(): Boolean { - if (this is PropertyAccessorDescriptor) return correspondingProperty.hasBuiltinSpecialPropertyFqName() +private object BuiltinSpecialMethods { + val REMOVE_AT_FQ_NAME = FqName("kotlin.MutableList.removeAt") + + val FQ_NAMES_TO_JVM_MAP: Map = mapOf( + REMOVE_AT_FQ_NAME to Name.identifier("remove"), + FqName("kotlin.CharSequence.get") to Name.identifier("charAt") + ) + + val ORIGINAL_SHORT_NAMES: List = FQ_NAMES_TO_JVM_MAP.keySet().map { it.shortName() } + + private val JVM_SHORT_NAME_TO_BUILTIN_FQ_NAMES_MAP: Map> = + FQ_NAMES_TO_JVM_MAP.entrySet().groupBy { it.value }.mapValues { entry -> entry.value.map { it.key } } + + val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map> = + JVM_SHORT_NAME_TO_BUILTIN_FQ_NAMES_MAP.mapValues { it.value.map { it.shortName() } } +} + +public fun CallableMemberDescriptor.hasBuiltinSpecialPropertyFqName(): Boolean { if (name !in BUILTIN_SPECIAL_PROPERTIES_SHORT_NAMES) return false return hasBuiltinSpecialPropertyFqNameImpl() } -private fun CallableDescriptor.hasBuiltinSpecialPropertyFqNameImpl(): Boolean { +private fun CallableMemberDescriptor.hasBuiltinSpecialPropertyFqNameImpl(): Boolean { if (fqNameOrNull() in BUILTIN_SPECIAL_PROPERTIES_FQ_NAMES) return true - if (!fqNameUnsafe.firstSegmentIs(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) return false - if (builtIns.builtInsModule != module) return false + if (!isFromBuiltins()) return false - return overriddenDescriptors.any(CallableDescriptor::hasBuiltinSpecialPropertyFqName) + return overriddenDescriptors.any(CallableMemberDescriptor::hasBuiltinSpecialPropertyFqName) +} + +public fun CallableMemberDescriptor.isFromBuiltins(): Boolean { + if (!(propertyIfAccessor.fqNameOrNull()?.firstSegmentIs(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME) ?: false)) return false + return builtIns.builtInsModule == module } private fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.check { it.isSafe }?.toSafe() @@ -66,28 +89,59 @@ public fun CallableMemberDescriptor.getBuiltinSpecialPropertyAccessorName(): Str @Suppress("UNCHECKED_CAST") fun T.getBuiltinSpecialOverridden(): T? { - return firstOverridden { it.propertyIfAccessor.hasBuiltinSpecialPropertyFqName() } as T? + return when (this) { + is PropertyDescriptor, is PropertyAccessorDescriptor -> + firstOverridden { it.propertyIfAccessor.hasBuiltinSpecialPropertyFqName() } as T? + else -> firstOverridden { it.isBuiltinFunctionWithDifferentNameInJvm() } as T? + } +} + +private fun CallableMemberDescriptor.isBuiltinFunctionWithDifferentNameInJvm(): Boolean { + if (!isFromBuiltins()) return false + val fqName = fqNameOrNull() ?: return false + return firstOverridden { BuiltinSpecialMethods.FQ_NAMES_TO_JVM_MAP.containsKey(fqName) } != null } fun CallableMemberDescriptor.overridesBuiltinSpecialDeclaration(): Boolean = getBuiltinSpecialOverridden() != null public fun CallableMemberDescriptor.getJvmMethodNameIfSpecial(): String? { - return getBuiltinOverriddenThatAffectsJvmName()?.getBuiltinSpecialPropertyAccessorName() + val builtinOverridden = getBuiltinOverriddenThatAffectsJvmName()?.propertyIfAccessor ?: return null + return when (builtinOverridden) { + is PropertyDescriptor -> builtinOverridden.getBuiltinSpecialPropertyAccessorName() + else -> builtinOverridden.specialJvmName()?.asString() + } } private fun CallableMemberDescriptor.getBuiltinOverriddenThatAffectsJvmName(): CallableMemberDescriptor? { - return if (hasBuiltinSpecialPropertyFqName() || original.isFromJava) getBuiltinSpecialOverridden() else null + val overriddenBuiltin = getBuiltinSpecialOverridden() ?: return null + + if (isFromJava || isFromBuiltins()) return overriddenBuiltin + + return null } -private val CallableMemberDescriptor.isFromJava: Boolean - get() = propertyIfAccessor is JavaCallableMemberDescriptor +private fun CallableMemberDescriptor.specialJvmName(): Name? { + return BuiltinSpecialMethods.FQ_NAMES_TO_JVM_MAP[fqNameOrNull() ?: return null] +} -private val CallableMemberDescriptor.propertyIfAccessor: CallableDescriptor +public fun getSpecialBuiltinFunctionsByJvmName(name: Name): List = + BuiltinSpecialMethods.JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP[name] ?: emptyList() + +public val CallableMemberDescriptor.isRemoveAtByIndex: Boolean + get() = name.asString() == "removeAt" && fqNameOrNull() == BuiltinSpecialMethods.REMOVE_AT_FQ_NAME + +private val CallableMemberDescriptor.isFromJava: Boolean + get() = propertyIfAccessor is JavaCallableMemberDescriptor && propertyIfAccessor.containingDeclaration is JavaClassDescriptor + +private val CallableMemberDescriptor.propertyIfAccessor: CallableMemberDescriptor get() = if (this is PropertyAccessorDescriptor) correspondingProperty else this val CallableMemberDescriptor.hasErasedValueParametersInJava: Boolean get() = fqNameOrNull() in BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_FQ_NAMES +val Name.sameAsRenamedInJvmBuiltin: Boolean + get() = this in BuiltinSpecialMethods.ORIGINAL_SHORT_NAMES + fun FunctionDescriptor.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(): FunctionDescriptor? { if (!name.sameAsBuiltinMethodWithErasedValueParameters) return null return firstOverridden { it.hasErasedValueParametersInJava } as FunctionDescriptor? diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index d85d137ae04..8fe5713edb4 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor -import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -36,12 +35,15 @@ import org.jetbrains.kotlin.load.java.lazy.child import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations import org.jetbrains.kotlin.load.java.lazy.types.RawSubstitution import org.jetbrains.kotlin.load.java.lazy.types.toAttributes +import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.typeEnhacement.enhanceSignatures import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.JetTypeChecker @@ -99,9 +101,36 @@ public class LazyJavaClassMemberScope( return !doesClassOverrideAnyProperty(getPropertiesFromSupertypes(name)) } + val javaMethod = (source as? JavaSourceElement)?.javaElement as? JavaMethod + if (javaMethod?.doesOverrideRenamedBuiltins() ?: false) { + return false + } + return true } + private fun JavaMethod.doesOverrideRenamedBuiltins(): Boolean { + return getSpecialBuiltinFunctionsByJvmName(name).any { + builtinName -> + val builtinSpecialFromSuperTypes = + getFunctionsFromSupertypes(builtinName).filter { it.overridesBuiltinSpecialDeclaration() } + if (builtinSpecialFromSuperTypes.isEmpty()) return@any false + + val methodDescriptor = resolveMethodToFunctionDescriptorWithName(this, builtinName) + + builtinSpecialFromSuperTypes.any { isOverridableRenamedDescriptor(it, methodDescriptor) } + } + } + + private fun isOverridableRenamedDescriptor(superDescriptor: FunctionDescriptor, subDescriptor: FunctionDescriptor): Boolean { + // if we check 'removeAt', get original sub-descriptor to distinct `remove(int)` and `remove(E)` in Java + val subDescriptorToCheck = if (superDescriptor.isRemoveAtByIndex) subDescriptor.original else subDescriptor + + return OverridingUtil.DEFAULT.isOverridableByIncludingReturnType( + superDescriptor, subDescriptorToCheck + ).result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE + } + private fun doesClassOverrideAnyProperty(properties: Collection) = properties.any { property -> doesClassOverridesProperty(property) } @@ -141,9 +170,35 @@ public class LazyJavaClassMemberScope( override fun computeNonDeclaredFunctions(result: MutableCollection, name: Name) { val functionsFromSupertypes = getFunctionsFromSupertypes(name) + if (name.sameAsRenamedInJvmBuiltin) { + addOverriddenBuiltinMethods(result, name, functionsFromSupertypes) + } + result.addAll(DescriptorResolverUtils.resolveOverrides(name, functionsFromSupertypes, result, getContainingDeclaration(), c.components.errorReporter)) } + private fun addOverriddenBuiltinMethods( + result: MutableCollection, + name: Name, + functionsFromSupertypes: Set + ) { + // Merge functions with same signatures + val mergedFunctionFromSuperTypes = DescriptorResolverUtils.resolveOverrides( + name, functionsFromSupertypes, emptyList(), getContainingDeclaration(), ErrorReporter.DO_NOTHING) + + for (descriptor in mergedFunctionFromSuperTypes) { + val overriddenBuiltin = descriptor.getBuiltinSpecialOverridden() ?: continue + val nameInJava = overriddenBuiltin.getJvmMethodNameIfSpecial()!! + for (method in memberIndex().findMethodsByName(Name.identifier(nameInJava))) { + val renamedCopy = resolveMethodToFunctionDescriptorWithName(method, name) + + if (isOverridableRenamedDescriptor(overriddenBuiltin, renamedCopy)) { + result.add(renamedCopy) + } + } + } + } + private fun getFunctionsFromSupertypes(name: Name): Set { return getContainingDeclaration().typeConstructor.supertypes.flatMap { it.memberScope.getFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS).map { f -> f as SimpleFunctionDescriptor } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index bf0f4bb346e..532969f16c0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -110,9 +110,13 @@ public abstract class LazyJavaScope( valueParameters: ResolvedValueParameters): MethodSignatureData open fun resolveMethodToFunctionDescriptor(method: JavaMethod): JavaMethodDescriptor { + return resolveMethodToFunctionDescriptorWithName(method, method.name) + } + + protected fun resolveMethodToFunctionDescriptorWithName(method: JavaMethod, name: Name): JavaMethodDescriptor { val annotations = c.resolveAnnotations(method) val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod( - containingDeclaration, annotations, method.getName(), c.components.sourceElementFactory.source(method) + containingDeclaration, annotations, name, c.components.sourceElementFactory.source(method) ) val c = c.child(functionDescriptorImpl, method) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/MemberIndex.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/MemberIndex.kt index 61228b38bac..a93ce8e5b6c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/MemberIndex.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/MemberIndex.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.utils.valuesToMap import java.util.HashSet @@ -38,6 +39,11 @@ object EMPTY_MEMBER_INDEX : MemberIndex { override fun getAllFieldNames() = listOf() } +private val ADDITIONAL_MEMBER_NAMES_MAP = mapOf( + FqName("java.util.List") to listOf(Name.identifier("removeAt")), + FqName("java.lang.CharSequence") to listOf(Name.identifier("get")) +) + open class ClassMemberIndex(val jClass: JavaClass, val memberFilter: (JavaMember) -> Boolean) : MemberIndex { private val methodFilter = { m: JavaMethod -> @@ -48,12 +54,17 @@ open class ClassMemberIndex(val jClass: JavaClass, val memberFilter: (JavaMember private val fields = jClass.getFields().asSequence().filter(memberFilter).valuesToMap { m -> m.getName() } override fun findMethodsByName(name: Name): Collection = methods[name] ?: listOf() - override fun getMethodNames(nameFilter: (Name) -> Boolean): Collection = jClass.getAllMemberNames(methodFilter) { getMethods() } + override fun getMethodNames(nameFilter: (Name) -> Boolean): Collection = + jClass.getAllMemberNames(methodFilter) { getMethods() } override fun findFieldByName(name: Name): JavaField? = fields[name] override fun getAllFieldNames(): Collection = jClass.getAllMemberNames(memberFilter) { getFields() } } +private fun JavaClass.getNonDeclaredMethodNames(): List { + return ADDITIONAL_MEMBER_NAMES_MAP[this.fqName].orEmpty() +} + private fun JavaClass.getAllMemberNames(filter: (M) -> Boolean, getMembers: JavaClass.() -> Collection): Set { val result = HashSet() val visitedSuperClasses = HashSet() @@ -70,6 +81,7 @@ private fun JavaClass.getAllMemberNames(filter: (M) -> Boolean, for (supertype in getSupertypes()) { val classifier = supertype.getClassifier() if (classifier is JavaClass) { + result.addAll(classifier.getNonDeclaredMethodNames()) classifier.visit() } }