[FIR] Java super-type arguments are now handled as flexible
This commit is contained in:
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
@@ -95,7 +96,7 @@ class JavaSymbolProvider(
|
||||
) {
|
||||
require(this is FirTypeParameterImpl)
|
||||
for (upperBound in javaTypeParameter.upperBounds) {
|
||||
bounds += upperBound.toFirResolvedTypeRef(this@JavaSymbolProvider.session, stack, isNullable = true)
|
||||
bounds += upperBound.toFirResolvedTypeRef(this@JavaSymbolProvider.session, stack, nullability = ConeNullability.NULLABLE)
|
||||
}
|
||||
addDefaultBoundIfNecessary()
|
||||
}
|
||||
@@ -155,7 +156,9 @@ class JavaSymbolProvider(
|
||||
this.typeParameters += foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
||||
addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack)
|
||||
for (supertype in javaClass.supertypes) {
|
||||
superTypeRefs += supertype.toFirResolvedTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack)
|
||||
superTypeRefs += supertype.toFirResolvedTypeRef(
|
||||
this@JavaSymbolProvider.session, javaTypeParameterStack, typeParametersNullability = ConeNullability.UNKNOWN
|
||||
)
|
||||
}
|
||||
// TODO: may be we can process fields & methods later.
|
||||
// However, they should be built up to override resolve stage
|
||||
|
||||
@@ -78,8 +78,8 @@ internal fun FirTypeRef.toNotNullConeKotlinType(
|
||||
|
||||
internal fun JavaType?.toNotNullConeKotlinType(
|
||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
|
||||
): ConeLookupTagBasedType {
|
||||
return toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = false)
|
||||
): ConeKotlinType {
|
||||
return toConeKotlinTypeWithNullability(session, javaTypeParameterStack, ConeNullability.NOT_NULL)
|
||||
}
|
||||
|
||||
internal fun JavaType.toFirJavaTypeRef(session: FirSession, javaTypeParameterStack: JavaTypeParameterStack): FirJavaTypeRef {
|
||||
@@ -91,9 +91,12 @@ internal fun JavaType.toFirJavaTypeRef(session: FirSession, javaTypeParameterSta
|
||||
}
|
||||
|
||||
internal fun JavaClassifierType.toFirResolvedTypeRef(
|
||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, isNullable: Boolean = false
|
||||
session: FirSession,
|
||||
javaTypeParameterStack: JavaTypeParameterStack,
|
||||
nullability: ConeNullability = ConeNullability.NOT_NULL,
|
||||
typeParametersNullability: ConeNullability = ConeNullability.NOT_NULL
|
||||
): FirResolvedTypeRef {
|
||||
val coneType = this.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable)
|
||||
val coneType = this.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, nullability, typeParametersNullability)
|
||||
return FirResolvedTypeRefImpl(
|
||||
source = null, type = coneType
|
||||
).apply {
|
||||
@@ -102,11 +105,14 @@ internal fun JavaClassifierType.toFirResolvedTypeRef(
|
||||
}
|
||||
|
||||
internal fun JavaType?.toConeKotlinTypeWithNullability(
|
||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, isNullable: Boolean
|
||||
): ConeLookupTagBasedType {
|
||||
session: FirSession,
|
||||
javaTypeParameterStack: JavaTypeParameterStack,
|
||||
nullability: ConeNullability,
|
||||
typeParametersNullability: ConeNullability = ConeNullability.NOT_NULL
|
||||
): ConeKotlinType {
|
||||
return when (this) {
|
||||
is JavaClassifierType -> {
|
||||
toConeKotlinTypeWithNullability(session, isNullable, javaTypeParameterStack)
|
||||
toConeKotlinTypeWithNullability(session, nullability, typeParametersNullability, javaTypeParameterStack)
|
||||
}
|
||||
is JavaPrimitiveType -> {
|
||||
val primitiveType = type
|
||||
@@ -115,38 +121,47 @@ internal fun JavaType?.toConeKotlinTypeWithNullability(
|
||||
else -> javaName.capitalize()
|
||||
}
|
||||
val classId = StandardClassIds.byName(kotlinPrimitiveName)
|
||||
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||
classId.toConeKotlinType(emptyArray(), nullability.isNullable)
|
||||
}
|
||||
is JavaArrayType -> {
|
||||
val componentType = componentType
|
||||
if (componentType !is JavaPrimitiveType) {
|
||||
val classId = StandardClassIds.Array
|
||||
val argumentType = ConeFlexibleType(
|
||||
componentType.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = false),
|
||||
componentType.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = true)
|
||||
componentType.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, ConeNullability.NOT_NULL),
|
||||
componentType.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, ConeNullability.NULLABLE)
|
||||
)
|
||||
classId.toConeKotlinType(arrayOf(argumentType), isNullable)
|
||||
classId.toConeKotlinType(arrayOf(argumentType), nullability.isNullable)
|
||||
} else {
|
||||
val javaComponentName = componentType.type?.typeName?.asString()?.capitalize() ?: error("Array of voids")
|
||||
val classId = StandardClassIds.byName(javaComponentName + "Array")
|
||||
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||
classId.toConeKotlinType(emptyArray(), nullability.isNullable)
|
||||
}
|
||||
}
|
||||
is JavaWildcardType -> bound?.toNotNullConeKotlinType(session, javaTypeParameterStack) ?: run {
|
||||
val classId = StandardClassIds.Any
|
||||
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||
classId.toConeKotlinType(emptyArray(), nullability.isNullable)
|
||||
}
|
||||
null -> {
|
||||
val classId = StandardClassIds.Any
|
||||
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||
classId.toConeKotlinType(emptyArray(), nullability.isNullable)
|
||||
}
|
||||
else -> error("Strange JavaType: ${this::class.java}")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun JavaClassifierType.toConeKotlinTypeWithNullability(
|
||||
session: FirSession, isNullable: Boolean, javaTypeParameterStack: JavaTypeParameterStack
|
||||
): ConeLookupTagBasedType {
|
||||
session: FirSession,
|
||||
nullability: ConeNullability,
|
||||
typeParametersNullability: ConeNullability,
|
||||
javaTypeParameterStack: JavaTypeParameterStack
|
||||
): ConeKotlinType {
|
||||
if (nullability == ConeNullability.UNKNOWN) {
|
||||
return ConeFlexibleType(
|
||||
toConeKotlinTypeWithNullability(session, ConeNullability.NOT_NULL, typeParametersNullability, javaTypeParameterStack),
|
||||
toConeKotlinTypeWithNullability(session, ConeNullability.NULLABLE, typeParametersNullability, javaTypeParameterStack)
|
||||
)
|
||||
}
|
||||
return when (val classifier = classifier) {
|
||||
is JavaClass -> {
|
||||
//val classId = classifier.classId!!
|
||||
@@ -155,17 +170,16 @@ internal fun JavaClassifierType.toConeKotlinTypeWithNullability(
|
||||
|
||||
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
lookupTag.constructClassType(
|
||||
typeArguments.mapIndexed { index, argument ->
|
||||
typeArguments.map { argument ->
|
||||
argument.toConeProjection(
|
||||
session, javaTypeParameterStack, null
|
||||
//symbol.fir.typeParameters.getOrNull(index)
|
||||
session, javaTypeParameterStack, boundTypeParameter = null, nullability = typeParametersNullability
|
||||
)
|
||||
}.toTypedArray(), isNullable
|
||||
}.toTypedArray(), nullability.isNullable
|
||||
)
|
||||
}
|
||||
is JavaTypeParameter -> {
|
||||
val symbol = javaTypeParameterStack[classifier]
|
||||
ConeTypeParameterTypeImpl(symbol.toLookupTag(), isNullable)
|
||||
ConeTypeParameterTypeImpl(symbol.toLookupTag(), nullability.isNullable)
|
||||
}
|
||||
else -> ConeClassErrorType(reason = "Unexpected classifier: $classifier")
|
||||
}
|
||||
@@ -208,7 +222,10 @@ internal fun JavaValueParameter.toFirValueParameter(
|
||||
}
|
||||
|
||||
internal fun JavaType?.toConeProjection(
|
||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, boundTypeParameter: FirTypeParameter?
|
||||
session: FirSession,
|
||||
javaTypeParameterStack: JavaTypeParameterStack,
|
||||
boundTypeParameter: FirTypeParameter?,
|
||||
nullability: ConeNullability = ConeNullability.NOT_NULL
|
||||
): ConeKotlinTypeProjection {
|
||||
return when (this) {
|
||||
null -> ConeStarProjection
|
||||
@@ -219,7 +236,7 @@ internal fun JavaType?.toConeProjection(
|
||||
if (bound == null || parameterVariance != INVARIANT && parameterVariance != argumentVariance) {
|
||||
ConeStarProjection
|
||||
} else {
|
||||
val boundType = bound.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = false)
|
||||
val boundType = bound.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, nullability)
|
||||
if (argumentVariance == OUT_VARIANCE) {
|
||||
ConeKotlinTypeProjectionOut(boundType)
|
||||
} else {
|
||||
@@ -227,7 +244,7 @@ internal fun JavaType?.toConeProjection(
|
||||
}
|
||||
}
|
||||
}
|
||||
is JavaClassifierType -> toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = false)
|
||||
is JavaClassifierType -> toConeKotlinTypeWithNullability(session, javaTypeParameterStack, nullability)
|
||||
else -> ConeClassErrorType("Unexpected type argument: $this")
|
||||
}
|
||||
}
|
||||
@@ -260,7 +277,9 @@ private fun JavaAnnotationArgument.toFirExpression(
|
||||
null
|
||||
}
|
||||
this.calleeReference = calleeReference
|
||||
?: FirErrorNamedReferenceImpl(null, FirSimpleDiagnostic("Strange Java enum value: $classId.$entryName", DiagnosticKind.Java))
|
||||
?: FirErrorNamedReferenceImpl(
|
||||
null, FirSimpleDiagnostic("Strange Java enum value: $classId.$entryName", DiagnosticKind.Java)
|
||||
)
|
||||
}
|
||||
}
|
||||
is JavaClassObjectAnnotationArgument -> FirGetClassCallImpl(null).apply {
|
||||
@@ -270,7 +289,9 @@ private fun JavaAnnotationArgument.toFirExpression(
|
||||
)
|
||||
}
|
||||
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall(session, javaTypeParameterStack)
|
||||
else -> FirErrorExpressionImpl(null, FirSimpleDiagnostic("Unknown JavaAnnotationArgument: ${this::class.java}", DiagnosticKind.Java))
|
||||
else -> FirErrorExpressionImpl(
|
||||
null, FirSimpleDiagnostic("Unknown JavaAnnotationArgument: ${this::class.java}", DiagnosticKind.Java)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +325,9 @@ internal fun Any?.createConstant(session: FirSession): FirExpression {
|
||||
is BooleanArray -> toList().createArrayOfCall(session, FirConstKind.Boolean)
|
||||
null -> FirConstExpressionImpl(null, FirConstKind.Null, null)
|
||||
|
||||
else -> FirErrorExpressionImpl(null, FirSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java))
|
||||
else -> FirErrorExpressionImpl(
|
||||
null, FirSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -152,8 +152,8 @@ internal class EnhancementSignatureParts(
|
||||
is FirJavaTypeRef -> {
|
||||
Pair(
|
||||
// TODO: optimize
|
||||
type.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = false),
|
||||
type.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, isNullable = true)
|
||||
type.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, nullability = ConeNullability.NOT_NULL),
|
||||
type.toConeKotlinTypeWithNullability(session, javaTypeParameterStack, nullability = ConeNullability.NULLABLE)
|
||||
)
|
||||
}
|
||||
else -> return JavaTypeQualifiers.NONE
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.java.toConeProjection
|
||||
import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
@@ -124,12 +123,12 @@ private fun JavaType?.subtreeSize(): Int {
|
||||
|
||||
private fun coneFlexibleOrSimpleType(
|
||||
session: FirSession,
|
||||
lowerBound: ConeLookupTagBasedType,
|
||||
upperBound: ConeLookupTagBasedType,
|
||||
lowerBound: ConeKotlinType,
|
||||
upperBound: ConeKotlinType,
|
||||
isNotNullTypeParameter: Boolean
|
||||
): ConeKotlinType {
|
||||
if (AbstractStrictEqualityTypeChecker.strictEqualTypes(session.typeContext, lowerBound, upperBound)) {
|
||||
val lookupTag = lowerBound.lookupTag
|
||||
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
|
||||
@@ -164,8 +163,6 @@ private fun ClassId.mutableToReadOnly(): ClassId? {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Definition:
|
||||
// ErasedUpperBound(T : G<t>) = G<*> // UpperBound(T) is a type G<t> with arguments
|
||||
// ErasedUpperBound(T : A) = A // UpperBound(T) is a type A without arguments
|
||||
@@ -181,8 +178,7 @@ private fun FirTypeParameter.getErasedUpperBound(
|
||||
|
||||
val firstUpperBound = this.bounds.first().coneTypeUnsafe<ConeKotlinType>()
|
||||
|
||||
val firstUpperBoundClassifier = firstUpperBound
|
||||
if (firstUpperBoundClassifier is ConeClassLikeType) {
|
||||
if (firstUpperBound is ConeClassLikeType) {
|
||||
return firstUpperBound.withArguments(firstUpperBound.typeArguments.map { ConeStarProjection }.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -225,7 +221,8 @@ fun computeProjection(
|
||||
// in T -> Comparable<Nothing>
|
||||
session.builtinTypes.nothingType.type
|
||||
else if (erasedUpperBound is ConeClassLikeType &&
|
||||
erasedUpperBound.lookupTag.toSymbol(session)!!.firUnsafe<FirRegularClass>().typeParameters.isNotEmpty())
|
||||
erasedUpperBound.lookupTag.toSymbol(session)!!.firUnsafe<FirRegularClass>().typeParameters.isNotEmpty()
|
||||
)
|
||||
// T : Enum<E> -> out Enum<*>
|
||||
ConeKotlinTypeProjectionOut(erasedUpperBound)
|
||||
else
|
||||
@@ -234,8 +231,6 @@ fun computeProjection(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun JavaClassifierType.enhanceInflexibleType(
|
||||
session: FirSession,
|
||||
javaTypeParameterStack: JavaTypeParameterStack,
|
||||
@@ -244,9 +239,8 @@ private fun JavaClassifierType.enhanceInflexibleType(
|
||||
position: TypeComponentPosition,
|
||||
qualifiers: IndexedJavaTypeQualifiers,
|
||||
index: Int
|
||||
): ConeLookupTagBasedType {
|
||||
val classifier = classifier
|
||||
val originalTag = when (classifier) {
|
||||
): ConeKotlinType {
|
||||
val originalTag = when (val classifier = classifier) {
|
||||
is JavaClass -> {
|
||||
val classId = classifier.classId!!
|
||||
var mappedId = JavaToKotlinClassMap.mapJavaToKotlin(classId.asSingleFqName())
|
||||
|
||||
Reference in New Issue
Block a user