FIR: rearrange some stuff in Java type conversion code
This commit is contained in:
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
|
||||||
|
|
||||||
private fun ClassId.toLookupTag(): ConeClassLikeLookupTag =
|
private fun ClassId.toLookupTag(): ConeClassLikeLookupTag =
|
||||||
ConeClassLikeLookupTagImpl(this)
|
ConeClassLikeLookupTagImpl(this)
|
||||||
@@ -75,91 +74,75 @@ internal fun JavaType?.toFirResolvedTypeRef(
|
|||||||
mode: FirJavaTypeConversionMode = FirJavaTypeConversionMode.DEFAULT
|
mode: FirJavaTypeConversionMode = FirJavaTypeConversionMode.DEFAULT
|
||||||
): FirResolvedTypeRef {
|
): FirResolvedTypeRef {
|
||||||
return buildResolvedTypeRef {
|
return buildResolvedTypeRef {
|
||||||
type = toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode)
|
type = toConeKotlinType(session, javaTypeParameterStack, mode)
|
||||||
.let { if (mode == FirJavaTypeConversionMode.SUPERTYPE) it.lowerBoundIfFlexible() else it }
|
.let { if (mode == FirJavaTypeConversionMode.SUPERTYPE) it.lowerBoundIfFlexible() else it }
|
||||||
annotations += type.attributes.customAnnotations
|
annotations += type.attributes.customAnnotations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaType?.toConeKotlinTypeWithoutEnhancement(
|
private fun JavaType?.toConeKotlinType(
|
||||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack,
|
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
mode: FirJavaTypeConversionMode
|
mode: FirJavaTypeConversionMode
|
||||||
): ConeKotlinType {
|
): ConeKotlinType =
|
||||||
|
toConeTypeProjection(session, javaTypeParameterStack, Variance.INVARIANT, mode).type
|
||||||
|
?: StandardClassIds.Any.toConeFlexibleType(emptyArray(), emptyArray(), ConeAttributes.Empty)
|
||||||
|
|
||||||
|
private fun JavaType?.toConeTypeProjection(
|
||||||
|
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
|
parameterVariance: Variance, mode: FirJavaTypeConversionMode
|
||||||
|
): ConeTypeProjection {
|
||||||
val attributes = if (this != null && annotations.isNotEmpty())
|
val attributes = if (this != null && annotations.isNotEmpty())
|
||||||
ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertAnnotationsToFir(session, javaTypeParameterStack))))
|
ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertAnnotationsToFir(session, javaTypeParameterStack))))
|
||||||
else
|
else
|
||||||
ConeAttributes.Empty
|
ConeAttributes.Empty
|
||||||
|
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JavaClassifierType ->
|
is JavaClassifierType -> {
|
||||||
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode, attributes)
|
val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes)
|
||||||
is JavaPrimitiveType -> {
|
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
|
||||||
val primitiveType = type
|
return lowerBound // TODO: `KClass<Any>` is wrong for raw `Class`
|
||||||
val kotlinPrimitiveName = when (val javaName = primitiveType?.typeName?.asString()) {
|
|
||||||
null -> "Unit"
|
|
||||||
else -> javaName.capitalizeAsciiOnly()
|
|
||||||
}
|
}
|
||||||
|
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, lowerBound)
|
||||||
val classId = StandardClassIds.byName(kotlinPrimitiveName)
|
if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
|
||||||
classId.constructClassLikeType(emptyArray(), isNullable = false, attributes)
|
|
||||||
}
|
}
|
||||||
is JavaArrayType ->
|
|
||||||
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode, attributes)
|
is JavaArrayType -> {
|
||||||
is JavaWildcardType ->
|
val (classId, arguments) = when (val componentType = componentType) {
|
||||||
bound?.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode)
|
is JavaPrimitiveType ->
|
||||||
null -> null
|
StandardClassIds.byName(componentType.type!!.arrayTypeName.identifier) to arrayOf()
|
||||||
|
else ->
|
||||||
|
StandardClassIds.Array to arrayOf(componentType.toConeKotlinType(session, javaTypeParameterStack, mode))
|
||||||
|
}
|
||||||
|
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
|
||||||
|
classId.constructClassLikeType(arguments, isNullable = false, attributes)
|
||||||
|
} else {
|
||||||
|
val argumentsForUpper = Array(arguments.size) { ConeKotlinTypeProjectionOut(arguments[it]) }
|
||||||
|
classId.toConeFlexibleType(arguments, argumentsForUpper, attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is JavaPrimitiveType ->
|
||||||
|
StandardClassIds.byName(type?.typeName?.identifier ?: "Unit")
|
||||||
|
.constructClassLikeType(emptyArray(), isNullable = false, attributes)
|
||||||
|
|
||||||
|
is JavaWildcardType -> {
|
||||||
|
// TODO: this discards annotations on wildcards, allowed since Java 8 - what do they mean?
|
||||||
|
// List<@NotNull ? extends @Nullable Object>
|
||||||
|
val bound = this.bound
|
||||||
|
val argumentVariance = if (isExtends) Variance.OUT_VARIANCE else Variance.IN_VARIANCE
|
||||||
|
if (bound == null || (parameterVariance != Variance.INVARIANT && parameterVariance != argumentVariance)) {
|
||||||
|
ConeStarProjection
|
||||||
|
} else {
|
||||||
|
val boundType = bound.toConeKotlinType(session, javaTypeParameterStack, mode)
|
||||||
|
if (isExtends) ConeKotlinTypeProjectionOut(boundType) else ConeKotlinTypeProjectionIn(boundType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
null -> ConeStarProjection
|
||||||
else -> error("Strange JavaType: ${this::class.java}")
|
else -> error("Strange JavaType: ${this::class.java}")
|
||||||
} ?: StandardClassIds.Any.toConeFlexibleType(emptyArray(), emptyArray(), attributes = attributes)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
|
|
||||||
session: FirSession,
|
|
||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
|
||||||
mode: FirJavaTypeConversionMode,
|
|
||||||
attributes: ConeAttributes
|
|
||||||
): ConeKotlinType {
|
|
||||||
val componentType = componentType
|
|
||||||
return if (componentType !is JavaPrimitiveType) {
|
|
||||||
val classId = StandardClassIds.Array
|
|
||||||
val argumentType = componentType.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, mode)
|
|
||||||
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
|
|
||||||
classId.constructClassLikeType(arrayOf(argumentType), isNullable = false, attributes = attributes)
|
|
||||||
} else {
|
|
||||||
classId.toConeFlexibleType(
|
|
||||||
arrayOf(argumentType),
|
|
||||||
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType)),
|
|
||||||
attributes = attributes
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val javaComponentName = componentType.type?.typeName?.asString()?.capitalizeAsciiOnly() ?: error("Array of voids")
|
|
||||||
val classId = StandardClassIds.byName(javaComponentName + "Array")
|
|
||||||
|
|
||||||
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
|
|
||||||
classId.constructClassLikeType(emptyArray(), isNullable = false, attributes = attributes)
|
|
||||||
} else {
|
|
||||||
classId.toConeFlexibleType(emptyArray(), emptyArray(), attributes = attributes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
|
|
||||||
session: FirSession,
|
|
||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
|
||||||
mode: FirJavaTypeConversionMode,
|
|
||||||
attributes: ConeAttributes
|
|
||||||
): ConeKotlinType {
|
|
||||||
val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes)
|
|
||||||
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
|
|
||||||
return lowerBound
|
|
||||||
}
|
|
||||||
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, lowerBound)
|
|
||||||
return if (isRaw)
|
|
||||||
ConeRawType(lowerBound, upperBound)
|
|
||||||
else
|
|
||||||
ConeFlexibleType(lowerBound, upperBound)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
|
private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
@@ -192,9 +175,11 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
|
|||||||
?: Array(classifier.typeParameters.size) { ConeStarProjection }
|
?: Array(classifier.typeParameters.size) { ConeStarProjection }
|
||||||
lookupTag != lowerBound?.lookupTag ->
|
lookupTag != lowerBound?.lookupTag ->
|
||||||
Array(typeArguments.size) { index ->
|
Array(typeArguments.size) { index ->
|
||||||
|
// TODO: check this
|
||||||
|
val newMode = if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) FirJavaTypeConversionMode.DEFAULT else mode
|
||||||
val argument = typeArguments[index]
|
val argument = typeArguments[index]
|
||||||
val parameter = typeParameters?.getOrNull(index)?.symbol?.fir
|
val variance = typeParameters?.getOrNull(index)?.symbol?.fir?.variance ?: Variance.INVARIANT
|
||||||
argument.toConeProjectionWithoutEnhancement(session, javaTypeParameterStack, parameter, mode)
|
argument.toConeTypeProjection(session, javaTypeParameterStack, variance, newMode)
|
||||||
}
|
}
|
||||||
else -> lowerBound.typeArguments
|
else -> lowerBound.typeArguments
|
||||||
}
|
}
|
||||||
@@ -266,32 +251,3 @@ private fun ConeKotlinType.eraseAsUpperBound(session: FirSession, cache: Mutable
|
|||||||
original.eraseAsUpperBound(session, cache).makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
|
original.eraseAsUpperBound(session, cache).makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
|
||||||
else -> error("unexpected Java type parameter upper bound kind: $this")
|
else -> error("unexpected Java type parameter upper bound kind: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaType?.toConeProjectionWithoutEnhancement(
|
|
||||||
session: FirSession,
|
|
||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
|
||||||
boundTypeParameter: FirTypeParameter?,
|
|
||||||
mode: FirJavaTypeConversionMode
|
|
||||||
): ConeTypeProjection {
|
|
||||||
// TODO: check this
|
|
||||||
val newMode = mode.takeIf { it == FirJavaTypeConversionMode.SUPERTYPE } ?: FirJavaTypeConversionMode.DEFAULT
|
|
||||||
return when (this) {
|
|
||||||
null -> ConeStarProjection
|
|
||||||
is JavaWildcardType -> {
|
|
||||||
val bound = this.bound
|
|
||||||
val argumentVariance = if (isExtends) Variance.OUT_VARIANCE else Variance.IN_VARIANCE
|
|
||||||
val parameterVariance = boundTypeParameter?.variance ?: Variance.INVARIANT
|
|
||||||
if (bound == null || parameterVariance != Variance.INVARIANT && parameterVariance != argumentVariance) {
|
|
||||||
ConeStarProjection
|
|
||||||
} else {
|
|
||||||
val boundType = bound.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, newMode)
|
|
||||||
if (argumentVariance == Variance.OUT_VARIANCE) {
|
|
||||||
ConeKotlinTypeProjectionOut(boundType)
|
|
||||||
} else {
|
|
||||||
ConeKotlinTypeProjectionIn(boundType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, newMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
|||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
@@ -30,7 +29,6 @@ import org.jetbrains.kotlin.load.java.typeEnhancement.*
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import org.jetbrains.kotlin.utils.extractRadix
|
import org.jetbrains.kotlin.utils.extractRadix
|
||||||
|
|
||||||
@@ -71,10 +69,7 @@ private fun ConeKotlinType.enhanceConeKotlinType(
|
|||||||
when {
|
when {
|
||||||
lowerResult == null && upperResult == null -> null
|
lowerResult == null && upperResult == null -> null
|
||||||
this is ConeRawType -> ConeRawType(lowerResult ?: lowerBound, upperResult ?: upperBound)
|
this is ConeRawType -> ConeRawType(lowerResult ?: lowerBound, upperResult ?: upperBound)
|
||||||
else -> coneFlexibleOrSimpleType(
|
else -> coneFlexibleOrSimpleType(session.typeContext, lowerResult ?: lowerBound, upperResult ?: upperBound)
|
||||||
session, lowerResult ?: lowerBound, upperResult ?: upperBound,
|
|
||||||
isNotNullTypeParameter = qualifiers(index).isNotNullTypeParameter
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ConeSimpleKotlinType -> enhanceInflexibleType(
|
is ConeSimpleKotlinType -> enhanceInflexibleType(
|
||||||
@@ -84,34 +79,6 @@ private fun ConeKotlinType.enhanceConeKotlinType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun coneFlexibleOrSimpleType(
|
|
||||||
session: FirSession,
|
|
||||||
lowerBound: ConeKotlinType,
|
|
||||||
upperBound: ConeKotlinType,
|
|
||||||
isNotNullTypeParameter: Boolean
|
|
||||||
): ConeKotlinType {
|
|
||||||
if (AbstractStrictEqualityTypeChecker.strictEqualTypes(session.typeContext, lowerBound, upperBound)) {
|
|
||||||
val lookupTag = (lowerBound as? ConeLookupTagBasedType)?.lookupTag
|
|
||||||
if (isNotNullTypeParameter && lookupTag is ConeTypeParameterLookupTag && !lowerBound.isMarkedNullable) {
|
|
||||||
// TODO: we need enhancement for type parameter bounds for this code to work properly
|
|
||||||
// At this moment, this condition is always true
|
|
||||||
if (lookupTag.typeParameterSymbol.fir.bounds.any {
|
|
||||||
val type = it.coneType
|
|
||||||
type is ConeTypeParameterType || type.isNullable
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return ConeDefinitelyNotNullType.create(
|
|
||||||
lowerBound,
|
|
||||||
session.typeContext,
|
|
||||||
useCorrectedNullabilityForFlexibleTypeParameters = true
|
|
||||||
) ?: lowerBound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lowerBound
|
|
||||||
}
|
|
||||||
return ConeFlexibleType(lowerBound, upperBound)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val KOTLIN_COLLECTIONS = FqName("kotlin.collections")
|
private val KOTLIN_COLLECTIONS = FqName("kotlin.collections")
|
||||||
|
|
||||||
private val KOTLIN_COLLECTIONS_PREFIX_LENGTH = KOTLIN_COLLECTIONS.asString().length + 1
|
private val KOTLIN_COLLECTIONS_PREFIX_LENGTH = KOTLIN_COLLECTIONS.asString().length + 1
|
||||||
@@ -174,7 +141,12 @@ private fun ConeKotlinType.enhanceInflexibleType(
|
|||||||
// TODO: val nullabilityForWarning = enhancedNullabilityAttribute != null && effectiveQualifiers.isNullabilityQualifierForWarning
|
// TODO: val nullabilityForWarning = enhancedNullabilityAttribute != null && effectiveQualifiers.isNullabilityQualifierForWarning
|
||||||
val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] }
|
val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] }
|
||||||
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
|
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
|
||||||
return enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
|
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
|
||||||
|
return if (effectiveQualifiers.isNotNullTypeParameter)
|
||||||
|
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext, useCorrectedNullabilityForFlexibleTypeParameters = true)
|
||||||
|
?: enhancedType
|
||||||
|
else
|
||||||
|
enhancedType
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeClassifierLookupTag.enhanceMutability(
|
private fun ConeClassifierLookupTag.enhanceMutability(
|
||||||
|
|||||||
Reference in New Issue
Block a user