FE: slowly refactor extractQualifiersFromAnnotations 2
This commit is contained in:
+28
-40
@@ -277,16 +277,17 @@ private class SignatureParts(
|
|||||||
val annotationsNullability = annotationTypeQualifierResolver.extractNullability(composedAnnotation) {
|
val annotationsNullability = annotationTypeQualifierResolver.extractNullability(composedAnnotation) {
|
||||||
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsInStrictMode) ||
|
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsInStrictMode) ||
|
||||||
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||||
}.takeUnless { type == null }
|
}
|
||||||
|
|
||||||
if (annotationsNullability != null) {
|
if (type != null && annotationsNullability != null) {
|
||||||
return JavaTypeQualifiers(
|
return JavaTypeQualifiers(
|
||||||
annotationsNullability.qualifier, annotationsMutability,
|
annotationsNullability.qualifier, annotationsMutability,
|
||||||
annotationsNullability.qualifier == NullabilityQualifier.NOT_NULL && typeOrBound.isTypeParameter(),
|
annotationsNullability.qualifier == NullabilityQualifier.NOT_NULL && type.isTypeParameter(),
|
||||||
annotationsNullability.isForWarningOnly
|
annotationsNullability.isForWarningOnly
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: check whether the code below works properly for star projections (when typeOrBound != type)
|
||||||
val defaultTypeQualifier = (
|
val defaultTypeQualifier = (
|
||||||
if (isHeadTypeConstructor)
|
if (isHeadTypeConstructor)
|
||||||
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
||||||
@@ -299,42 +300,43 @@ private class SignatureParts(
|
|||||||
)
|
)
|
||||||
)?.takeIf { (it.affectsTypeParameterBasedTypes || !typeOrBound.isTypeParameter()) && (it.affectsStarProjection || type != null) }
|
)?.takeIf { (it.affectsTypeParameterBasedTypes || !typeOrBound.isTypeParameter()) && (it.affectsStarProjection || type != null) }
|
||||||
|
|
||||||
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
val referencedParameterBoundsNullability =
|
||||||
typeOrBound.nullabilityInfoBoundsForTypeParameterUsage()
|
(typeOrBound.constructor.declarationDescriptor as? TypeParameterDescriptor)?.boundsNullability()
|
||||||
val nullabilityInfo = computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
|
||||||
nullabilityFromBoundsForTypeBasedOnTypeParameter,
|
|
||||||
defaultTypeQualifier,
|
|
||||||
typeParameterForArgument
|
|
||||||
)
|
|
||||||
|
|
||||||
|
// For type parameter uses, we have *three* options:
|
||||||
|
// T!! - NOT_NULL, isNotNullTypeParameter = true
|
||||||
|
// happens if T is bounded by @NotNull (technically !! is redundant) or context says unannotated
|
||||||
|
// type parameters are non-null;
|
||||||
|
// T - NOT_NULL, isNotNullTypeParameter = false
|
||||||
|
// happens if T is bounded by @Nullable or context says unannotated types in general are non-null;
|
||||||
|
// T? - NULLABLE, isNotNullTypeParameter = false
|
||||||
|
// happens if context says unannotated types in general are nullable.
|
||||||
|
// For other types, this is more straightforward (just take nullability from the context).
|
||||||
|
// TODO: clean up the representation of those cases in JavaTypeQualifiers
|
||||||
|
val defaultNullability =
|
||||||
|
referencedParameterBoundsNullability?.copy(qualifier = NullabilityQualifier.NOT_NULL)
|
||||||
|
?: defaultTypeQualifier?.nullabilityQualifier
|
||||||
val isNotNullTypeParameter =
|
val isNotNullTypeParameter =
|
||||||
isTypeParameterWithNotNullableBounds || defaultTypeQualifier?.makesTypeParameterNotNull == true
|
referencedParameterBoundsNullability?.qualifier == NullabilityQualifier.NOT_NULL ||
|
||||||
|
(typeOrBound.isTypeParameter() && defaultTypeQualifier?.makesTypeParameterNotNull == true)
|
||||||
|
|
||||||
|
val nullabilityInfo = computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(defaultNullability, typeParameterForArgument)
|
||||||
|
|
||||||
return JavaTypeQualifiers(
|
return JavaTypeQualifiers(
|
||||||
nullabilityInfo?.qualifier, annotationsMutability,
|
nullabilityInfo?.qualifier, annotationsMutability,
|
||||||
isNotNullTypeParameter = isNotNullTypeParameter && typeOrBound.isTypeParameter(),
|
isNotNullTypeParameter,
|
||||||
isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true
|
nullabilityInfo?.isForWarningOnly == true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
private fun computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||||
nullabilityFromBoundsForTypeBasedOnTypeParameter: NullabilityQualifierWithMigrationStatus?,
|
result: NullabilityQualifierWithMigrationStatus?,
|
||||||
defaultTypeQualifier: JavaDefaultQualifiers?,
|
|
||||||
typeParameterForArgument: TypeParameterDescriptor?
|
typeParameterForArgument: TypeParameterDescriptor?
|
||||||
): NullabilityQualifierWithMigrationStatus? {
|
): NullabilityQualifierWithMigrationStatus? {
|
||||||
|
|
||||||
val result =
|
|
||||||
nullabilityFromBoundsForTypeBasedOnTypeParameter
|
|
||||||
?: defaultTypeQualifier?.nullabilityQualifier?.let { nullabilityQualifierWithMigrationStatus ->
|
|
||||||
NullabilityQualifierWithMigrationStatus(
|
|
||||||
nullabilityQualifierWithMigrationStatus.qualifier,
|
|
||||||
nullabilityQualifierWithMigrationStatus.isForWarningOnly
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val boundsFromTypeParameterForArgument = typeParameterForArgument?.boundsNullability() ?: return result
|
val boundsFromTypeParameterForArgument = typeParameterForArgument?.boundsNullability() ?: return result
|
||||||
|
|
||||||
if (defaultTypeQualifier == null && result == null && boundsFromTypeParameterForArgument.qualifier == NullabilityQualifier.NULLABLE) {
|
if (result == null && boundsFromTypeParameterForArgument.qualifier == NullabilityQualifier.NULLABLE) {
|
||||||
return NullabilityQualifierWithMigrationStatus(
|
return NullabilityQualifierWithMigrationStatus(
|
||||||
NullabilityQualifier.FORCE_FLEXIBILITY,
|
NullabilityQualifier.FORCE_FLEXIBILITY,
|
||||||
boundsFromTypeParameterForArgument.isForWarningOnly
|
boundsFromTypeParameterForArgument.isForWarningOnly
|
||||||
@@ -350,6 +352,7 @@ private class SignatureParts(
|
|||||||
a: NullabilityQualifierWithMigrationStatus,
|
a: NullabilityQualifierWithMigrationStatus,
|
||||||
b: NullabilityQualifierWithMigrationStatus
|
b: NullabilityQualifierWithMigrationStatus
|
||||||
): NullabilityQualifierWithMigrationStatus {
|
): NullabilityQualifierWithMigrationStatus {
|
||||||
|
// TODO: this probably behaves really weirdly when some of those are warnings.
|
||||||
if (a.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return b
|
if (a.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return b
|
||||||
if (b.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return a
|
if (b.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return a
|
||||||
if (a.qualifier == NullabilityQualifier.NULLABLE) return b
|
if (a.qualifier == NullabilityQualifier.NULLABLE) return b
|
||||||
@@ -361,21 +364,6 @@ private class SignatureParts(
|
|||||||
return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.nullabilityInfoBoundsForTypeParameterUsage(): Pair<NullabilityQualifierWithMigrationStatus?, Boolean> {
|
|
||||||
val typeParameterBoundsNullability =
|
|
||||||
(constructor.declarationDescriptor as? TypeParameterDescriptor)?.boundsNullability() ?: return Pair(null, false)
|
|
||||||
|
|
||||||
// If type parameter has a nullable (non-flexible) upper bound
|
|
||||||
// We shouldn't mark its type usages as nullable:
|
|
||||||
// interface A<T extends @Nullable Object> {
|
|
||||||
// void foo(T t); // should be loaded as "fun foo(t: T)" but not as "fun foo(t: T?)"
|
|
||||||
// }
|
|
||||||
return Pair(
|
|
||||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, typeParameterBoundsNullability.isForWarningOnly),
|
|
||||||
typeParameterBoundsNullability.qualifier == NullabilityQualifier.NOT_NULL
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun TypeParameterDescriptor.boundsNullability(): NullabilityQualifierWithMigrationStatus? {
|
private fun TypeParameterDescriptor.boundsNullability(): NullabilityQualifierWithMigrationStatus? {
|
||||||
// Do not use bounds from Kotlin-defined type parameters
|
// Do not use bounds from Kotlin-defined type parameters
|
||||||
if (this !is LazyJavaTypeParameterDescriptor || upperBounds.all(KotlinType::isError)) return null
|
if (this !is LazyJavaTypeParameterDescriptor || upperBounds.all(KotlinType::isError)) return null
|
||||||
|
|||||||
Reference in New Issue
Block a user