FIR/FE: extract common code for handling known nullability annotations
This commit is contained in:
+5
-7
@@ -184,8 +184,7 @@ internal class EnhancementSignatureParts(
|
|||||||
|
|
||||||
private fun FirTypeRef?.extractQualifiersFromAnnotations(
|
private fun FirTypeRef?.extractQualifiersFromAnnotations(
|
||||||
isHeadTypeConstructor: Boolean,
|
isHeadTypeConstructor: Boolean,
|
||||||
defaultQualifiersForType: JavaDefaultQualifiers?,
|
defaultQualifiersForType: JavaDefaultQualifiers?
|
||||||
javaTypeEnhancementState: JavaTypeEnhancementState
|
|
||||||
): JavaTypeQualifiers {
|
): JavaTypeQualifiers {
|
||||||
val composedAnnotation =
|
val composedAnnotation =
|
||||||
if (isHeadTypeConstructor && typeContainer != null)
|
if (isHeadTypeConstructor && typeContainer != null)
|
||||||
@@ -207,7 +206,7 @@ internal class EnhancementSignatureParts(
|
|||||||
else
|
else
|
||||||
defaultQualifiersForType
|
defaultQualifiersForType
|
||||||
|
|
||||||
val nullabilityInfo = composedAnnotation.extractNullability(typeQualifierResolver, javaTypeEnhancementState).also {
|
val nullabilityInfo = composedAnnotation.extractNullability(typeQualifierResolver).also {
|
||||||
if (it?.qualifier == NullabilityQualifier.NOT_NULL) {
|
if (it?.qualifier == NullabilityQualifier.NOT_NULL) {
|
||||||
attributesCache[this] = composedAnnotation.computeTypeAttributesForJavaType()
|
attributesCache[this] = composedAnnotation.computeTypeAttributesForJavaType()
|
||||||
}
|
}
|
||||||
@@ -242,8 +241,7 @@ internal class EnhancementSignatureParts(
|
|||||||
session: FirSession,
|
session: FirSession,
|
||||||
fromSupertypes: Collection<FirTypeRef>,
|
fromSupertypes: Collection<FirTypeRef>,
|
||||||
defaultQualifiersForType: JavaDefaultQualifiers?,
|
defaultQualifiersForType: JavaDefaultQualifiers?,
|
||||||
isHeadTypeConstructor: Boolean,
|
isHeadTypeConstructor: Boolean
|
||||||
javaTypeEnhancementState: JavaTypeEnhancementState
|
|
||||||
): JavaTypeQualifiers {
|
): JavaTypeQualifiers {
|
||||||
val superQualifiers = fromSupertypes.map { it.extractQualifiers(session) }
|
val superQualifiers = fromSupertypes.map { it.extractQualifiers(session) }
|
||||||
val mutabilityFromSupertypes = superQualifiers.mapNotNull { it.mutability }.toSet()
|
val mutabilityFromSupertypes = superQualifiers.mapNotNull { it.mutability }.toSet()
|
||||||
@@ -252,7 +250,7 @@ internal class EnhancementSignatureParts(
|
|||||||
.mapNotNull { it.extractQualifiers(session).nullability }
|
.mapNotNull { it.extractQualifiers(session).nullability }
|
||||||
.toSet()
|
.toSet()
|
||||||
|
|
||||||
val own = extractQualifiersFromAnnotations(isHeadTypeConstructor, defaultQualifiersForType, javaTypeEnhancementState)
|
val own = extractQualifiersFromAnnotations(isHeadTypeConstructor, defaultQualifiersForType)
|
||||||
val ownNullability = own.takeIf { !it.isNullabilityQualifierForWarning }?.nullability
|
val ownNullability = own.takeIf { !it.isNullabilityQualifierForWarning }?.nullability
|
||||||
val ownNullabilityForWarning = own.nullability
|
val ownNullabilityForWarning = own.nullability
|
||||||
|
|
||||||
@@ -306,7 +304,7 @@ internal class EnhancementSignatureParts(
|
|||||||
val verticalSlice = indexedFromSupertypes.mapNotNull { it.getOrNull(index)?.type }
|
val verticalSlice = indexedFromSupertypes.mapNotNull { it.getOrNull(index)?.type }
|
||||||
|
|
||||||
// Only the head type constructor is safely co-variant
|
// Only the head type constructor is safely co-variant
|
||||||
type.computeQualifiersForOverride(session, verticalSlice, defaultQualifiers, isHeadTypeConstructor, javaTypeEnhancementState)
|
type.computeQualifiersForOverride(session, verticalSlice, defaultQualifiers, isHeadTypeConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return IndexedJavaTypeQualifiers(computedResult)
|
return IndexedJavaTypeQualifiers(computedResult)
|
||||||
|
|||||||
+3
-10
@@ -21,7 +21,6 @@ class FirJavaEnhancementContext private constructor(
|
|||||||
|
|
||||||
fun extractDefaultNullabilityQualifier(
|
fun extractDefaultNullabilityQualifier(
|
||||||
typeQualifierResolver: FirAnnotationTypeQualifierResolver,
|
typeQualifierResolver: FirAnnotationTypeQualifierResolver,
|
||||||
javaTypeEnhancementState: JavaTypeEnhancementState,
|
|
||||||
annotationCall: FirAnnotationCall
|
annotationCall: FirAnnotationCall
|
||||||
): JavaDefaultQualifiers? {
|
): JavaDefaultQualifiers? {
|
||||||
typeQualifierResolver.resolveQualifierBuiltInDefaultAnnotation(annotationCall)?.let { return it }
|
typeQualifierResolver.resolveQualifierBuiltInDefaultAnnotation(annotationCall)?.let { return it }
|
||||||
@@ -38,10 +37,8 @@ fun extractDefaultNullabilityQualifier(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val nullabilityQualifier = typeQualifier.extractNullability(
|
val nullabilityQualifier = typeQualifier.extractNullability(typeQualifierResolver)
|
||||||
typeQualifierResolver, javaTypeEnhancementState
|
?.copy(isForWarningOnly = jsr305ReportLevel.isWarning) ?: return null
|
||||||
)?.copy(isForWarningOnly = jsr305ReportLevel.isWarning) ?: return null
|
|
||||||
|
|
||||||
return JavaDefaultQualifiers(nullabilityQualifier, applicability)
|
return JavaDefaultQualifiers(nullabilityQualifier, applicability)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +51,7 @@ fun FirJavaEnhancementContext.computeNewDefaultTypeQualifiers(
|
|||||||
|
|
||||||
val defaultQualifiers =
|
val defaultQualifiers =
|
||||||
additionalAnnotations.mapNotNull { annotationCall ->
|
additionalAnnotations.mapNotNull { annotationCall ->
|
||||||
extractDefaultNullabilityQualifier(
|
extractDefaultNullabilityQualifier(typeQualifierResolver, annotationCall)
|
||||||
typeQualifierResolver,
|
|
||||||
javaTypeEnhancementState,
|
|
||||||
annotationCall
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultQualifiers.isEmpty()) return defaultTypeQualifiers
|
if (defaultQualifiers.isEmpty()) return defaultTypeQualifiers
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
|
import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
|
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
|
||||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||||
import org.jetbrains.kotlin.load.java.JavaDefaultQualifiers
|
import org.jetbrains.kotlin.load.java.*
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||||
import org.jetbrains.kotlin.load.java.typeEnhancement.*
|
import org.jetbrains.kotlin.load.java.typeEnhancement.*
|
||||||
@@ -355,3 +355,9 @@ internal fun List<FirAnnotationCall>.computeTypeAttributesForJavaType(): ConeAtt
|
|||||||
-> add(CompilerConeAttributes.EnhancedNullability)
|
-> add(CompilerConeAttributes.EnhancedNullability)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val NOT_NULL_ANNOTATION_IDS = NOT_NULL_ANNOTATIONS.map { ClassId.topLevel(it) }
|
||||||
|
private val JAVAX_NONNULL_ANNOTATION_ID = ClassId.topLevel(JAVAX_NONNULL_ANNOTATION)
|
||||||
|
private val JAVAX_CHECKFORNULL_ANNOTATION_ID = ClassId.topLevel(JAVAX_CHECKFORNULL_ANNOTATION)
|
||||||
|
private val COMPATQUAL_NONNULL_ANNOTATION_ID = ClassId.topLevel(COMPATQUAL_NONNULL_ANNOTATION)
|
||||||
|
private val ANDROIDX_RECENTLY_NON_NULL_ANNOTATION_ID = ClassId.topLevel(ANDROIDX_RECENTLY_NON_NULL_ANNOTATION)
|
||||||
|
|||||||
+5
-76
@@ -6,86 +6,15 @@
|
|||||||
package org.jetbrains.kotlin.fir.java.enhancement
|
package org.jetbrains.kotlin.fir.java.enhancement
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.classId
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
|
||||||
import org.jetbrains.kotlin.load.java.*
|
|
||||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier
|
|
||||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
|
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
|
|
||||||
fun List<FirAnnotationCall>.extractNullability(
|
fun List<FirAnnotationCall>.extractNullability(
|
||||||
annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver,
|
annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver
|
||||||
javaTypeEnhancementState: JavaTypeEnhancementState
|
|
||||||
): NullabilityQualifierWithMigrationStatus? =
|
): NullabilityQualifierWithMigrationStatus? =
|
||||||
this.firstNotNullOfOrNull { annotationCall ->
|
this.firstNotNullOfOrNull { it.extractNullability(annotationTypeQualifierResolver) }
|
||||||
annotationCall.extractNullability(annotationTypeQualifierResolver, javaTypeEnhancementState)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun FirAnnotationCall.extractNullability(
|
fun FirAnnotationCall.extractNullability(
|
||||||
annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver,
|
annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver
|
||||||
javaTypeEnhancementState: JavaTypeEnhancementState
|
): NullabilityQualifierWithMigrationStatus? =
|
||||||
): NullabilityQualifierWithMigrationStatus? {
|
annotationTypeQualifierResolver.extractNullability(this) { false }
|
||||||
this.extractNullabilityFromKnownAnnotations(javaTypeEnhancementState)?.let { return it }
|
|
||||||
|
|
||||||
val typeQualifierAnnotation =
|
|
||||||
annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(this)
|
|
||||||
?: return null
|
|
||||||
|
|
||||||
val jsr305ReportLevel = annotationTypeQualifierResolver.resolveJsr305AnnotationState(this)
|
|
||||||
if (jsr305ReportLevel.isIgnore) return null
|
|
||||||
|
|
||||||
return typeQualifierAnnotation.extractNullabilityFromKnownAnnotations(javaTypeEnhancementState)?.copy(isForWarningOnly = jsr305ReportLevel.isWarning)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirAnnotationCall.extractNullabilityFromKnownAnnotations(javaTypeEnhancementState: JavaTypeEnhancementState): NullabilityQualifierWithMigrationStatus? {
|
|
||||||
val annotationClassId = classId ?: return null
|
|
||||||
val reportLevel = javaTypeEnhancementState.getReportLevelForAnnotation(annotationClassId.asSingleFqName())
|
|
||||||
|
|
||||||
if (reportLevel == ReportLevel.IGNORE) return null
|
|
||||||
|
|
||||||
return when (annotationClassId) {
|
|
||||||
in NULLABLE_ANNOTATION_IDS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, reportLevel.isWarning)
|
|
||||||
in NOT_NULL_ANNOTATION_IDS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, reportLevel.isWarning)
|
|
||||||
JSPECIFY_NULLABLE_ANNOTATION_ID -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, reportLevel.isWarning)
|
|
||||||
JSPECIFY_NULLNESS_UNKNOWN_ANNOTATION_ID ->
|
|
||||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY, reportLevel.isWarning)
|
|
||||||
JAVAX_NONNULL_ANNOTATION_ID -> extractNullabilityTypeFromArgument()
|
|
||||||
COMPATQUAL_NULLABLE_ANNOTATION_ID -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, reportLevel.isWarning)
|
|
||||||
COMPATQUAL_NONNULL_ANNOTATION_ID -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, reportLevel.isWarning)
|
|
||||||
ANDROIDX_RECENTLY_NON_NULL_ANNOTATION_ID -> NullabilityQualifierWithMigrationStatus(
|
|
||||||
NullabilityQualifier.NOT_NULL,
|
|
||||||
isForWarningOnly = reportLevel.isWarning
|
|
||||||
)
|
|
||||||
ANDROIDX_RECENTLY_NULLABLE_ANNOTATION_ID -> NullabilityQualifierWithMigrationStatus(
|
|
||||||
NullabilityQualifier.NULLABLE,
|
|
||||||
isForWarningOnly = reportLevel.isWarning
|
|
||||||
)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirAnnotationCall.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? {
|
|
||||||
val enumValue = this.arguments.firstOrNull()?.toResolvedCallableSymbol()?.callableId?.callableName
|
|
||||||
// if no argument is specified, use default value: NOT_NULL
|
|
||||||
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
|
||||||
|
|
||||||
return when (enumValue.asString()) {
|
|
||||||
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
|
||||||
"MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
|
||||||
"UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val NULLABLE_ANNOTATION_IDS = NULLABLE_ANNOTATIONS.map { ClassId.topLevel(it) }
|
|
||||||
val NOT_NULL_ANNOTATION_IDS = NOT_NULL_ANNOTATIONS.map { ClassId.topLevel(it) }
|
|
||||||
val JAVAX_NONNULL_ANNOTATION_ID = ClassId.topLevel(JAVAX_NONNULL_ANNOTATION)
|
|
||||||
val JAVAX_CHECKFORNULL_ANNOTATION_ID = ClassId.topLevel(JAVAX_CHECKFORNULL_ANNOTATION)
|
|
||||||
private val COMPATQUAL_NULLABLE_ANNOTATION_ID = ClassId.topLevel(COMPATQUAL_NULLABLE_ANNOTATION)
|
|
||||||
val COMPATQUAL_NONNULL_ANNOTATION_ID = ClassId.topLevel(COMPATQUAL_NONNULL_ANNOTATION)
|
|
||||||
val ANDROIDX_RECENTLY_NON_NULL_ANNOTATION_ID = ClassId.topLevel(ANDROIDX_RECENTLY_NON_NULL_ANNOTATION)
|
|
||||||
private val ANDROIDX_RECENTLY_NULLABLE_ANNOTATION_ID = ClassId.topLevel(ANDROIDX_RECENTLY_NULLABLE_ANNOTATION)
|
|
||||||
private val JSPECIFY_NULLABLE_ANNOTATION_ID = ClassId.topLevel(JSPECIFY_NULLABLE)
|
|
||||||
private val JSPECIFY_NULLNESS_UNKNOWN_ANNOTATION_ID = ClassId.topLevel(JSPECIFY_NULLNESS_UNKNOWN)
|
|
||||||
|
|||||||
+38
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.load.java
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
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 org.jetbrains.kotlin.name.FqName
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
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)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
private companion object {
|
private companion object {
|
||||||
val JAVA_APPLICABILITY_TYPES = buildMap<String, AnnotationQualifierApplicabilityType> {
|
val JAVA_APPLICABILITY_TYPES = buildMap<String, AnnotationQualifierApplicabilityType> {
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier(
|
|||||||
|
|
||||||
val areImprovementsInStrictMode = components.settings.typeEnhancementImprovementsInStrictMode
|
val areImprovementsInStrictMode = components.settings.typeEnhancementImprovementsInStrictMode
|
||||||
|
|
||||||
|
// TODO: if `extractNullability` forces a warning for compatibility, this overrides that. Expected? Probably not.
|
||||||
val nullabilityQualifier =
|
val nullabilityQualifier =
|
||||||
components.signatureEnhancement.extractNullability(typeQualifier, areImprovementsInStrictMode, typeParameterBounds = false)
|
components.signatureEnhancement.extractNullability(typeQualifier, areImprovementsInStrictMode, typeParameterBounds = false)
|
||||||
?.copy(isForWarningOnly = jsr305State.isWarning) ?: return null
|
?.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.computeJvmDescriptor
|
||||||
import org.jetbrains.kotlin.load.kotlin.signature
|
import org.jetbrains.kotlin.load.kotlin.signature
|
||||||
import org.jetbrains.kotlin.name.FqName
|
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.deprecation.DEPRECATED_FUNCTION_KEY
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
@@ -47,90 +45,17 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
|
|
||||||
class SignatureEnhancement(
|
class SignatureEnhancement(
|
||||||
private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver,
|
private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver,
|
||||||
private val javaTypeEnhancementState: JavaTypeEnhancementState,
|
|
||||||
private val typeEnhancement: JavaTypeEnhancement
|
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(
|
fun extractNullability(
|
||||||
annotationDescriptor: AnnotationDescriptor,
|
annotationDescriptor: AnnotationDescriptor,
|
||||||
areImprovementsEnabled: Boolean,
|
areImprovementsEnabled: Boolean,
|
||||||
typeParameterBounds: Boolean
|
typeParameterBounds: Boolean
|
||||||
): NullabilityQualifierWithMigrationStatus? {
|
): NullabilityQualifierWithMigrationStatus? =
|
||||||
extractNullabilityFromKnownAnnotations(annotationDescriptor, areImprovementsEnabled, typeParameterBounds)?.let { return it }
|
annotationTypeQualifierResolver.extractNullability(annotationDescriptor) {
|
||||||
|
(this is LazyJavaAnnotationDescriptor && (isFreshlySupportedTypeUseAnnotation || typeParameterBounds) && !areImprovementsEnabled) ||
|
||||||
val typeQualifierAnnotation =
|
(this is PossiblyExternalAnnotationDescriptor && isIdeExternalAnnotation)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
||||||
return platformSignatures.map {
|
return platformSignatures.map {
|
||||||
|
|||||||
+1
-5
@@ -163,11 +163,7 @@ fun makeLazyJavaPackageFragmentProvider(
|
|||||||
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolverImpl(storageManager, emptyList()), javaSourceElementFactory,
|
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolverImpl(storageManager, emptyList()), javaSourceElementFactory,
|
||||||
singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
|
singleModuleClassResolver, packagePartProvider, SupertypeLoopChecker.EMPTY, LookupTracker.DO_NOTHING, module,
|
||||||
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
|
ReflectionTypes(module, notFoundClasses), annotationTypeQualifierResolver,
|
||||||
SignatureEnhancement(
|
SignatureEnhancement(annotationTypeQualifierResolver, JavaTypeEnhancement(JavaResolverSettings.Default)),
|
||||||
annotationTypeQualifierResolver,
|
|
||||||
JavaTypeEnhancementState.DEFAULT,
|
|
||||||
JavaTypeEnhancement(JavaResolverSettings.Default)
|
|
||||||
),
|
|
||||||
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default, javaTypeEnhancementState,
|
JavaClassesTracker.Default, JavaResolverSettings.Default, NewKotlinTypeChecker.Default, javaTypeEnhancementState,
|
||||||
object : JavaModuleAnnotationsProvider {
|
object : JavaModuleAnnotationsProvider {
|
||||||
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? = null
|
override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List<JavaAnnotation>? = null
|
||||||
|
|||||||
Reference in New Issue
Block a user