Support generic constructors defined in Java
#KT-10686 Fixed #KT-10410 Fixed
This commit is contained in:
@@ -75,5 +75,6 @@ fun LazyJavaResolverContext.child(
|
||||
|
||||
fun LazyJavaResolverContext.child(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner
|
||||
) = this.child(LazyJavaTypeParameterResolver(this, containingDeclaration, typeParameterOwner))
|
||||
typeParameterOwner: JavaTypeParameterListOwner,
|
||||
typeParametersIndexOffset: Int = 0
|
||||
) = this.child(LazyJavaTypeParameterResolver(this, containingDeclaration, typeParameterOwner, typeParametersIndexOffset))
|
||||
|
||||
+7
-2
@@ -506,9 +506,14 @@ class LazyJavaClassMemberScope(
|
||||
classDescriptor, c.resolveAnnotations(constructor), /* isPrimary = */ false, c.components.sourceElementFactory.source(constructor)
|
||||
)
|
||||
|
||||
val valueParameters = resolveValueParameters(c, constructorDescriptor, constructor.valueParameters)
|
||||
|
||||
constructorDescriptor.initialize(valueParameters.descriptors, constructor.visibility)
|
||||
val c = c.child(constructorDescriptor, constructor, typeParametersIndexOffset = classDescriptor.declaredTypeParameters.size)
|
||||
val valueParameters = resolveValueParameters(c, constructorDescriptor, constructor.valueParameters)
|
||||
val constructorTypeParameters =
|
||||
classDescriptor.declaredTypeParameters +
|
||||
constructor.typeParameters.map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
|
||||
|
||||
constructorDescriptor.initialize(valueParameters.descriptors, constructor.visibility, constructorTypeParameters)
|
||||
constructorDescriptor.setHasStableParameterNames(false)
|
||||
constructorDescriptor.setHasSynthesizedParameterNames(valueParameters.hasSynthesizedNames)
|
||||
|
||||
|
||||
@@ -43,14 +43,15 @@ interface TypeParameterResolver {
|
||||
class LazyJavaTypeParameterResolver(
|
||||
private val c: LazyJavaResolverContext,
|
||||
private val containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner
|
||||
typeParameterOwner: JavaTypeParameterListOwner,
|
||||
private val typeParametersIndexOffset: Int
|
||||
) : TypeParameterResolver {
|
||||
private val typeParameters: Map<JavaTypeParameter, Int> = typeParameterOwner.typeParameters.mapToIndex()
|
||||
|
||||
private val resolve = c.storageManager.createMemoizedFunctionWithNullableValues {
|
||||
typeParameter: JavaTypeParameter ->
|
||||
typeParameters[typeParameter]?.let { index ->
|
||||
LazyJavaTypeParameterDescriptor(c.child(this), typeParameter, index, containingDeclaration)
|
||||
LazyJavaTypeParameterDescriptor(c.child(this), typeParameter, typeParametersIndexOffset + index, containingDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-32
@@ -116,13 +116,8 @@ class LazyJavaTypeResolver(
|
||||
?: ErrorUtils.createErrorTypeConstructor("Unresolved java classifier: " + javaType.presentableText)
|
||||
}
|
||||
is JavaTypeParameter -> {
|
||||
if (isConstructorTypeParameter()) {
|
||||
getConstructorTypeParameterSubstitute().getConstructor()
|
||||
}
|
||||
else {
|
||||
typeParameterResolver.resolveTypeParameter(classifier)?.typeConstructor
|
||||
?: ErrorUtils.createErrorTypeConstructor("Unresolved Java type parameter: " + javaType.presentableText)
|
||||
}
|
||||
typeParameterResolver.resolveTypeParameter(classifier)?.typeConstructor
|
||||
?: ErrorUtils.createErrorTypeConstructor("Unresolved Java type parameter: " + javaType.presentableText)
|
||||
}
|
||||
else -> throw IllegalStateException("Unknown classifier kind: $classifier")
|
||||
}
|
||||
@@ -158,24 +153,6 @@ class LazyJavaTypeResolver(
|
||||
return kotlinDescriptor
|
||||
}
|
||||
|
||||
private fun isConstructorTypeParameter(): Boolean {
|
||||
val classifier = classifier()
|
||||
return classifier is JavaTypeParameter && classifier.getOwner() is JavaConstructor
|
||||
}
|
||||
|
||||
// We do not memoize the results of this method, because it would consume much memory, and the real gain is little:
|
||||
// the case this method accounts for is very rare, no point in optimizing it
|
||||
private fun getConstructorTypeParameterSubstitute(): KotlinType {
|
||||
// If a Java constructor declares its own type parameters, we have no way of directly expressing them in Kotlin,
|
||||
// so we replace each type parameter with its representative upper bound (which in Java is also the first bound)
|
||||
val upperBounds = (classifier() as JavaTypeParameter).upperBounds
|
||||
if (upperBounds.isEmpty()) {
|
||||
return c.module.builtIns.nullableAnyType
|
||||
}
|
||||
|
||||
return transformJavaType(upperBounds.first(), UPPER_BOUND.toAttributes())
|
||||
}
|
||||
|
||||
private fun isRaw(): Boolean {
|
||||
if (javaType.isRaw) return true
|
||||
|
||||
@@ -212,9 +189,6 @@ class LazyJavaTypeResolver(
|
||||
RawSubstitution.computeProjection(parameter, attr, erasedUpperBound)
|
||||
}
|
||||
}
|
||||
if (isConstructorTypeParameter()) {
|
||||
return getConstructorTypeParameterSubstitute().getArguments()
|
||||
}
|
||||
|
||||
if (typeParameters.size != javaType.typeArguments.size) {
|
||||
// Most of the time this means there is an error in the Java code
|
||||
@@ -265,10 +239,7 @@ class LazyJavaTypeResolver(
|
||||
// nullability will be taken care of in individual member signatures
|
||||
when (classifier()) {
|
||||
is JavaTypeParameter -> {
|
||||
if (isConstructorTypeParameter())
|
||||
getConstructorTypeParameterSubstitute().isMarkedNullable()
|
||||
else
|
||||
attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT, SUPERTYPE)
|
||||
attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT, SUPERTYPE)
|
||||
}
|
||||
is JavaClass,
|
||||
null -> attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE)
|
||||
|
||||
Reference in New Issue
Block a user