From 8d39d155bba076b246a703157199922d6722a4be Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 9 Aug 2021 17:41:08 +0200 Subject: [PATCH] FE/FIR: extract common code for mutability qualifiers --- .../enhancement/EnhancementSignatureParts.kt | 37 ++--------------- ...AbstractAnnotationTypeQualifierResolver.kt | 22 ++++++++-- .../kotlin/load/java/JvmAnnotationNames.kt | 4 +- .../typeEnhancement/signatureEnhancement.kt | 40 +++---------------- 4 files changed, 30 insertions(+), 73 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt index b05995bbdc1..898b4963a5e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt @@ -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 List.ifPresent(qualifier: T) = - if (any { classId -> - composedAnnotation.any { it.classId == classId } - } - ) qualifier else null - - fun 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) } - } } - diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/AbstractAnnotationTypeQualifierResolver.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/AbstractAnnotationTypeQualifierResolver.kt index 9f95e719366..d9db1526f4a 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/AbstractAnnotationTypeQualifierResolver.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/AbstractAnnotationTypeQualifierResolver.kt @@ -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( } } - 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( ?.copy(isForWarningOnly = jsr305State.isWarning) } + fun extractNullability( + annotations: Iterable, forceWarning: Annotation.() -> Boolean = { false } + ): NullabilityQualifierWithMigrationStatus? = + annotations.firstNotNullOfOrNull { extractNullability(it, forceWarning) } + + fun extractMutability(annotations: Iterable): 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( 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) } diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt index f5ed6617586..5ad11be7753 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt @@ -74,12 +74,12 @@ val NULLABILITY_ANNOTATIONS = mutableSetOf() + 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 ) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt index f4bacd0cfbd..c36f6072635 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt @@ -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 List.ifPresent(qualifier: T) = - if (any { composedAnnotation.findAnnotation(it) != null }) qualifier else null - - fun 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()