Support loading builtin methods from Java with different names

This commit is contained in:
Denis Zharkov
2015-10-10 18:47:18 +03:00
parent 3f5498e9f5
commit 742a538aed
11 changed files with 413 additions and 16 deletions
@@ -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)
}
@@ -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
}
@@ -0,0 +1,22 @@
// FILE: A.java
abstract public class A<F> extends B<F> {
public F remove(int x) { }
public boolean remove(Object x) { }
}
// FILE: main.kt
import java.util.*;
abstract class B<T> : MutableList<T>, AbstractList<T>() {
override fun removeAt(index: Int): T = null!!
override fun remove(o: T): Boolean = null!!
}
fun main(a: A<String>, b: B<String>, c: ArrayList<String>) {
a.remove("")
a.removeAt(0)
b.remove("")
b.removeAt(0)
c.remove("")
c.removeAt(0)
}
@@ -0,0 +1,76 @@
package
public fun main(/*0*/ a: A<kotlin.String>, /*1*/ b: B<kotlin.String>, /*2*/ c: java.util.ArrayList<kotlin.String>): kotlin.Unit
public abstract class A</*0*/ F : kotlin.Any!> : B<F!> {
public constructor A</*0*/ F : kotlin.Any!>()
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<F!>): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection<F!>): 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<F!>): 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<F!>
public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int
public open override /*1*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator<F!>
public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator<F!>
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.Any?>): 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.Any?>): 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<F!>
public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>!
public open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> 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 </*0*/ T : kotlin.Any!> 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</*0*/ T> : kotlin.MutableList<T>, java.util.AbstractList<T> {
public constructor B</*0*/ T>()
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<T!>): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection<T!>): 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<T!>): 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<T!>
public open override /*2*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int
public open override /*2*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator<T!>
public open override /*2*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator<T!>
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.Any?>): 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.Any?>): 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<T!>
public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>!
public open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>!
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -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<Int>, AbstractList<Int>() {
override fun removeAt(index: Int): Int = null!!
override fun remove(o: Int): Boolean = null!!
}
fun main(a: A, b: B, c: ArrayList<Int>) {
a.remove(1)
a.removeAt(0)
b.remove(1)
b.removeAt(0)
c.remove(1)
c.removeAt(0)
}
@@ -0,0 +1,76 @@
package
public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: java.util.ArrayList<kotlin.Int>): 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.Int!>): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection<kotlin.Int!>): 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.Int!>): 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<kotlin.Int!>
public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int
public open override /*1*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator<kotlin.Int!>
public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator<kotlin.Int!>
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.Any?>): 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.Any?>): 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<kotlin.Int!>
public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>!
public open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> 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 </*0*/ T : kotlin.Any!> 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<kotlin.Int>, java.util.AbstractList<kotlin.Int> {
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.Int!>): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ c: kotlin.Collection<kotlin.Int!>): 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.Int!>): 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<kotlin.Int!>
public open override /*2*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int
public open override /*2*/ /*fake_override*/ fun listIterator(): kotlin.MutableListIterator<kotlin.Int!>
public open override /*2*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator<kotlin.Int!>
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.Any?>): 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.Any?>): 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<kotlin.Int!>
public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!>!
public open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> toArray(/*0*/ p0: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>!
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -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")
@@ -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<FqName, Name> = mapOf(
REMOVE_AT_FQ_NAME to Name.identifier("remove"),
FqName("kotlin.CharSequence.get") to Name.identifier("charAt")
)
val ORIGINAL_SHORT_NAMES: List<Name> = FQ_NAMES_TO_JVM_MAP.keySet().map { it.shortName() }
private val JVM_SHORT_NAME_TO_BUILTIN_FQ_NAMES_MAP: Map<Name, List<FqName>> =
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<Name, List<Name>> =
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 : CallableMemberDescriptor> 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<Name> =
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?
@@ -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<PropertyDescriptor>)
= properties.any { property -> doesClassOverridesProperty(property) }
@@ -141,9 +170,35 @@ public class LazyJavaClassMemberScope(
override fun computeNonDeclaredFunctions(result: MutableCollection<SimpleFunctionDescriptor>, 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<SimpleFunctionDescriptor>,
name: Name,
functionsFromSupertypes: Set<SimpleFunctionDescriptor>
) {
// 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<SimpleFunctionDescriptor> {
return getContainingDeclaration().typeConstructor.supertypes.flatMap {
it.memberScope.getFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS).map { f -> f as SimpleFunctionDescriptor }
@@ -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)
@@ -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<Name>()
}
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<JavaMethod> = methods[name] ?: listOf()
override fun getMethodNames(nameFilter: (Name) -> Boolean): Collection<Name> = jClass.getAllMemberNames(methodFilter) { getMethods() }
override fun getMethodNames(nameFilter: (Name) -> Boolean): Collection<Name> =
jClass.getAllMemberNames(methodFilter) { getMethods() }
override fun findFieldByName(name: Name): JavaField? = fields[name]
override fun getAllFieldNames(): Collection<Name> = jClass.getAllMemberNames(memberFilter) { getFields() }
}
private fun JavaClass.getNonDeclaredMethodNames(): List<Name> {
return ADDITIONAL_MEMBER_NAMES_MAP[this.fqName].orEmpty()
}
private fun <M : JavaMember> JavaClass.getAllMemberNames(filter: (M) -> Boolean, getMembers: JavaClass.() -> Collection<M>): Set<Name> {
val result = HashSet<Name>()
val visitedSuperClasses = HashSet<JavaClass>()
@@ -70,6 +81,7 @@ private fun <M : JavaMember> JavaClass.getAllMemberNames(filter: (M) -> Boolean,
for (supertype in getSupertypes()) {
val classifier = supertype.getClassifier()
if (classifier is JavaClass) {
result.addAll(classifier.getNonDeclaredMethodNames())
classifier.visit()
}
}