FIR/FE: extract common code for handling known nullability annotations
This commit is contained in:
+38
@@ -7,6 +7,8 @@ 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.NullabilityQualifier
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@@ -102,6 +104,42 @@ abstract class AbstractAnnotationTypeQualifierResolver<Annotation : Any>(
|
||||
}
|
||||
}
|
||||
|
||||
fun extractNullability(annotation: Annotation, forceWarning: Annotation.() -> Boolean): NullabilityQualifierWithMigrationStatus? {
|
||||
knownNullability(annotation, annotation.forceWarning())?.let { return it }
|
||||
|
||||
val typeQualifierAnnotation = resolveTypeQualifierAnnotation(annotation) ?: return null
|
||||
val jsr305State = resolveJsr305AnnotationState(annotation)
|
||||
if (jsr305State.isIgnore) return null
|
||||
// TODO: the result of `forceWarning` will be overwritten - expected? Probably not.
|
||||
return knownNullability(typeQualifierAnnotation, typeQualifierAnnotation.forceWarning())
|
||||
?.copy(isForWarningOnly = jsr305State.isWarning)
|
||||
}
|
||||
|
||||
private fun knownNullability(annotation: Annotation, forceWarning: Boolean): NullabilityQualifierWithMigrationStatus? {
|
||||
val fqName = annotation.fqName ?: return null
|
||||
val reportLevel = javaTypeEnhancementState.getReportLevelForAnnotation(fqName)
|
||||
if (reportLevel.isIgnore) return null
|
||||
val nullability = when (fqName) {
|
||||
in NULLABLE_ANNOTATIONS -> NullabilityQualifier.NULLABLE
|
||||
in NOT_NULL_ANNOTATIONS -> NullabilityQualifier.NOT_NULL
|
||||
JSPECIFY_NULLABLE -> NullabilityQualifier.NULLABLE
|
||||
JSPECIFY_NULLNESS_UNKNOWN -> NullabilityQualifier.FORCE_FLEXIBILITY
|
||||
JAVAX_NONNULL_ANNOTATION ->
|
||||
when (annotation.enumArguments(onlyValue = false).firstOrNull()) {
|
||||
"ALWAYS", null -> NullabilityQualifier.NOT_NULL
|
||||
"MAYBE", "NEVER" -> NullabilityQualifier.NULLABLE
|
||||
"UNKNOWN" -> NullabilityQualifier.FORCE_FLEXIBILITY
|
||||
else -> return null
|
||||
}
|
||||
COMPATQUAL_NULLABLE_ANNOTATION -> NullabilityQualifier.NULLABLE
|
||||
COMPATQUAL_NONNULL_ANNOTATION -> NullabilityQualifier.NOT_NULL
|
||||
ANDROIDX_RECENTLY_NON_NULL_ANNOTATION -> NullabilityQualifier.NOT_NULL
|
||||
ANDROIDX_RECENTLY_NULLABLE_ANNOTATION -> NullabilityQualifier.NULLABLE
|
||||
else -> return null
|
||||
}
|
||||
return NullabilityQualifierWithMigrationStatus(nullability, reportLevel.isWarning || forceWarning)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private companion object {
|
||||
val JAVA_APPLICABILITY_TYPES = buildMap<String, AnnotationQualifierApplicabilityType> {
|
||||
|
||||
@@ -173,6 +173,7 @@ private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier(
|
||||
|
||||
val areImprovementsInStrictMode = components.settings.typeEnhancementImprovementsInStrictMode
|
||||
|
||||
// TODO: if `extractNullability` forces a warning for compatibility, this overrides that. Expected? Probably not.
|
||||
val nullabilityQualifier =
|
||||
components.signatureEnhancement.extractNullability(typeQualifier, areImprovementsInStrictMode, typeParameterBounds = false)
|
||||
?.copy(isForWarningOnly = jsr305State.isWarning) ?: return null
|
||||
|
||||
+4
-79
@@ -35,9 +35,7 @@ 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.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DEPRECATED_FUNCTION_KEY
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
@@ -47,90 +45,17 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class SignatureEnhancement(
|
||||
private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver,
|
||||
private val javaTypeEnhancementState: JavaTypeEnhancementState,
|
||||
private val typeEnhancement: JavaTypeEnhancement
|
||||
) {
|
||||
|
||||
private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(isForWarningOnly: Boolean): NullabilityQualifierWithMigrationStatus? {
|
||||
val enumValue = firstArgument() as? EnumValue
|
||||
// if no argument is specified, use default value: NOT_NULL
|
||||
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly)
|
||||
|
||||
return when (enumValue.enumEntryName.asString()) {
|
||||
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly)
|
||||
"MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarningOnly)
|
||||
"UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY, isForWarningOnly)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun extractNullability(
|
||||
annotationDescriptor: AnnotationDescriptor,
|
||||
areImprovementsEnabled: Boolean,
|
||||
typeParameterBounds: Boolean
|
||||
): NullabilityQualifierWithMigrationStatus? {
|
||||
extractNullabilityFromKnownAnnotations(annotationDescriptor, areImprovementsEnabled, typeParameterBounds)?.let { return it }
|
||||
|
||||
val typeQualifierAnnotation =
|
||||
annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||
?: return null
|
||||
|
||||
val jsr305State = annotationTypeQualifierResolver.resolveJsr305AnnotationState(annotationDescriptor)
|
||||
if (jsr305State.isIgnore) return null
|
||||
|
||||
return extractNullabilityFromKnownAnnotations(typeQualifierAnnotation, areImprovementsEnabled, typeParameterBounds)
|
||||
?.copy(isForWarningOnly = jsr305State.isWarning)
|
||||
}
|
||||
|
||||
private fun extractNullabilityFromKnownAnnotations(
|
||||
annotationDescriptor: AnnotationDescriptor,
|
||||
areImprovementsEnabled: Boolean,
|
||||
typeParameterBounds: Boolean
|
||||
): NullabilityQualifierWithMigrationStatus? {
|
||||
val annotationFqName = annotationDescriptor.fqName ?: return null
|
||||
val isForWarningOnly = annotationDescriptor is LazyJavaAnnotationDescriptor
|
||||
&& (annotationDescriptor.isFreshlySupportedTypeUseAnnotation || typeParameterBounds)
|
||||
&& !areImprovementsEnabled
|
||||
val migrationStatus = commonMigrationStatus(annotationFqName, annotationDescriptor, isForWarningOnly) ?: return null
|
||||
|
||||
return if (!migrationStatus.isForWarningOnly
|
||||
&& annotationDescriptor is PossiblyExternalAnnotationDescriptor
|
||||
&& annotationDescriptor.isIdeExternalAnnotation
|
||||
) {
|
||||
migrationStatus.copy(isForWarningOnly = true)
|
||||
} else migrationStatus
|
||||
}
|
||||
|
||||
private fun commonMigrationStatus(
|
||||
annotationFqName: FqName,
|
||||
annotationDescriptor: AnnotationDescriptor,
|
||||
isForWarningOnly: Boolean = false
|
||||
): NullabilityQualifierWithMigrationStatus? {
|
||||
val reportLevel = javaTypeEnhancementState.getReportLevelForAnnotation(annotationFqName)
|
||||
|
||||
if (reportLevel.isIgnore) return null
|
||||
|
||||
val isForWarning = reportLevel.isWarning || isForWarningOnly
|
||||
|
||||
return when (annotationFqName) {
|
||||
in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarning)
|
||||
in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarning)
|
||||
JSPECIFY_NULLABLE -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarning)
|
||||
JSPECIFY_NULLNESS_UNKNOWN -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY, isForWarning)
|
||||
JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument(isForWarning)
|
||||
COMPATQUAL_NULLABLE_ANNOTATION ->
|
||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarning)
|
||||
COMPATQUAL_NONNULL_ANNOTATION ->
|
||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarning)
|
||||
ANDROIDX_RECENTLY_NON_NULL_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
||||
NullabilityQualifier.NOT_NULL, isForWarning
|
||||
)
|
||||
ANDROIDX_RECENTLY_NULLABLE_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
||||
NullabilityQualifier.NULLABLE, isForWarning
|
||||
)
|
||||
else -> null
|
||||
): NullabilityQualifierWithMigrationStatus? =
|
||||
annotationTypeQualifierResolver.extractNullability(annotationDescriptor) {
|
||||
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsEnabled) ||
|
||||
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||
}
|
||||
}
|
||||
|
||||
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
||||
return platformSignatures.map {
|
||||
|
||||
+1
-5
@@ -163,11 +163,7 @@ fun makeLazyJavaPackageFragmentProvider(
|
||||
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolverImpl(storageManager, emptyList()), javaSourceElementFactory,
|
||||
singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
|
||||
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
|
||||
SignatureEnhancement(
|
||||
annotationTypeQualifierResolver,
|
||||
JavaTypeEnhancementState.DEFAULT,
|
||||
JavaTypeEnhancement(JavaResolverSettings.Default)
|
||||
),
|
||||
SignatureEnhancement(annotationTypeQualifierResolver, JavaTypeEnhancement(JavaResolverSettings.Default)),
|
||||
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default, javaTypeEnhancementState,
|
||||
object : JavaModuleAnnotationsProvider {
|
||||
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? = null
|
||||
|
||||
Reference in New Issue
Block a user