FE/FIR: extract common code for mutability qualifiers

This commit is contained in:
pyos
2021-08-09 17:41:08 +02:00
committed by teamcityserver
parent c753e547c6
commit 8d39d155bb
4 changed files with 30 additions and 73 deletions
@@ -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) }
}
}
@@ -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
)
@@ -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()