FE: slowly refactor extractQualifiersFromAnnotations 2
This commit is contained in:
+28
-40
@@ -277,16 +277,17 @@ private class SignatureParts(
|
||||
val annotationsNullability = annotationTypeQualifierResolver.extractNullability(composedAnnotation) {
|
||||
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsInStrictMode) ||
|
||||
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||
}.takeUnless { type == null }
|
||||
}
|
||||
|
||||
if (annotationsNullability != null) {
|
||||
if (type != null && annotationsNullability != null) {
|
||||
return JavaTypeQualifiers(
|
||||
annotationsNullability.qualifier, annotationsMutability,
|
||||
annotationsNullability.qualifier == NullabilityQualifier.NOT_NULL && typeOrBound.isTypeParameter(),
|
||||
annotationsNullability.qualifier == NullabilityQualifier.NOT_NULL && type.isTypeParameter(),
|
||||
annotationsNullability.isForWarningOnly
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: check whether the code below works properly for star projections (when typeOrBound != type)
|
||||
val defaultTypeQualifier = (
|
||||
if (isHeadTypeConstructor)
|
||||
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
||||
@@ -299,42 +300,43 @@ private class SignatureParts(
|
||||
)
|
||||
)?.takeIf { (it.affectsTypeParameterBasedTypes || !typeOrBound.isTypeParameter()) && (it.affectsStarProjection || type != null) }
|
||||
|
||||
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
||||
typeOrBound.nullabilityInfoBoundsForTypeParameterUsage()
|
||||
val nullabilityInfo = computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||
nullabilityFromBoundsForTypeBasedOnTypeParameter,
|
||||
defaultTypeQualifier,
|
||||
typeParameterForArgument
|
||||
)
|
||||
val referencedParameterBoundsNullability =
|
||||
(typeOrBound.constructor.declarationDescriptor as? TypeParameterDescriptor)?.boundsNullability()
|
||||
|
||||
// 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 =
|
||||
isTypeParameterWithNotNullableBounds || defaultTypeQualifier?.makesTypeParameterNotNull == true
|
||||
referencedParameterBoundsNullability?.qualifier == NullabilityQualifier.NOT_NULL ||
|
||||
(typeOrBound.isTypeParameter() && defaultTypeQualifier?.makesTypeParameterNotNull == true)
|
||||
|
||||
val nullabilityInfo = computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(defaultNullability, typeParameterForArgument)
|
||||
|
||||
return JavaTypeQualifiers(
|
||||
nullabilityInfo?.qualifier, annotationsMutability,
|
||||
isNotNullTypeParameter = isNotNullTypeParameter && typeOrBound.isTypeParameter(),
|
||||
isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true
|
||||
isNotNullTypeParameter,
|
||||
nullabilityInfo?.isForWarningOnly == true
|
||||
)
|
||||
}
|
||||
|
||||
private fun computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||
nullabilityFromBoundsForTypeBasedOnTypeParameter: NullabilityQualifierWithMigrationStatus?,
|
||||
defaultTypeQualifier: JavaDefaultQualifiers?,
|
||||
result: NullabilityQualifierWithMigrationStatus?,
|
||||
typeParameterForArgument: TypeParameterDescriptor?
|
||||
): NullabilityQualifierWithMigrationStatus? {
|
||||
|
||||
val result =
|
||||
nullabilityFromBoundsForTypeBasedOnTypeParameter
|
||||
?: defaultTypeQualifier?.nullabilityQualifier?.let { nullabilityQualifierWithMigrationStatus ->
|
||||
NullabilityQualifierWithMigrationStatus(
|
||||
nullabilityQualifierWithMigrationStatus.qualifier,
|
||||
nullabilityQualifierWithMigrationStatus.isForWarningOnly
|
||||
)
|
||||
}
|
||||
|
||||
val boundsFromTypeParameterForArgument = typeParameterForArgument?.boundsNullability() ?: return result
|
||||
|
||||
if (defaultTypeQualifier == null && result == null && boundsFromTypeParameterForArgument.qualifier == NullabilityQualifier.NULLABLE) {
|
||||
if (result == null && boundsFromTypeParameterForArgument.qualifier == NullabilityQualifier.NULLABLE) {
|
||||
return NullabilityQualifierWithMigrationStatus(
|
||||
NullabilityQualifier.FORCE_FLEXIBILITY,
|
||||
boundsFromTypeParameterForArgument.isForWarningOnly
|
||||
@@ -350,6 +352,7 @@ private class SignatureParts(
|
||||
a: NullabilityQualifierWithMigrationStatus,
|
||||
b: NullabilityQualifierWithMigrationStatus
|
||||
): NullabilityQualifierWithMigrationStatus {
|
||||
// TODO: this probably behaves really weirdly when some of those are warnings.
|
||||
if (a.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return b
|
||||
if (b.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return a
|
||||
if (a.qualifier == NullabilityQualifier.NULLABLE) return b
|
||||
@@ -361,21 +364,6 @@ private class SignatureParts(
|
||||
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? {
|
||||
// Do not use bounds from Kotlin-defined type parameters
|
||||
if (this !is LazyJavaTypeParameterDescriptor || upperBounds.all(KotlinType::isError)) return null
|
||||
|
||||
Reference in New Issue
Block a user