Setup specific loading contains/containsAll from java
If they override Kotlin collection members contains(Object) -> contains(E) containsAll(Collection<?>) -> containsAll(Collection<E>)
This commit is contained in:
+49
-1
@@ -24,12 +24,23 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
private val BUILTIN_SPECIAL_PROPERTIES_FQ_NAMES = setOf(FqName("kotlin.Collection.size"), FqName("kotlin.Map.size"))
|
||||
private val BUILTIN_SPECIAL_PROPERTIES_SHORT_NAMES = BUILTIN_SPECIAL_PROPERTIES_FQ_NAMES.map { it.shortName() }.toSet()
|
||||
|
||||
|
||||
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_ERASED_VALUE_PARAMETERS_FQ_NAMES =
|
||||
BUILTIN_METHODS_GENERIC_PARAMETERS_FQ_NAMES + BUILTIN_METHODS_ERASED_COLLECTION_PARAMETER_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()
|
||||
if (name !in BUILTIN_SPECIAL_PROPERTIES_SHORT_NAMES) return false
|
||||
@@ -38,7 +49,7 @@ public fun CallableDescriptor.hasBuiltinSpecialPropertyFqName(): Boolean {
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.hasBuiltinSpecialPropertyFqNameImpl(): Boolean {
|
||||
if (fqNameUnsafe.check { it.isSafe }?.toSafe() in BUILTIN_SPECIAL_PROPERTIES_FQ_NAMES) return true
|
||||
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
|
||||
@@ -46,6 +57,8 @@ private fun CallableDescriptor.hasBuiltinSpecialPropertyFqNameImpl(): Boolean {
|
||||
return overriddenDescriptors.any(CallableDescriptor::hasBuiltinSpecialPropertyFqName)
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.check { it.isSafe }?.toSafe()
|
||||
|
||||
val Name.isBuiltinSpecialPropertyName: Boolean get() = this in BUILTIN_SPECIAL_PROPERTIES_SHORT_NAMES
|
||||
|
||||
private val CallableDescriptor.builtinSpecialPropertyAccessorName: String?
|
||||
@@ -78,3 +91,38 @@ private val CallableDescriptor.isFromJava: Boolean
|
||||
|
||||
private val CallableDescriptor.propertyIfAccessor: CallableDescriptor
|
||||
get() = if (this is PropertyAccessorDescriptor) correspondingProperty else this
|
||||
|
||||
val CallableMemberDescriptor.hasErasedValueParametersInJava: Boolean
|
||||
get() = fqNameOrNull() in BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_FQ_NAMES
|
||||
|
||||
|
||||
val FunctionDescriptor.overriddenBuiltinFunctionWithErasedValueParametersInJava: FunctionDescriptor?
|
||||
get() {
|
||||
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return null
|
||||
return firstOverridden { it.hasErasedValueParametersInJava } as FunctionDescriptor?
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.firstOverridden(
|
||||
predicate: (CallableMemberDescriptor) -> Boolean
|
||||
): CallableMemberDescriptor? {
|
||||
var result: CallableMemberDescriptor? = null
|
||||
return DFS.dfs(listOf(this),
|
||||
object : DFS.Neighbors<CallableMemberDescriptor> {
|
||||
override fun getNeighbors(current: CallableMemberDescriptor?): Iterable<CallableMemberDescriptor> {
|
||||
return current?.overriddenDescriptors ?: emptyList()
|
||||
}
|
||||
},
|
||||
object : DFS.AbstractNodeHandler<CallableMemberDescriptor, CallableMemberDescriptor?>() {
|
||||
override fun beforeChildren(current: CallableMemberDescriptor) = result == null
|
||||
override fun afterChildren(current: CallableMemberDescriptor) {
|
||||
if (result == null && predicate(current)) {
|
||||
result = current
|
||||
}
|
||||
}
|
||||
override fun result(): CallableMemberDescriptor? = result
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean
|
||||
get () = this in BUILTIN_METHODS_ERASED_VALUE_PARAMETERS_SHORT_NAMES
|
||||
|
||||
+71
-7
@@ -23,18 +23,16 @@ import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.java.builtinSpecialOverridden
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.isBuiltinSpecialPropertyName
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
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.structure.JavaArrayType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
@@ -49,6 +47,8 @@ import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
import org.jetbrains.kotlin.utils.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import java.util.*
|
||||
|
||||
public class LazyJavaClassMemberScope(
|
||||
@@ -105,12 +105,13 @@ public class LazyJavaClassMemberScope(
|
||||
}
|
||||
|
||||
override fun computeNonDeclaredFunctions(result: MutableCollection<SimpleFunctionDescriptor>, name: Name) {
|
||||
val functionsFromSupertypes = getFunctionsFromSupertypes(name, getContainingDeclaration())
|
||||
val functionsFromSupertypes = getFunctionsFromSupertypes(name)
|
||||
|
||||
result.addAll(DescriptorResolverUtils.resolveOverrides(name, functionsFromSupertypes, result, getContainingDeclaration(), c.components.errorReporter))
|
||||
}
|
||||
|
||||
private fun getFunctionsFromSupertypes(name: Name, descriptor: ClassDescriptor): Set<SimpleFunctionDescriptor> {
|
||||
return descriptor.typeConstructor.supertypes.flatMap {
|
||||
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 }
|
||||
}.toSet()
|
||||
}
|
||||
@@ -193,6 +194,69 @@ public class LazyJavaClassMemberScope(
|
||||
return LazyJavaScope.MethodSignatureData(effectiveSignature, propagated.getErrors() + effectiveSignature.getErrors())
|
||||
}
|
||||
|
||||
override fun resolveMethodToFunctionDescriptor(method: JavaMethod): JavaMethodDescriptor {
|
||||
val commonResult = super.resolveMethodToFunctionDescriptor(method)
|
||||
|
||||
if (commonResult.name.sameAsBuiltinMethodWithErasedValueParameters) {
|
||||
val erasedCopy = createOverrideForErasedIfNeeded(commonResult)
|
||||
if (erasedCopy != null) return erasedCopy
|
||||
}
|
||||
|
||||
return commonResult
|
||||
}
|
||||
|
||||
private fun createOverrideForErasedIfNeeded(
|
||||
methodDescriptor: JavaMethodDescriptor
|
||||
): JavaMethodDescriptor? {
|
||||
|
||||
val overriddenCandidates =
|
||||
getFunctionsFromSupertypes(methodDescriptor.name).map { it.overriddenBuiltinFunctionWithErasedValueParametersInJava }.filterNotNull()
|
||||
|
||||
if (overriddenCandidates.isEmpty()) return null
|
||||
|
||||
val overridden = firstOverriddenBuiltinFunctionWithErasedValueParameters(methodDescriptor, overriddenCandidates) ?: return null
|
||||
|
||||
return methodDescriptor
|
||||
.enhance(
|
||||
methodDescriptor.extensionReceiverParameter?.type,
|
||||
overridden.valueParameters.map { it.type },
|
||||
methodDescriptor.returnType!!)
|
||||
.copy(
|
||||
methodDescriptor.containingDeclaration,
|
||||
methodDescriptor.modality, methodDescriptor.visibility,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED, false) as? JavaMethodDescriptor
|
||||
}
|
||||
|
||||
private fun firstOverriddenBuiltinFunctionWithErasedValueParameters(
|
||||
javaMethodDescriptor: JavaMethodDescriptor,
|
||||
candidatesToOverride: Collection<FunctionDescriptor>
|
||||
): FunctionDescriptor? {
|
||||
return candidatesToOverride.firstNotNullResult overrides@{
|
||||
candidate ->
|
||||
candidate.check { javaMethodDescriptor.doesOverrideBuiltinFunctionWithErasedValueParameters(candidate) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun JavaMethodDescriptor.doesOverrideBuiltinFunctionWithErasedValueParameters(
|
||||
builtinWithErasedParameters: FunctionDescriptor
|
||||
): Boolean {
|
||||
if (this.valueParameters.size() != builtinWithErasedParameters.valueParameters.size()) return false
|
||||
if (!this.typeParameters.isEmpty() || !builtinWithErasedParameters.typeParameters.isEmpty()) return false
|
||||
if (this.extensionReceiverParameter != null || builtinWithErasedParameters.extensionReceiverParameter != null) return false
|
||||
|
||||
return this.valueParameters.indices.all {
|
||||
index ->
|
||||
val currentType = valueParameters[index].type
|
||||
val overriddenCandidate = RawSubstitution.eraseType(
|
||||
builtinWithErasedParameters.original.valueParameters[index].type)
|
||||
JetTypeChecker.DEFAULT.equalTypes(currentType, overriddenCandidate)
|
||||
} && returnType.isSubtypeOf(builtinWithErasedParameters.returnType)
|
||||
}
|
||||
|
||||
private fun JetType?.isSubtypeOf(other: JetType?): Boolean {
|
||||
return JetTypeChecker.DEFAULT.isSubtypeOf(this ?: return false, other ?: return false)
|
||||
}
|
||||
|
||||
private fun resolveConstructor(constructor: JavaConstructor): JavaConstructorDescriptor {
|
||||
val classDescriptor = getContainingDeclaration()
|
||||
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ public abstract class LazyJavaScope(
|
||||
returnType: JetType,
|
||||
valueParameters: ResolvedValueParameters): MethodSignatureData
|
||||
|
||||
fun resolveMethodToFunctionDescriptor(method: JavaMethod): JavaMethodDescriptor {
|
||||
open fun resolveMethodToFunctionDescriptor(method: JavaMethod): JavaMethodDescriptor {
|
||||
val annotations = c.resolveAnnotations(method)
|
||||
val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod(
|
||||
containingDeclaration, annotations, method.getName(), c.components.sourceElementFactory.source(method)
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ internal object RawSubstitution : TypeSubstitution() {
|
||||
private val lowerTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND)
|
||||
private val upperTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND)
|
||||
|
||||
private fun eraseType(type: JetType): JetType {
|
||||
public fun eraseType(type: JetType): JetType {
|
||||
val declaration = type.constructor.declarationDescriptor
|
||||
return when (declaration) {
|
||||
is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound())
|
||||
|
||||
Reference in New Issue
Block a user