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 2c57296b422..c07c48d280d 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 @@ -27,7 +27,6 @@ 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.load.java.JavaTypeEnhancementState import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal class EnhancementSignatureParts( @@ -49,11 +48,10 @@ internal class EnhancementSignatureParts( internal fun enhance( session: FirSession, - javaTypeEnhancementState: JavaTypeEnhancementState, predefined: TypeEnhancementInfo? = null, forAnnotationMember: Boolean = false ): PartEnhancementResult { - val qualifiers = computeIndexedQualifiersForOverride(session, javaTypeEnhancementState) + val qualifiers = computeIndexedQualifiersForOverride(session) val qualifiersWithPredefined = predefined?.let { IndexedJavaTypeQualifiers(qualifiers.size) { index -> @@ -95,13 +93,12 @@ internal class EnhancementSignatureParts( private fun FirTypeRef.toIndexed( typeQualifierResolver: FirAnnotationTypeQualifierResolver, - javaTypeEnhancementState: JavaTypeEnhancementState, context: FirJavaEnhancementContext ): List { val list = ArrayList(1) fun add(type: FirTypeRef?) { - val c = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, javaTypeEnhancementState, type?.annotations.orEmpty()) + val c = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, type?.annotations.orEmpty()) list.add( TypeAndDefaultQualifiers( @@ -206,7 +203,7 @@ internal class EnhancementSignatureParts( else defaultQualifiersForType - val nullabilityInfo = composedAnnotation.extractNullability(typeQualifierResolver).also { + val nullabilityInfo = composedAnnotation.firstNotNullOfOrNull { typeQualifierResolver.extractNullability(it) }.also { if (it?.qualifier == NullabilityQualifier.NOT_NULL) { attributesCache[this] = composedAnnotation.computeTypeAttributesForJavaType() } @@ -284,9 +281,9 @@ internal class EnhancementSignatureParts( ) } - private fun computeIndexedQualifiersForOverride(session: FirSession, javaTypeEnhancementState: JavaTypeEnhancementState): IndexedJavaTypeQualifiers { - val indexedFromSupertypes = fromOverridden.map { it.toIndexed(typeQualifierResolver, javaTypeEnhancementState, context) } - val indexedThisType = current.toIndexed(typeQualifierResolver, javaTypeEnhancementState, context) + private fun computeIndexedQualifiersForOverride(session: FirSession): IndexedJavaTypeQualifiers { + val indexedFromSupertypes = fromOverridden.map { it.toIndexed(typeQualifierResolver, context) } + val indexedThisType = current.toIndexed(typeQualifierResolver, context) // The covariant case may be hard, e.g. in the superclass the return may be Super, but in the subclass it may be Derived, which // is declared to extend Super, and propagating data here is highly non-trivial, so we only look at the head type constructor diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/FirJavaEnhancementContext.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/FirJavaEnhancementContext.kt index b8c00db9834..fc813c7d23e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/FirJavaEnhancementContext.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/FirJavaEnhancementContext.kt @@ -19,66 +19,13 @@ class FirJavaEnhancementContext private constructor( val defaultTypeQualifiers: JavaTypeQualifiersByElementType? by delegateForDefaultTypeQualifiers } -fun extractDefaultNullabilityQualifier( - typeQualifierResolver: FirAnnotationTypeQualifierResolver, - annotationCall: FirAnnotationCall -): JavaDefaultQualifiers? { - typeQualifierResolver.resolveQualifierBuiltInDefaultAnnotation(annotationCall)?.let { return it } - - val (typeQualifier, applicability) = - typeQualifierResolver.resolveTypeQualifierDefaultAnnotation(annotationCall) - ?: return null - - val jsr305ReportLevel = with(typeQualifierResolver) { - resolveJsr305CustomState(annotationCall) ?: resolveJsr305AnnotationState(typeQualifier) - } - - if (jsr305ReportLevel.isIgnore) { - return null - } - - val nullabilityQualifier = typeQualifier.extractNullability(typeQualifierResolver) - ?.copy(isForWarningOnly = jsr305ReportLevel.isWarning) ?: return null - return JavaDefaultQualifiers(nullabilityQualifier, applicability) -} - -fun FirJavaEnhancementContext.computeNewDefaultTypeQualifiers( - typeQualifierResolver: FirAnnotationTypeQualifierResolver, - javaTypeEnhancementState: JavaTypeEnhancementState, - additionalAnnotations: List -): JavaTypeQualifiersByElementType? { - if (javaTypeEnhancementState.jsr305.isDisabled) return defaultTypeQualifiers - - val defaultQualifiers = - additionalAnnotations.mapNotNull { annotationCall -> - extractDefaultNullabilityQualifier(typeQualifierResolver, annotationCall) - } - - if (defaultQualifiers.isEmpty()) return defaultTypeQualifiers - - val defaultQualifiersByType = - defaultTypeQualifiers?.defaultQualifiers?.let(::QualifierByApplicabilityType) - ?: QualifierByApplicabilityType(AnnotationQualifierApplicabilityType::class.java) - - var wasUpdate = false - for (qualifier in defaultQualifiers) { - for (applicabilityType in qualifier.qualifierApplicabilityTypes) { - defaultQualifiersByType[applicabilityType] = qualifier - wasUpdate = true - } - } - - return if (!wasUpdate) defaultTypeQualifiers else JavaTypeQualifiersByElementType(defaultQualifiersByType) -} - fun FirJavaEnhancementContext.copyWithNewDefaultTypeQualifiers( typeQualifierResolver: FirAnnotationTypeQualifierResolver, - javaTypeEnhancementState: JavaTypeEnhancementState, additionalAnnotations: List ): FirJavaEnhancementContext = when { additionalAnnotations.isEmpty() -> this else -> FirJavaEnhancementContext(session) { - computeNewDefaultTypeQualifiers(typeQualifierResolver, javaTypeEnhancementState, additionalAnnotations) + typeQualifierResolver.extractAndMergeDefaultQualifiers(defaultTypeQualifiers, additionalAnnotations) } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index 33f47570b66..d6ea6b0406e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -57,7 +57,7 @@ class FirSignatureEnhancement( private val typeQualifierResolver = FirAnnotationTypeQualifierResolver(session, jsr305State) private val context: FirJavaEnhancementContext = - FirJavaEnhancementContext(session) { null }.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, owner.annotations) + FirJavaEnhancementContext(session) { null }.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, owner.annotations) private val enhancements = mutableMapOf, FirCallableSymbol<*>>() @@ -85,7 +85,7 @@ class FirSignatureEnhancement( when (val firElement = original.fir) { is FirEnumEntry -> { if (firElement.returnTypeRef !is FirJavaTypeRef) return original - val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firElement.annotations) + val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, firElement.annotations) val predefinedInfo = PredefinedFunctionEnhancementInfo( TypeEnhancementInfo(0 to JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, false)), @@ -100,7 +100,7 @@ class FirSignatureEnhancement( } is FirField -> { if (firElement.returnTypeRef !is FirJavaTypeRef) return original - val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firElement.annotations) + val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, firElement.annotations) val newReturnTypeRef = enhanceReturnType(firElement, emptyList(), memberContext, null) val symbol = FirFieldSymbol(original.callableId) @@ -176,7 +176,7 @@ class FirSignatureEnhancement( methodId: CallableId, name: Name? ): FirFunctionSymbol<*> { - val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations) + val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, firMethod.annotations) val predefinedEnhancementInfo = SignatureBuildingComponents.signature( @@ -316,7 +316,7 @@ class FirSignatureEnhancement( parameterContainer = ownerFunction, methodContext = memberContext, typeInSignature = TypeInSignature.Receiver - ).enhance(session, jsr305State) + ).enhance(session) return signatureParts.type } @@ -340,7 +340,6 @@ class FirSignatureEnhancement( typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index) ).enhance( session, - jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index), forAnnotationMember = owner.classKind == ClassKind.ANNOTATION_CLASS ) @@ -363,8 +362,7 @@ class FirSignatureEnhancement( else AnnotationQualifierApplicabilityType.METHOD_RETURN_TYPE, typeInSignature = TypeInSignature.Return ).enhance( - session, jsr305State, predefinedEnhancementInfo?.returnTypeInfo, - forAnnotationMember = this.owner.classKind == ClassKind.ANNOTATION_CLASS + session, predefinedEnhancementInfo?.returnTypeInfo, forAnnotationMember = this.owner.classKind == ClassKind.ANNOTATION_CLASS ) return signatureParts.type } @@ -405,7 +403,7 @@ class FirSignatureEnhancement( overriddenMembers, parameterContainer, false, parameterContainer?.let { - methodContext.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, it.annotations) + methodContext.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, it.annotations) } ?: methodContext, AnnotationQualifierApplicabilityType.VALUE_PARAMETER, typeInSignature @@ -432,7 +430,7 @@ class FirSignatureEnhancement( isCovariant, // recompute default type qualifiers using type annotations containerContext.copyWithNewDefaultTypeQualifiers( - typeQualifierResolver, jsr305State, typeRef.annotations + typeQualifierResolver, typeRef.annotations ), containerApplicabilityType ) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/nullabilityUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/nullabilityUtils.kt deleted file mode 100644 index 9790eff05d0..00000000000 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/nullabilityUtils.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.fir.java.enhancement - -import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall -import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus - -fun List.extractNullability( - annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver -): NullabilityQualifierWithMigrationStatus? = - this.firstNotNullOfOrNull { it.extractNullability(annotationTypeQualifierResolver) } - - -fun FirAnnotationCall.extractNullability( - annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver -): NullabilityQualifierWithMigrationStatus? = - annotationTypeQualifierResolver.extractNullability(this) { false } 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 7721993c736..9f95e719366 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 @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMi import org.jetbrains.kotlin.name.FqName import java.util.concurrent.ConcurrentHashMap -typealias TypeQualifierWithApplicability = Pair> +private typealias TypeQualifierWithApplicability = Pair> abstract class AbstractAnnotationTypeQualifierResolver( private val javaTypeEnhancementState: JavaTypeEnhancementState @@ -43,7 +43,7 @@ abstract class AbstractAnnotationTypeQualifierResolver( } } - fun resolveQualifierBuiltInDefaultAnnotation(annotation: Annotation): JavaDefaultQualifiers? { + private fun resolveQualifierBuiltInDefaultAnnotation(annotation: Annotation): JavaDefaultQualifiers? { if (javaTypeEnhancementState.disabledDefaultAnnotations) { return null } @@ -72,7 +72,7 @@ abstract class AbstractAnnotationTypeQualifierResolver( else this - fun resolveTypeQualifierDefaultAnnotation(annotation: Annotation): TypeQualifierWithApplicability? { + private fun resolveTypeQualifierDefaultAnnotation(annotation: Annotation): TypeQualifierWithApplicability? { if (javaTypeEnhancementState.jsr305.isDisabled) return null val typeQualifierDefault = annotation.findAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME) ?: return null val typeQualifier = annotation.annotations.firstOrNull { resolveTypeQualifierAnnotation(it) != null } ?: return null @@ -87,12 +87,12 @@ abstract class AbstractAnnotationTypeQualifierResolver( return target.enumArguments(onlyValue = false).any { it == KotlinTarget.TYPE.name } } - fun resolveJsr305AnnotationState(annotation: Annotation): ReportLevel { + private fun resolveJsr305AnnotationState(annotation: Annotation): ReportLevel { resolveJsr305CustomState(annotation)?.let { return it } return javaTypeEnhancementState.jsr305.globalLevel } - fun resolveJsr305CustomState(annotation: Annotation): ReportLevel? { + private fun resolveJsr305CustomState(annotation: Annotation): ReportLevel? { javaTypeEnhancementState.jsr305.userDefinedLevelForSpecificAnnotation[annotation.fqName]?.let { return it } val enumValue = annotation.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.enumArguments(onlyValue = false)?.firstOrNull() ?: return null @@ -104,7 +104,9 @@ abstract class AbstractAnnotationTypeQualifierResolver( } } - fun extractNullability(annotation: Annotation, forceWarning: Annotation.() -> Boolean): NullabilityQualifierWithMigrationStatus? { + fun extractNullability( + annotation: Annotation, forceWarning: Annotation.() -> Boolean = { false } + ): NullabilityQualifierWithMigrationStatus? { knownNullability(annotation, annotation.forceWarning())?.let { return it } val typeQualifierAnnotation = resolveTypeQualifierAnnotation(annotation) ?: return null @@ -115,6 +117,42 @@ abstract class AbstractAnnotationTypeQualifierResolver( ?.copy(isForWarningOnly = jsr305State.isWarning) } + private fun extractDefaultQualifiers(annotation: Annotation): JavaDefaultQualifiers? { + resolveQualifierBuiltInDefaultAnnotation(annotation)?.let { return it } + + val (typeQualifier, applicability) = resolveTypeQualifierDefaultAnnotation(annotation) + ?: return null + val jsr305State = resolveJsr305CustomState(annotation) ?: resolveJsr305AnnotationState(typeQualifier) + 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 + return JavaDefaultQualifiers(nullabilityQualifier.copy(isForWarningOnly = jsr305State.isWarning), applicability) + } + + fun extractAndMergeDefaultQualifiers( + oldQualifiers: JavaTypeQualifiersByElementType?, annotations: Iterable + ): JavaTypeQualifiersByElementType? { + if (javaTypeEnhancementState.disabledDefaultAnnotations) return oldQualifiers + + val defaultQualifiers = annotations.mapNotNull { extractDefaultQualifiers(it) } + if (defaultQualifiers.isEmpty()) return oldQualifiers + + val defaultQualifiersByType = + oldQualifiers?.defaultQualifiers?.let(::QualifierByApplicabilityType) + ?: QualifierByApplicabilityType(AnnotationQualifierApplicabilityType::class.java) + + var wasUpdate = false + for (qualifier in defaultQualifiers) { + for (applicabilityType in qualifier.qualifierApplicabilityTypes) { + defaultQualifiersByType[applicabilityType] = qualifier + wasUpdate = true + } + } + + return if (!wasUpdate) oldQualifiers else JavaTypeQualifiersByElementType(defaultQualifiersByType) + } + private fun knownNullability(annotation: Annotation, forceWarning: Boolean): NullabilityQualifierWithMigrationStatus? { val fqName = annotation.fqName ?: return null val reportLevel = javaTypeEnhancementState.getReportLevelForAnnotation(fqName) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt index e5d534af7c9..f90dfd61f7c 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.java.* @@ -29,7 +28,6 @@ import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluato import org.jetbrains.kotlin.load.java.components.JavaResolverCache import org.jetbrains.kotlin.load.java.components.SignaturePropagator import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver -import org.jetbrains.kotlin.load.java.lazy.types.TypeParameterUpperBoundEraser import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement @@ -131,55 +129,8 @@ fun LazyJavaResolverContext.child( fun LazyJavaResolverContext.computeNewDefaultTypeQualifiers( additionalAnnotations: Annotations -): JavaTypeQualifiersByElementType? { - if (components.javaTypeEnhancementState.disabledDefaultAnnotations) return defaultTypeQualifiers - - val defaultQualifiers = - additionalAnnotations.mapNotNull(this::extractDefaultNullabilityQualifier) - - if (defaultQualifiers.isEmpty()) return defaultTypeQualifiers - - val defaultQualifiersByType = - defaultTypeQualifiers?.defaultQualifiers?.let(::QualifierByApplicabilityType) - ?: QualifierByApplicabilityType(AnnotationQualifierApplicabilityType::class.java) - - var wasUpdate = false - for (qualifier in defaultQualifiers) { - for (applicabilityType in qualifier.qualifierApplicabilityTypes) { - defaultQualifiersByType[applicabilityType] = qualifier - wasUpdate = true - } - } - - return if (!wasUpdate) defaultTypeQualifiers else JavaTypeQualifiersByElementType(defaultQualifiersByType) -} - -private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier( - annotationDescriptor: AnnotationDescriptor -): JavaDefaultQualifiers? { - val typeQualifierResolver = components.annotationTypeQualifierResolver - typeQualifierResolver.resolveQualifierBuiltInDefaultAnnotation(annotationDescriptor)?.let { return it } - - val (typeQualifier, applicability) = - typeQualifierResolver.resolveTypeQualifierDefaultAnnotation(annotationDescriptor) - ?: return null - - val jsr305State = typeQualifierResolver.resolveJsr305CustomState(annotationDescriptor) - ?: typeQualifierResolver.resolveJsr305AnnotationState(typeQualifier) - - if (jsr305State.isIgnore) { - return null - } - - 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 - - return JavaDefaultQualifiers(nullabilityQualifier, applicability) -} +): JavaTypeQualifiersByElementType? = + components.annotationTypeQualifierResolver.extractAndMergeDefaultQualifiers(defaultTypeQualifiers, additionalAnnotations) fun LazyJavaResolverContext.replaceComponents( components: JavaResolverComponents