FE/FIR: extract common code for mutability qualifiers
This commit is contained in:
+3
-34
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.classId
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeWithoutEnhancement
|
||||
import org.jetbrains.kotlin.fir.java.toFirJavaTypeRef
|
||||
@@ -19,13 +18,10 @@ import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
|
||||
import org.jetbrains.kotlin.load.java.JavaDefaultQualifiers
|
||||
import org.jetbrains.kotlin.load.java.MUTABLE_ANNOTATIONS
|
||||
import org.jetbrains.kotlin.load.java.READ_ONLY_ANNOTATIONS
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaWildcardType
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
@@ -189,43 +185,22 @@ internal class EnhancementSignatureParts(
|
||||
else
|
||||
this?.annotations.orEmpty()
|
||||
|
||||
fun <T : Any> List<ClassId>.ifPresent(qualifier: T) =
|
||||
if (any { classId ->
|
||||
composedAnnotation.any { it.classId == classId }
|
||||
}
|
||||
) qualifier else null
|
||||
|
||||
fun <T : Any> uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
|
||||
|
||||
val defaultTypeQualifier =
|
||||
if (isHeadTypeConstructor)
|
||||
context.defaultTypeQualifiers?.get(containerApplicabilityType)
|
||||
else
|
||||
defaultQualifiersForType
|
||||
|
||||
val nullabilityInfo = composedAnnotation.firstNotNullOfOrNull { typeQualifierResolver.extractNullability(it) }.also {
|
||||
val nullabilityInfo = typeQualifierResolver.extractNullability(composedAnnotation).also {
|
||||
if (it?.qualifier == NullabilityQualifier.NOT_NULL) {
|
||||
attributesCache[this] = composedAnnotation.computeTypeAttributesForJavaType()
|
||||
}
|
||||
}
|
||||
?: defaultTypeQualifier?.nullabilityQualifier?.let { nullability ->
|
||||
NullabilityQualifierWithMigrationStatus(
|
||||
nullability.qualifier,
|
||||
nullability.isForWarningOnly
|
||||
)
|
||||
}
|
||||
} ?: defaultTypeQualifier?.nullabilityQualifier
|
||||
|
||||
@Suppress("SimplifyBooleanWithConstants")
|
||||
return JavaTypeQualifiers(
|
||||
nullabilityInfo?.qualifier,
|
||||
uniqueNotNull(
|
||||
READ_ONLY_ANNOTATION_IDS.ifPresent(
|
||||
MutabilityQualifier.READ_ONLY
|
||||
),
|
||||
MUTABLE_ANNOTATION_IDS.ifPresent(
|
||||
MutabilityQualifier.MUTABLE
|
||||
)
|
||||
),
|
||||
typeQualifierResolver.extractMutability(composedAnnotation),
|
||||
isNotNullTypeParameter = nullabilityInfo?.qualifier == NullabilityQualifier.NOT_NULL && this.isTypeParameterBasedType(),
|
||||
isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true
|
||||
)
|
||||
@@ -262,10 +237,4 @@ internal class EnhancementSignatureParts(
|
||||
val wereChanges: Boolean,
|
||||
val containsFunctionN: Boolean
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val READ_ONLY_ANNOTATION_IDS = READ_ONLY_ANNOTATIONS.map { ClassId.topLevel(it) }
|
||||
private val MUTABLE_ANNOTATION_IDS = MUTABLE_ANNOTATIONS.map { ClassId.topLevel(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.load.java
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.MutabilityQualifier
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -104,8 +105,8 @@ abstract class AbstractAnnotationTypeQualifierResolver<Annotation : Any>(
|
||||
}
|
||||
}
|
||||
|
||||
fun extractNullability(
|
||||
annotation: Annotation, forceWarning: Annotation.() -> Boolean = { false }
|
||||
private fun extractNullability(
|
||||
annotation: Annotation, forceWarning: Annotation.() -> Boolean
|
||||
): NullabilityQualifierWithMigrationStatus? {
|
||||
knownNullability(annotation, annotation.forceWarning())?.let { return it }
|
||||
|
||||
@@ -117,6 +118,21 @@ abstract class AbstractAnnotationTypeQualifierResolver<Annotation : Any>(
|
||||
?.copy(isForWarningOnly = jsr305State.isWarning)
|
||||
}
|
||||
|
||||
fun extractNullability(
|
||||
annotations: Iterable<Annotation>, forceWarning: Annotation.() -> Boolean = { false }
|
||||
): NullabilityQualifierWithMigrationStatus? =
|
||||
annotations.firstNotNullOfOrNull { extractNullability(it, forceWarning) }
|
||||
|
||||
fun extractMutability(annotations: Iterable<Annotation>): MutabilityQualifier? {
|
||||
return annotations.fold(null as MutabilityQualifier?) { found, annotation ->
|
||||
when (annotation.fqName) {
|
||||
in READ_ONLY_ANNOTATIONS -> MutabilityQualifier.READ_ONLY
|
||||
in MUTABLE_ANNOTATIONS -> MutabilityQualifier.MUTABLE
|
||||
else -> found
|
||||
}.also { if (found != null && found != it) return null /* inconsistent */ }
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractDefaultQualifiers(annotation: Annotation): JavaDefaultQualifiers? {
|
||||
resolveQualifierBuiltInDefaultAnnotation(annotation)?.let { return it }
|
||||
|
||||
@@ -126,7 +142,7 @@ abstract class AbstractAnnotationTypeQualifierResolver<Annotation : Any>(
|
||||
if (jsr305State.isIgnore) return null
|
||||
// TODO: since we override the warning status, whether we force it in `extractNullability` is irrelevant.
|
||||
// However, this is probably not what was intended.
|
||||
val nullabilityQualifier = extractNullability(typeQualifier) ?: return null
|
||||
val nullabilityQualifier = extractNullability(typeQualifier) { false } ?: return null
|
||||
return JavaDefaultQualifiers(nullabilityQualifier.copy(isForWarningOnly = jsr305State.isWarning), applicability)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,12 +74,12 @@ val NULLABILITY_ANNOTATIONS = mutableSetOf<FqName>() +
|
||||
JSPECIFY_NULLNESS_UNKNOWN +
|
||||
JSPECIFY_NULL_MARKED
|
||||
|
||||
val READ_ONLY_ANNOTATIONS = listOf(
|
||||
val READ_ONLY_ANNOTATIONS = setOf(
|
||||
JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION,
|
||||
JvmAnnotationNames.READONLY_ANNOTATION
|
||||
)
|
||||
|
||||
val MUTABLE_ANNOTATIONS = listOf(
|
||||
val MUTABLE_ANNOTATIONS = setOf(
|
||||
JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION,
|
||||
JvmAnnotationNames.MUTABLE_ANNOTATION
|
||||
)
|
||||
|
||||
+6
-34
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
@@ -33,7 +32,6 @@ import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
|
||||
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.signature
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DEPRECATED_FUNCTION_KEY
|
||||
@@ -258,7 +256,7 @@ private class SignatureParts(
|
||||
val isHeadTypeConstructor = typeParameterForArgument == null
|
||||
val typeOrBound = type ?: typeParameterForArgument!!.starProjectionType()
|
||||
val composedAnnotation =
|
||||
if (isHeadTypeConstructor && typeContainer != null && typeContainer !is TypeParameterDescriptor && areImprovementsInStrictMode) {
|
||||
if (isHeadTypeConstructor && typeContainer != null && !typeParameterBounds && areImprovementsInStrictMode) {
|
||||
val filteredContainerAnnotations = typeContainer.annotations.filter {
|
||||
/*
|
||||
* We don't apply container type use annotations to avoid double applying them like with arrays:
|
||||
@@ -275,11 +273,6 @@ private class SignatureParts(
|
||||
composeAnnotations(typeContainer.annotations, typeOrBound.annotations)
|
||||
} else typeOrBound.annotations
|
||||
|
||||
fun <T : Any> List<FqName>.ifPresent(qualifier: T) =
|
||||
if (any { composedAnnotation.findAnnotation(it) != null }) qualifier else null
|
||||
|
||||
fun <T : Any> uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
|
||||
|
||||
val defaultTypeQualifier = (
|
||||
if (isHeadTypeConstructor)
|
||||
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
||||
@@ -295,8 +288,10 @@ private class SignatureParts(
|
||||
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
||||
typeOrBound.nullabilityInfoBoundsForTypeParameterUsage()
|
||||
|
||||
val annotationsNullability = composedAnnotation.extractNullability(areImprovementsInStrictMode, typeParameterBounds)
|
||||
?.takeUnless { type == null }
|
||||
val annotationsNullability = annotationTypeQualifierResolver.extractNullability(composedAnnotation) {
|
||||
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsInStrictMode) ||
|
||||
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||
}.takeUnless { type == null }
|
||||
val nullabilityInfo =
|
||||
annotationsNullability
|
||||
?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||
@@ -312,15 +307,7 @@ private class SignatureParts(
|
||||
isTypeParameterWithNotNullableBounds || defaultTypeQualifier?.makesTypeParameterNotNull == true
|
||||
|
||||
return JavaTypeQualifiers(
|
||||
nullabilityInfo?.qualifier,
|
||||
uniqueNotNull(
|
||||
READ_ONLY_ANNOTATIONS.ifPresent(
|
||||
MutabilityQualifier.READ_ONLY
|
||||
),
|
||||
MUTABLE_ANNOTATIONS.ifPresent(
|
||||
MutabilityQualifier.MUTABLE
|
||||
)
|
||||
),
|
||||
nullabilityInfo?.qualifier, annotationTypeQualifierResolver.extractMutability(composedAnnotation),
|
||||
isNotNullTypeParameter = isNotNullTypeParameter && typeOrBound.isTypeParameter(),
|
||||
isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true
|
||||
)
|
||||
@@ -407,21 +394,6 @@ private class SignatureParts(
|
||||
return NullabilityQualifierWithMigrationStatus(resultingQualifier)
|
||||
}
|
||||
|
||||
private fun Annotations.extractNullability(
|
||||
areImprovementsEnabled: Boolean,
|
||||
typeParameterBounds: Boolean
|
||||
): NullabilityQualifierWithMigrationStatus? =
|
||||
firstNotNullOfOrNull { it.extractNullability(areImprovementsEnabled, typeParameterBounds) }
|
||||
|
||||
private fun AnnotationDescriptor.extractNullability(
|
||||
areImprovementsEnabled: Boolean,
|
||||
typeParameterBounds: Boolean
|
||||
): NullabilityQualifierWithMigrationStatus? =
|
||||
containerContext.components.annotationTypeQualifierResolver.extractNullability(this) {
|
||||
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsEnabled) ||
|
||||
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||
}
|
||||
|
||||
private fun computeIndexedQualifiersForOverride(predefined: TypeEnhancementInfo?): (Int) -> JavaTypeQualifiers {
|
||||
val indexedFromSupertypes = fromOverridden.map { it.toIndexed() }
|
||||
val indexedThisType = fromOverride.toIndexed()
|
||||
|
||||
Reference in New Issue
Block a user