FIR2IR: add implicit NOT_NULL cast if needed

This commit is contained in:
Jinseong Jeon
2020-10-18 23:36:47 -07:00
committed by Mikhail Glukhikh
parent eeda48e63e
commit 46cc01602e
44 changed files with 181 additions and 88 deletions
@@ -61,10 +61,11 @@ internal val JavaClass.classKind: ClassKind
internal fun ClassId.toConeKotlinType(
typeArguments: Array<ConeTypeProjection>,
isNullable: Boolean
isNullable: Boolean,
attributes: ConeAttributes = ConeAttributes.Empty
): ConeLookupTagBasedType {
val lookupTag = ConeClassLikeLookupTagImpl(this)
return ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable)
return ConeClassLikeTypeImpl(lookupTag, typeArguments, isNullable, attributes)
}
internal fun FirTypeRef.toConeKotlinTypeProbablyFlexible(
@@ -110,11 +111,17 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack,
forAnnotationValueParameter: Boolean = false,
isForSupertypes: Boolean = false
isForSupertypes: Boolean = false,
attributes: ConeAttributes = ConeAttributes.Empty
): ConeKotlinType {
return when (this) {
is JavaClassifierType -> {
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter = forAnnotationValueParameter)
toConeKotlinTypeWithoutEnhancement(
session,
javaTypeParameterStack,
forAnnotationValueParameter = forAnnotationValueParameter,
attributes = attributes
)
}
is JavaPrimitiveType -> {
val primitiveType = type
@@ -124,14 +131,26 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
}
val classId = StandardClassIds.byName(kotlinPrimitiveName)
classId.toConeKotlinType(emptyArray(), isNullable = false)
classId.toConeKotlinType(emptyArray(), isNullable = false, attributes)
}
is JavaArrayType -> {
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter, isForSupertypes)
}
is JavaWildcardType -> bound?.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, isForSupertypes = isForSupertypes) ?: run {
StandardClassIds.Any.toConeFlexibleType(emptyArray())
toConeKotlinTypeWithoutEnhancement(
session,
javaTypeParameterStack,
forAnnotationValueParameter,
isForSupertypes,
attributes = attributes
)
}
is JavaWildcardType ->
bound?.toConeKotlinTypeWithoutEnhancement(
session,
javaTypeParameterStack,
isForSupertypes = isForSupertypes,
attributes = attributes
) ?: run {
StandardClassIds.Any.toConeFlexibleType(emptyArray())
}
null -> {
StandardClassIds.Any.toConeFlexibleType(emptyArray())
}
@@ -143,7 +162,8 @@ private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack,
forAnnotationValueParameter: Boolean = false,
isForSupertypes: Boolean
isForSupertypes: Boolean,
attributes: ConeAttributes = ConeAttributes.Empty
): ConeKotlinType {
val componentType = componentType
return if (componentType !is JavaPrimitiveType) {
@@ -152,11 +172,12 @@ private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
session, javaTypeParameterStack, forAnnotationValueParameter, isForSupertypes
)
if (forAnnotationValueParameter) {
classId.constructClassLikeType(arrayOf(argumentType), isNullable = false)
classId.constructClassLikeType(arrayOf(argumentType), isNullable = false, attributes = attributes)
} else {
classId.toConeFlexibleType(
arrayOf(argumentType),
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType))
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType)),
attributes = attributes
)
}
} else {
@@ -164,19 +185,20 @@ private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
val classId = StandardClassIds.byName(javaComponentName + "Array")
if (forAnnotationValueParameter) {
classId.constructClassLikeType(emptyArray(), isNullable = false)
classId.constructClassLikeType(emptyArray(), isNullable = false, attributes = attributes)
} else {
classId.toConeFlexibleType(emptyArray())
classId.toConeFlexibleType(emptyArray(), attributes = attributes)
}
}
}
private fun ClassId.toConeFlexibleType(
typeArguments: Array<ConeTypeProjection>,
typeArgumentsForUpper: Array<ConeTypeProjection> = typeArguments
typeArgumentsForUpper: Array<ConeTypeProjection> = typeArguments,
attributes: ConeAttributes = ConeAttributes.Empty
) = ConeFlexibleType(
toConeKotlinType(typeArguments, isNullable = false),
toConeKotlinType(typeArgumentsForUpper, isNullable = true)
toConeKotlinType(typeArguments, isNullable = false, attributes),
toConeKotlinType(typeArgumentsForUpper, isNullable = true, attributes)
)
private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
@@ -184,7 +206,8 @@ private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
javaTypeParameterStack: JavaTypeParameterStack,
forTypeParameterBounds: Boolean = false,
isForSupertypes: Boolean = false,
forAnnotationValueParameter: Boolean = false
forAnnotationValueParameter: Boolean = false,
attributes: ConeAttributes = ConeAttributes.Empty
): ConeKotlinType {
val lowerBound = toConeKotlinTypeForFlexibleBound(
session,
@@ -192,7 +215,8 @@ private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
isLowerBound = true,
forTypeParameterBounds,
isForSupertypes,
forAnnotationValueParameter = forAnnotationValueParameter
forAnnotationValueParameter = forAnnotationValueParameter,
attributes = attributes
)
if (forAnnotationValueParameter) {
return lowerBound
@@ -205,7 +229,8 @@ private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
forTypeParameterBounds,
isForSupertypes,
lowerBound,
forAnnotationValueParameter = forAnnotationValueParameter
forAnnotationValueParameter = forAnnotationValueParameter,
attributes = attributes
)
return if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
@@ -308,7 +333,8 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
forTypeParameterBounds: Boolean,
isForSupertypes: Boolean,
lowerBound: ConeLookupTagBasedType? = null,
forAnnotationValueParameter: Boolean = false
forAnnotationValueParameter: Boolean = false,
attributes: ConeAttributes = ConeAttributes.Empty
): ConeLookupTagBasedType {
return when (val classifier = classifier) {
is JavaClass -> {
@@ -357,7 +383,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
}
lookupTag.constructClassType(
mappedTypeArguments.toTypedArray(), isNullable = !isLowerBound
mappedTypeArguments.toTypedArray(), isNullable = !isLowerBound, attributes
)
}
is JavaTypeParameter -> {
@@ -42,6 +42,8 @@ internal class EnhancementSignatureParts(
) {
private val isForVarargParameter get() = typeContainer.safeAs<FirValueParameter>()?.isVararg == true
private val attributesCache = mutableMapOf<FirTypeRef?, ConeAttributes>().withDefault { ConeAttributes.Empty }
private fun ConeKotlinType.toFqNameUnsafe(): FqNameUnsafe? =
((this as? ConeLookupTagBasedType)?.lookupTag as? ConeClassLikeLookupTag)?.classId?.asSingleFqName()?.toUnsafe()
@@ -62,7 +64,8 @@ internal class EnhancementSignatureParts(
val typeWithoutEnhancement = current.type.toConeKotlinTypeWithoutEnhancement(
session,
javaTypeParameterStack,
forAnnotationValueParameter
forAnnotationValueParameter,
attributes = attributesCache.getValue(current)
)
val containsFunctionN = typeWithoutEnhancement.contains {
if (it is ConeClassErrorType) false
@@ -204,7 +207,11 @@ internal class EnhancementSignatureParts(
else
defaultQualifiersForType
val nullabilityInfo = composedAnnotation.extractNullability(typeQualifierResolver, javaTypeEnhancementState)
val nullabilityInfo = composedAnnotation.extractNullability(typeQualifierResolver, javaTypeEnhancementState).also {
if (it?.qualifier == NullabilityQualifier.NOT_NULL) {
attributesCache[this] = composedAnnotation.computeTypeAttributesForJavaType()
}
}
?: defaultTypeQualifier?.nullabilityQualifier?.let { nullability ->
NullabilityQualifierWithMigrationStatus(
nullability.qualifier,
@@ -13,14 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildQualifiedAccessExpression
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
@@ -327,3 +324,11 @@ internal fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaul
private val DEFAULT_VALUE_ID = ClassId.topLevel(DEFAULT_VALUE_FQ_NAME)
private val DEFAULT_NULL_ID = ClassId.topLevel(DEFAULT_NULL_FQ_NAME)
internal fun List<FirAnnotationCall>.computeTypeAttributesForJavaType(): ConeAttributes =
computeTypeAttributes { classId ->
when (classId) {
CompilerConeAttributes.EnhancedNullability.ANNOTATION_CLASS_ID -> add(CompilerConeAttributes.EnhancedNullability)
// TODO: Need to handle others too? E.g., COMPATQUAL_NONNULL_ANNOTATION_ID
in NOT_NULL_ANNOTATION_IDS -> add(CompilerConeAttributes.EnhancedNullability)
}
}
@@ -82,7 +82,7 @@ private fun FirAnnotationCall.extractNullabilityTypeFromArgument(): NullabilityQ
}
private val NULLABLE_ANNOTATION_IDS = NULLABLE_ANNOTATIONS.map { ClassId.topLevel(it) }
private val NOT_NULL_ANNOTATION_IDS = NOT_NULL_ANNOTATIONS.map { ClassId.topLevel(it) }
val NOT_NULL_ANNOTATION_IDS = NOT_NULL_ANNOTATIONS.map { ClassId.topLevel(it) }
private val JAVAX_NONNULL_ANNOTATION_ID = ClassId.topLevel(JAVAX_NONNULL_ANNOTATION)
private val COMPATQUAL_NULLABLE_ANNOTATION_ID = ClassId.topLevel(COMPATQUAL_NULLABLE_ANNOTATION)
private val COMPATQUAL_NONNULL_ANNOTATION_ID = ClassId.topLevel(COMPATQUAL_NONNULL_ANNOTATION)