[FIR] Remove jvm-specific annotations from common compiler code

^KT-54596 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-10 15:44:52 +03:00
committed by Space Team
parent f7a2da8f82
commit 986f1624ec
48 changed files with 405 additions and 268 deletions
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getExplicitAnnotationRetention
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.getExplicitAnnotationRetention
object FirJsRuntimeAnnotationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -15,13 +15,13 @@ import org.jetbrains.kotlin.fir.isNewPlaceForBodyGeneration
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.JvmNames
fun <D> FirBasedSymbol<out D>.isCompiledToJvmDefault(
session: FirSession,
jvmDefaultMode: JvmDefaultMode,
): Boolean where D : FirAnnotationContainer, D : FirDeclaration {
if (getAnnotationByClassId(StandardClassIds.Annotations.JvmDefault, session) != null) return true
if (getAnnotationByClassId(JvmNames.Annotations.JvmDefault, session) != null) return true
val container = getContainingClassSymbol(session)
if (container !is FirRegularClassSymbol || container.origin.fromSource) return jvmDefaultMode.forAllMethodsWithBody
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2023 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.analysis.jvm.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.getAnnotationRetention
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.AnnotationsPosition
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.declarations.FirAnnotationsPlatformSpecificSupportComponent
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
object FirJvmAnnotationsPlatformSpecificSupportComponent : FirAnnotationsPlatformSpecificSupportComponent() {
override val requiredAnnotationsWithArguments: Set<ClassId> = setOf(
StandardClassIds.Annotations.Deprecated,
StandardClassIds.Annotations.Target,
JvmNames.Annotations.Java.Target,
)
override val requiredAnnotations: Set<ClassId> = requiredAnnotationsWithArguments + setOf(
JvmNames.Annotations.Java.Deprecated,
StandardClassIds.Annotations.DeprecatedSinceKotlin,
StandardClassIds.Annotations.SinceKotlin,
StandardClassIds.Annotations.WasExperimental,
JvmNames.Annotations.JvmRecord,
)
override val volatileAnnotations: Set<ClassId> = setOf(
StandardClassIds.Annotations.Volatile,
JvmNames.Annotations.JvmVolatile,
)
override val deprecationAnnotationsWithOverridesPropagation: Map<ClassId, Boolean> = mapOf(
StandardClassIds.Annotations.Deprecated to true,
JvmNames.Annotations.Java.Deprecated to false,
StandardClassIds.Annotations.SinceKotlin to true,
)
override fun symbolContainsRepeatableAnnotation(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
if (symbol.getAnnotationByClassId(StandardClassIds.Annotations.Repeatable, session) != null) return true
if (symbol.getAnnotationByClassId(JvmNames.Annotations.Java.Repeatable, session) != null ||
symbol.getAnnotationByClassId(JvmNames.Annotations.JvmRepeatable, session) != null
) {
return session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) ||
symbol.getAnnotationRetention(session) == AnnotationRetention.SOURCE && symbol.origin is FirDeclarationOrigin.Java
}
return false
}
override fun extractBackingFieldAnnotationsFromProperty(
property: FirProperty,
session: FirSession,
propertyAnnotations: List<FirAnnotation>,
backingFieldAnnotations: List<FirAnnotation>,
): AnnotationsPosition? {
if (propertyAnnotations.isEmpty() || property.backingField == null) return null
val (newBackingFieldAnnotations, newPropertyAnnotations) = propertyAnnotations.partition {
it.toAnnotationClassIdSafe(session) == JvmNames.Annotations.Java.Deprecated
}
if (newBackingFieldAnnotations.isEmpty()) return null
return AnnotationsPosition(
propertyAnnotations = newPropertyAnnotations,
backingFieldAnnotations = backingFieldAnnotations + newBackingFieldAnnotations,
)
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2023 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.analysis.jvm.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.FirPrimaryConstructorSuperTypeCheckerPlatformComponent
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
object FirJvmPrimaryConstructorSuperTypeCheckerPlatformComponent : FirPrimaryConstructorSuperTypeCheckerPlatformComponent() {
override val supertypesThatDontNeedInitializationInSubtypesConstructors: Set<ClassId> =
setOf(StandardClassIds.Enum, JvmNames.Java.Record)
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.resolve.getContainingClass
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
@@ -58,7 +59,7 @@ object FirJvmNameChecker : FirBasicDeclarationChecker() {
private fun FirDeclaration.findJvmNameAnnotation(): FirAnnotation? {
return annotations.firstOrNull {
it.annotationTypeRef.coneType.classId == StandardClassIds.Annotations.JvmName
it.annotationTypeRef.coneType.classId == JvmNames.Annotations.JvmName
}
}
@@ -24,14 +24,14 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.JvmNames.JVM_RECORD_ANNOTATION_CLASS_ID
import org.jetbrains.kotlin.name.StandardClassIds
object FirJvmRecordChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
declaration.superTypeRefs.firstOrNull()?.let { typeRef ->
// compiler automatically adds java.lang.Record supertype, so we should check only for explicit type declarations
if (typeRef.source != null && typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedClassId(context.session) == StandardClassIds.Java.Record) {
if (typeRef.source != null && typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedClassId(context.session) == JvmNames.Java.Record) {
reporter.reportOn(typeRef.source, FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, context)
return
}
@@ -13,15 +13,15 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Repeatable
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.JvmRepeatable
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Java
import org.jetbrains.kotlin.name.JvmNames.Annotations.JvmRepeatable
object FirJvmRedundantRepeatableChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
val kotlinRepeatable = declaration.getAnnotationByClassId(Repeatable, context.session)
val javaRepeatable = declaration.getAnnotationByClassId(JvmRepeatable, context.session)
?: declaration.getAnnotationByClassId(Java.Repeatable, context.session)
?: declaration.getAnnotationByClassId(JvmNames.Annotations.Java.Repeatable, context.session)
if (kotlinRepeatable != null && javaRepeatable != null) {
reporter.reportOn(
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
@@ -42,14 +43,14 @@ object FirJvmStaticChecker : FirBasicDeclarationChecker() {
return
}
val declarationAnnotation = declaration.findAnnotation(StandardClassIds.Annotations.JvmStatic, context.session)
val declarationAnnotation = declaration.findAnnotation(JvmNames.Annotations.JvmStatic, context.session)
if (declarationAnnotation != null) {
checkAnnotated(declaration, context, reporter, declaration.source)
}
fun checkIfAnnotated(it: FirDeclaration) {
if (!it.hasAnnotation(StandardClassIds.Annotations.JvmStatic, context.session)) {
if (!it.hasAnnotation(JvmNames.Annotations.JvmStatic, context.session)) {
return
}
val targetSource = it.source ?: declaration.source
@@ -201,7 +202,7 @@ object FirJvmStaticChecker : FirBasicDeclarationChecker() {
targetSource: KtSourceElement?,
) {
if (declaration !is FirProperty) return
if (declaration.isConst || declaration.backingField?.hasAnnotationNamedAs(StandardClassIds.Annotations.JvmField, context.session) == true) {
if (declaration.isConst || declaration.backingField?.hasAnnotationNamedAs(JvmNames.Annotations.JvmField, context.session) == true) {
reporter.reportOn(targetSource, FirJvmErrors.JVM_STATIC_ON_CONST_OR_JVM_FIELD, context)
}
}
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.containsRepeatableAnnotation
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationRetention
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.declarations.getAnnotationRetention
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
@@ -33,6 +32,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
@@ -58,7 +58,7 @@ object FirRepeatableAnnotationChecker : FirBasicDeclarationChecker() {
existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }
if (duplicateAnnotation &&
annotationClass.containsRepeatableAnnotation(session) &&
session.annotationPlatformSupport.symbolContainsRepeatableAnnotation(annotationClass, session) &&
annotationClass.getAnnotationRetention(session) != AnnotationRetention.SOURCE
) {
if (session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations)) {
@@ -83,7 +83,7 @@ object FirRepeatableAnnotationChecker : FirBasicDeclarationChecker() {
}
if (declaration is FirRegularClass) {
val javaRepeatable = annotations.getAnnotationByClassId(StandardClassIds.Annotations.Java.Repeatable, session)
val javaRepeatable = annotations.getAnnotationByClassId(JvmNames.Annotations.Java.Repeatable, session)
if (javaRepeatable != null) {
checkJavaRepeatableAnnotationDeclaration(javaRepeatable, declaration, context, reporter)
} else {
@@ -97,7 +97,7 @@ object FirRepeatableAnnotationChecker : FirBasicDeclarationChecker() {
private fun FirClassLikeSymbol<*>.resolveContainerAnnotation(session: FirSession): ClassId? {
val repeatableAnnotation = getAnnotationByClassId(StandardClassIds.Annotations.Repeatable, session)
?: getAnnotationByClassId(StandardClassIds.Annotations.Java.Repeatable, session)
?: getAnnotationByClassId(JvmNames.Annotations.Java.Repeatable, session)
?: return null
return repeatableAnnotation.resolveContainerAnnotation()
}
@@ -26,16 +26,17 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds.Annotations
object FirJavaAnnotationsChecker : FirAnnotationChecker() {
private val javaToKotlinNameMap: Map<ClassId, ClassId> =
mapOf(
Annotations.Java.Target to Annotations.Target,
Annotations.Java.Retention to Annotations.Retention,
Annotations.Java.Deprecated to Annotations.Deprecated,
Annotations.Java.Documented to Annotations.MustBeDocumented,
JvmNames.Annotations.Java.Target to Annotations.Target,
JvmNames.Annotations.Java.Retention to Annotations.Retention,
JvmNames.Annotations.Java.Deprecated to Annotations.Deprecated,
JvmNames.Annotations.Java.Documented to Annotations.MustBeDocumented,
)
override fun check(expression: FirAnnotation, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
@@ -15,11 +14,10 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getRetention
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.FirFromMissingDependenciesNamedReference
import org.jetbrains.kotlin.fir.references.resolved
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -121,26 +119,7 @@ fun FirAnnotation.isRepeatable(session: FirSession): Boolean {
if (annotationClassId.isLocal) return false
val annotationClass = session.symbolProvider.getClassLikeSymbolByClassId(annotationClassId) ?: return false
return annotationClass.containsRepeatableAnnotation(session)
}
fun FirClassLikeSymbol<*>.containsRepeatableAnnotation(session: FirSession): Boolean {
if (getAnnotationByClassId(StandardClassIds.Annotations.Repeatable, session) != null) return true
if (getAnnotationByClassId(StandardClassIds.Annotations.Java.Repeatable, session) != null ||
getAnnotationByClassId(StandardClassIds.Annotations.JvmRepeatable, session) != null
) {
return session.languageVersionSettings.supportsFeature(LanguageFeature.RepeatableAnnotations) ||
getAnnotationRetention(session) == AnnotationRetention.SOURCE && origin is FirDeclarationOrigin.Java
}
return false
}
fun FirClassLikeSymbol<*>.getExplicitAnnotationRetention(session: FirSession): AnnotationRetention? {
return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session)?.getRetention()
}
fun FirClassLikeSymbol<*>.getAnnotationRetention(session: FirSession): AnnotationRetention {
return getExplicitAnnotationRetention(session) ?: AnnotationRetention.RUNTIME
return session.annotationPlatformSupport.symbolContainsRepeatableAnnotation(annotationClass, session)
}
fun FirAnnotationContainer.getDefaultUseSiteTarget(
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2023 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.analysis.checkers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
abstract class FirPrimaryConstructorSuperTypeCheckerPlatformComponent : FirSessionComponent {
abstract val supertypesThatDontNeedInitializationInSubtypesConstructors: Set<ClassId>
object Default : FirPrimaryConstructorSuperTypeCheckerPlatformComponent() {
override val supertypesThatDontNeedInitializationInSubtypesConstructors: Set<ClassId> = setOf(StandardClassIds.Enum)
}
}
val FirSession.primaryConstructorSuperTypePlatformSupport by FirSession.sessionComponentAccessor<FirPrimaryConstructorSuperTypeCheckerPlatformComponent>()
@@ -18,8 +18,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLE_IN_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.getRetention
import org.jetbrains.kotlin.fir.analysis.getRetentionAnnotation
import org.jetbrains.kotlin.fir.declarations.getRetention
import org.jetbrains.kotlin.fir.declarations.getRetentionAnnotation
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
@@ -12,8 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.getRetention
import org.jetbrains.kotlin.fir.analysis.getRetentionAnnotation
import org.jetbrains.kotlin.fir.declarations.getRetention
import org.jetbrains.kotlin.fir.declarations.getRetentionAnnotation
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.resolve.checkers.OptInDescription
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.primaryConstructorSuperTypePlatformSupport
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
@@ -22,7 +23,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
/** Checker on super type declarations in the primary constructor of a class declaration. */
@@ -80,7 +80,9 @@ object FirPrimaryConstructorSuperTypeChecker : FirClassChecker() {
}
val delegatedCallSource = delegatedConstructorCall.source ?: return
if (delegatedCallSource.kind !is KtFakeSourceElementKind) return
if (superClassSymbol.classId == StandardClassIds.Enum || superClassSymbol.classId == StandardClassIds.Java.Record) return
val supertypesToSkip = context.session.primaryConstructorSuperTypePlatformSupport
.supertypesThatDontNeedInitializationInSubtypesConstructors
if (superClassSymbol.classId in supertypesToSkip) return
if (delegatedCallSource.elementType != KtNodeTypes.SUPER_TYPE_CALL_ENTRY) {
reporter.reportOn(constructedTypeRef.source, FirErrors.SUPERTYPE_NOT_INITIALIZED, context)
}
@@ -7,24 +7,19 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassIds
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.name.StandardClassIds
object FirVolatileAnnotationChecker : FirPropertyChecker() {
private val VOLATILE_CLASS_IDS = listOf(StandardClassIds.Annotations.Volatile, StandardClassIds.Annotations.JvmVolatile)
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.source?.kind != KtRealSourceElementKind) return
val fieldAnnotation = declaration.backingField?.annotations?.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session)
val volatileAnnotations = context.session.annotationPlatformSupport.volatileAnnotations
val fieldAnnotation = declaration.backingField?.annotations?.getAnnotationByClassIds(volatileAnnotations, context.session)
?: return
if (!declaration.isVar) {
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAnonymousFunctionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationRetention
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.InlineStatus
import org.jetbrains.kotlin.fir.declarations.getAnnotationRetention
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
object FirInlinedLambdaNonSourceAnnotationsChecker : FirAnonymousFunctionChecker() {
@@ -12,15 +12,19 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.checkers.FirInlineCheckerPlatformSpecificComponent
import org.jetbrains.kotlin.fir.analysis.checkers.FirPrimaryConstructorSuperTypeCheckerPlatformComponent
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmAnnotationsPlatformSpecificSupportComponent
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmInlineCheckerComponent
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmPrimaryConstructorSuperTypeCheckerPlatformComponent
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper
import org.jetbrains.kotlin.fir.declarations.FirTypeSpecificityComparatorProvider
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl
import org.jetbrains.kotlin.fir.declarations.FirAnnotationsPlatformSpecificSupportComponent
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationExtension
import org.jetbrains.kotlin.fir.extensions.*
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
@@ -83,6 +87,8 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
register(FirOverrideChecker::class, FirStandardOverrideChecker(this))
register(FirDeclarationOverloadabilityHelper::class, FirDeclarationOverloadabilityHelperImpl(this))
register(FirAnnotationsPlatformSpecificSupportComponent::class, FirAnnotationsPlatformSpecificSupportComponent.Default)
register(FirPrimaryConstructorSuperTypeCheckerPlatformComponent::class, FirPrimaryConstructorSuperTypeCheckerPlatformComponent.Default)
}
@OptIn(SessionConfiguration::class)
@@ -134,6 +140,8 @@ fun FirSession.registerCommonJavaComponents(
register(FirDeserializationExtension::class, FirJvmDeserializationExtension(this))
register(FirEnumEntriesSupport::class, FirJvmEnumEntriesSupport(this))
register(CompilerRequiredAnnotationEnhancementProvider::class, JavaCompilerRequiredAnnotationEnhancementProvider)
register(FirAnnotationsPlatformSpecificSupportComponent::class, FirJvmAnnotationsPlatformSpecificSupportComponent)
register(FirPrimaryConstructorSuperTypeCheckerPlatformComponent::class, FirJvmPrimaryConstructorSuperTypeCheckerPlatformComponent)
}
// -------------------------- Resolve components --------------------------
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -41,14 +41,14 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.threadLocal
import java.util.concurrent.ConcurrentHashMap
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
@OptIn(LeakedDeclarationCaches::class)
class Fir2IrDeclarationStorage(
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
@@ -8,8 +8,11 @@ package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirArrayLiteral
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
@@ -25,6 +28,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaModifierListOwner
import org.jetbrains.kotlin.load.java.structure.JavaWildcardType
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.types.ConstantValueKind
internal val JavaModifierListOwner.modality: Modality
@@ -132,3 +136,9 @@ fun extractNullabilityAnnotationOnBoundedWildcard(wildcardType: JavaWildcardType
require(wildcardType.bound != null) { "Nullability annotations on unbounded wildcards aren't supported" }
return wildcardType.annotations.find { annotation -> RXJAVA3_ANNOTATIONS.any { annotation.classId?.asSingleFqName() == it } }
}
fun FirProperty.hasJvmFieldAnnotation(session: FirSession): Boolean =
backingField?.annotations?.any { it.isJvmFieldAnnotation(session) } == true
fun FirAnnotation.isJvmFieldAnnotation(session: FirSession): Boolean =
toAnnotationClassId(session) == JvmNames.Annotations.JvmField
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
class JvmSupertypeUpdater(private val session: FirSession) : PlatformSupertypeUpdater() {
@@ -32,7 +33,7 @@ class JvmSupertypeUpdater(private val session: FirSession) : PlatformSupertypeUp
override fun updateSupertypesIfNeeded(firClass: FirClass, scopeSession: ScopeSession) {
if (firClass !is FirRegularClass || !firClass.isData ||
!firClass.hasAnnotationSafe(StandardClassIds.Annotations.JvmRecord, session)
!firClass.hasAnnotationSafe(JvmNames.Annotations.JvmRecord, session)
) return
var anyFound = false
var hasExplicitSuperClass = false
@@ -61,7 +62,7 @@ class JvmSupertypeUpdater(private val session: FirSession) : PlatformSupertypeUp
private class DelegatedConstructorCallTransformer(private val session: FirSession) : FirTransformer<ScopeSession>() {
companion object {
val recordType = StandardClassIds.Java.Record.constructClassLikeType(emptyArray(), isNullable = false)
val recordType = JvmNames.Java.Record.constructClassLikeType(emptyArray(), isNullable = false)
}
override fun <E : FirElement> transformElement(element: E, data: ScopeSession): E {
@@ -103,7 +104,7 @@ class JvmSupertypeUpdater(private val session: FirSession) : PlatformSupertypeUp
if (recordConstructorSymbol != null) {
val newReference = buildResolvedNamedReference {
name = StandardClassIds.Java.Record.shortClassName
name = JvmNames.Java.Record.shortClassName
resolvedSymbol = recordConstructorSymbol
}
delegatedConstructorCall.replaceCalleeReference(newReference)
@@ -10,12 +10,13 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationEnhancementProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
object JavaCompilerRequiredAnnotationEnhancementProvider : CompilerRequiredAnnotationEnhancementProvider() {
override fun enhance(enumSymbol: FirClassSymbol<*>, enumEntrySymbol: FirEnumEntrySymbol, session: FirSession): FirEnumEntrySymbol {
val firRegularClass = enumSymbol.fir as? FirRegularClass ?: return enumEntrySymbol
if (enumSymbol.classId != StandardClassIds.Annotations.Java.ElementType) return enumEntrySymbol
if (enumSymbol.classId != JvmNames.Annotations.Java.ElementType) return enumEntrySymbol
return FirSignatureEnhancement(firRegularClass, session) { emptyList() }.enhancedProperty(
enumEntrySymbol,
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.toKtPsiSourceElement
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
@@ -68,7 +65,7 @@ internal fun JavaAnnotationOwner.convertAnnotationsToFir(
internal object DeprecatedInJavaDocAnnotation : JavaAnnotation {
override val arguments: Collection<JavaAnnotationArgument> get() = emptyList()
override val classId: ClassId get() = StandardClassIds.Annotations.Java.Deprecated
override val classId: ClassId get() = JvmStandardClassIds.Annotations.Java.Deprecated
override fun resolve(): JavaClass? = null
}
@@ -255,15 +252,15 @@ private fun fillAnnotationArgumentMapping(
}
internal fun JavaAnnotation.isJavaDeprecatedAnnotation(): Boolean {
return classId == StandardClassIds.Annotations.Java.Deprecated
return classId == JvmStandardClassIds.Annotations.Java.Deprecated
}
private fun JavaAnnotation.toFirAnnotationCall(session: FirSession): FirAnnotation = buildAnnotation {
val lookupTag = when (classId) {
StandardClassIds.Annotations.Java.Target -> StandardClassIds.Annotations.Target
StandardClassIds.Annotations.Java.Retention -> StandardClassIds.Annotations.Retention
StandardClassIds.Annotations.Java.Documented -> StandardClassIds.Annotations.MustBeDocumented
StandardClassIds.Annotations.Java.Deprecated -> StandardClassIds.Annotations.Deprecated
JvmNames.Annotations.Java.Target -> StandardClassIds.Annotations.Target
JvmNames.Annotations.Java.Retention -> StandardClassIds.Annotations.Retention
JvmNames.Annotations.Java.Documented -> StandardClassIds.Annotations.MustBeDocumented
JvmNames.Annotations.Java.Deprecated -> StandardClassIds.Annotations.Deprecated
else -> classId
}?.toLookupTag()
annotationTypeRef = if (lookupTag != null) {
@@ -288,7 +285,7 @@ private fun JavaAnnotation.toFirAnnotationCall(session: FirSession): FirAnnotati
override val mapping: Map<Name, FirExpression> by lazy {
when {
classId == StandardClassIds.Annotations.Java.Target -> {
classId == JvmNames.Annotations.Java.Target -> {
when (val argument = arguments.firstOrNull()) {
is JavaArrayAnnotationArgument -> argument.getElements().mapJavaTargetArguments(session)
is JavaEnumValueAnnotationArgument -> listOf(argument).mapJavaTargetArguments(session)
@@ -298,13 +295,13 @@ private fun JavaAnnotation.toFirAnnotationCall(session: FirSession): FirAnnotati
}
}
classId == StandardClassIds.Annotations.Java.Retention -> {
classId == JvmNames.Annotations.Java.Retention -> {
arguments.firstOrNull()?.mapJavaRetentionArgument(session)?.let {
mapOf(StandardClassIds.Annotations.ParameterNames.retentionValue to it)
}
}
classId == StandardClassIds.Annotations.Java.Deprecated -> {
classId == JvmNames.Annotations.Java.Deprecated -> {
mapOf(
StandardClassIds.Annotations.ParameterNames.deprecatedMessage to "Deprecated in Java".createConstantOrError(
session,
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
@@ -70,13 +69,6 @@ fun List<FirAnnotation>.nonSourceAnnotations(session: FirSession): List<FirAnnot
fun FirAnnotationContainer.nonSourceAnnotations(session: FirSession): List<FirAnnotation> =
annotations.nonSourceAnnotations(session)
@Suppress("NOTHING_TO_INLINE")
inline fun FirProperty.hasJvmFieldAnnotation(session: FirSession): Boolean =
backingField?.annotations?.any { it.isJvmFieldAnnotation(session) } == true
fun FirAnnotation.isJvmFieldAnnotation(session: FirSession): Boolean =
toAnnotationClassId(session) == StandardClassIds.Annotations.JvmField
fun FirAnnotation.useSiteTargetsFromMetaAnnotation(session: FirSession): Set<AnnotationUseSiteTarget> {
return toAnnotationClass(session)
?.annotations
@@ -186,18 +178,6 @@ fun List<FirAnnotation>.getAnnotationByClassIds(classIds: Collection<ClassId>, s
}
}
inline fun <T> List<FirAnnotation>.mapAnnotationsWithClassIdTo(
classId: ClassId,
destination: MutableCollection<T>,
func: (FirAnnotation) -> T
) {
for (annotation in this) {
if (annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == classId) {
destination.add(func(annotation))
}
}
}
fun FirExpression.unwrapVarargValue(): List<FirExpression> {
return when (this) {
is FirVarargArgumentsExpression -> arguments
@@ -243,14 +223,6 @@ fun FirGetClassCall.getTargetType(): ConeKotlinType? {
return resolvedType.typeArguments.getOrNull(0)?.type
}
fun FirAnnotationContainer.getJvmNameFromAnnotation(session: FirSession, target: AnnotationUseSiteTarget? = null): String? {
val annotationCalls = getAnnotationsByClassId(StandardClassIds.Annotations.JvmName, session)
return annotationCalls.firstNotNullOfOrNull { call ->
call.getStringArgument(StandardNames.NAME)
?.takeIf { target == null || call.useSiteTarget == target }
}
}
val FirAnnotation.resolved: Boolean
get() {
if (annotationTypeRef !is FirResolvedTypeRef) return false
@@ -0,0 +1,93 @@
/*
* Copyright 2010-2023 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.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
/**
* @see org.jetbrains.kotlin.light.classes.symbol.annotations.GranularAnnotationsBox.Companion
*/
abstract class FirAnnotationsPlatformSpecificSupportComponent : FirSessionComponent {
abstract val requiredAnnotationsWithArguments: Set<ClassId>
abstract val requiredAnnotations: Set<ClassId>
abstract val volatileAnnotations: Set<ClassId>
val requiredAnnotationsShortClassNames: Set<Name> by lazy {
requiredAnnotations.mapTo(mutableSetOf()) { it.shortClassName }
}
/**
* Maps deprecation annotation ClassIds to the flag
* which is true iff the corresponding annotation must
* be propagated to overrides.
*/
abstract val deprecationAnnotationsWithOverridesPropagation: Map<ClassId, Boolean>
private val deprecationAnnotations: Set<ClassId> by lazy {
deprecationAnnotationsWithOverridesPropagation.keys
}
val deprecationAnnotationsSimpleNames: Set<String> by lazy {
deprecationAnnotations.mapTo(mutableSetOf()) { it.shortClassName.asString() }
}
abstract fun symbolContainsRepeatableAnnotation(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean
abstract fun extractBackingFieldAnnotationsFromProperty(
property: FirProperty,
session: FirSession,
propertyAnnotations: List<FirAnnotation> = property.annotations,
backingFieldAnnotations: List<FirAnnotation> = property.backingField?.annotations.orEmpty(),
): AnnotationsPosition?
object Default : FirAnnotationsPlatformSpecificSupportComponent() {
override val requiredAnnotationsWithArguments = setOf(
StandardClassIds.Annotations.Deprecated,
StandardClassIds.Annotations.Target,
)
override val requiredAnnotations = requiredAnnotationsWithArguments + setOf(
StandardClassIds.Annotations.DeprecatedSinceKotlin,
StandardClassIds.Annotations.SinceKotlin,
StandardClassIds.Annotations.WasExperimental,
)
override val volatileAnnotations = setOf(
StandardClassIds.Annotations.Volatile,
)
override val deprecationAnnotationsWithOverridesPropagation = mapOf(
StandardClassIds.Annotations.Deprecated to true,
StandardClassIds.Annotations.SinceKotlin to true,
)
override fun symbolContainsRepeatableAnnotation(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
return symbol.getAnnotationByClassId(StandardClassIds.Annotations.Repeatable, session) != null
}
override fun extractBackingFieldAnnotationsFromProperty(
property: FirProperty,
session: FirSession,
propertyAnnotations: List<FirAnnotation>,
backingFieldAnnotations: List<FirAnnotation>,
): AnnotationsPosition? {
return null
}
}
}
val FirSession.annotationPlatformSupport by FirSession.sessionComponentAccessor<FirAnnotationsPlatformSpecificSupportComponent>()
class AnnotationsPosition(
val backingFieldAnnotations: List<FirAnnotation>,
val propertyAnnotations: List<FirAnnotation>,
)
@@ -3,15 +3,14 @@
* 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.analysis
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedEnumEntrySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
fun FirRegularClass.getRetention(session: FirSession): AnnotationRetention {
@@ -41,6 +40,10 @@ private fun FirRegularClassSymbol.getRetentionAnnotation(session: FirSession): F
return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session)
}
private fun FirRegularClassSymbol.getAnnotationByClassId(classId: ClassId, session: FirSession): FirAnnotation? {
return resolvedAnnotationsWithArguments.firstOrNull { it.toAnnotationClassId(session) == classId }
}
fun FirClassLikeSymbol<*>.getExplicitAnnotationRetention(session: FirSession): AnnotationRetention? {
return getAnnotationByClassId(StandardClassIds.Annotations.Retention, session)?.getRetention()
}
fun FirClassLikeSymbol<*>.getAnnotationRetention(session: FirSession): AnnotationRetention {
return getExplicitAnnotationRetention(session) ?: AnnotationRetention.RUNTIME
}
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.forEachType
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
@@ -123,7 +121,7 @@ fun FirAnnotationContainer.extractDeprecationInfoPerUseSite(
versionRequirements = this.versionRequirements
}
return buildDeprecationAnnotationInfoPerUseSiteStorage {
add((customAnnotations ?: annotations).extractDeprecationAnnotationInfoPerUseSite(fromJava, versionRequirements))
add((customAnnotations ?: annotations).extractDeprecationAnnotationInfoPerUseSite(fromJava, session, versionRequirements))
if (this@extractDeprecationInfoPerUseSite is FirProperty) {
add(
getDeprecationsAnnotationInfoByUseSiteFromAccessors(
@@ -179,7 +177,7 @@ fun List<FirAnnotation>.getDeprecationsProviderFromAnnotations(
fromJava: Boolean,
versionRequirements: List<VersionRequirement>? = null,
): DeprecationsProvider {
val deprecationAnnotationByUseSite = extractDeprecationAnnotationInfoPerUseSite(fromJava, versionRequirements)
val deprecationAnnotationByUseSite = extractDeprecationAnnotationInfoPerUseSite(fromJava, session, versionRequirements)
return deprecationAnnotationByUseSite.toDeprecationsProvider(session.firCachesFactory)
}
@@ -252,29 +250,26 @@ private fun FirAnnotation.getDeprecationLevel(): DeprecationLevelValue? {
return DeprecationLevelValue.values().find { it.name == targetName }
}
val deprecationAnnotationSimpleNames: Set<String> = setOf(
StandardClassIds.Annotations.Deprecated.shortClassName.asString(),
StandardClassIds.Annotations.Java.Deprecated.shortClassName.asString(),
StandardClassIds.Annotations.SinceKotlin.shortClassName.asString(),
)
private fun List<FirAnnotation>.extractDeprecationAnnotationInfoPerUseSite(
fromJava: Boolean,
session: FirSession,
versionRequirements: List<VersionRequirement>?,
): DeprecationAnnotationInfoPerUseSiteStorage {
// NB: We can't expand typealiases (`toAnnotationClassId`), because it
// requires `lookupTag.tySymbol()`, but we can have cycles in annotations.
// See the commit message for an example.
@Suppress("RemoveExplicitTypeArguments")
val annotations = buildList<Pair<FirAnnotation, Boolean>> {
mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.Deprecated, this) { it to false }
mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.Java.Deprecated, this) { it to true }
mapAnnotationsWithClassIdTo(StandardClassIds.Annotations.SinceKotlin, this) { it to false }
}
val annotations = session.annotationPlatformSupport.deprecationAnnotationsWithOverridesPropagation
.flatMap { (classId, shouldPropagateToOverrides) ->
this.filter {
it.unexpandedClassId == classId
}.map {
it to shouldPropagateToOverrides
}
}
return buildDeprecationAnnotationInfoPerUseSiteStorage {
for ((deprecated, fromJavaAnnotation) in annotations) {
for ((deprecated, shouldPropagateToOverrides) in annotations) {
if (deprecated.unexpandedClassId == StandardClassIds.Annotations.SinceKotlin) {
val sinceKotlinSingleArgument = deprecated.findArgumentByName(ParameterNames.sinceKotlinVersion)
val apiVersion = ((sinceKotlinSingleArgument as? FirConstExpression<*>)?.value as? String)
@@ -287,7 +282,7 @@ private fun List<FirAnnotation>.extractDeprecationAnnotationInfoPerUseSite(
}
} else {
val deprecationLevel = deprecated.getDeprecationLevel() ?: DeprecationLevelValue.WARNING
val propagatesToOverride = !fromJavaAnnotation && !fromJava
val propagatesToOverride = shouldPropagateToOverrides && !fromJava
val deprecatedSinceKotlin = this@extractDeprecationAnnotationInfoPerUseSite.firstOrNull {
it.unexpandedClassId == StandardClassIds.Annotations.DeprecatedSinceKotlin
}
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.getRetention
import org.jetbrains.kotlin.fir.declarations.getRetention
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isActual
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
@@ -9,6 +9,7 @@ import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.extensions.*
@@ -21,8 +22,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper.REQUIRED_ANNOTATIONS
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper.REQUIRED_ANNOTATIONS_WITH_ARGUMENTS
import org.jetbrains.kotlin.fir.resolve.transformers.withClassDeclarationCleanup
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
@@ -40,38 +39,10 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Deprecated
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DeprecatedSinceKotlin
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Java
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.JvmRecord
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.SinceKotlin
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Target
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.WasExperimental
import org.jetbrains.kotlin.util.PrivateForInline
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
/**
* @see org.jetbrains.kotlin.light.classes.symbol.annotations.GranularAnnotationsBox.Companion
*/
object CompilerRequiredAnnotationsHelper {
internal val REQUIRED_ANNOTATIONS_WITH_ARGUMENTS: Set<ClassId> = setOf(
Deprecated,
Target,
Java.Target,
)
val REQUIRED_ANNOTATIONS: Set<ClassId> = REQUIRED_ANNOTATIONS_WITH_ARGUMENTS + setOf(
Java.Deprecated,
DeprecatedSinceKotlin,
SinceKotlin,
WasExperimental,
JvmRecord,
)
}
@OptIn(PrivateForInline::class)
abstract class AbstractFirSpecificAnnotationResolveTransformer(
@property:PrivateForInline val session: FirSession,
@@ -79,10 +50,6 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
@property:PrivateForInline val computationSession: CompilerRequiredAnnotationsComputationSession,
containingDeclarations: List<FirDeclaration> = emptyList()
) : FirDefaultTransformer<Nothing?>() {
companion object {
private val REQUIRED_ANNOTATION_NAMES: Set<Name> = REQUIRED_ANNOTATIONS.mapTo(mutableSetOf()) { it.shortClassName }
}
inner class FirEnumAnnotationArgumentsTransformerDispatcher : FirAbstractBodyResolveTransformerDispatcher(
session,
FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS,
@@ -244,7 +211,9 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
val requiredAnnotationsWithArguments = session.annotationPlatformSupport.requiredAnnotationsWithArguments
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in requiredAnnotationsWithArguments) {
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
}
}
@@ -261,13 +230,13 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
fun shouldRunAnnotationResolve(typeRef: FirUserTypeRef): Boolean {
val name = typeRef.qualifier.last().name
if (metaAnnotationsFromPlugins.isNotEmpty()) return true
return name in REQUIRED_ANNOTATION_NAMES || annotationsFromPlugins.any { it.shortName() == name }
return name in session.annotationPlatformSupport.requiredAnnotationsShortClassNames || annotationsFromPlugins.any { it.shortName() == name }
}
private fun FirResolvedTypeRef.requiredToSave(): Boolean {
val classId = type.classId ?: return false
return when {
classId in REQUIRED_ANNOTATIONS -> true
classId in session.annotationPlatformSupport.requiredAnnotations -> true
classId.asSingleFqName() in annotationsFromPlugins -> true
metaAnnotationsFromPlugins.isEmpty() -> false
else -> type.markedWithMetaAnnotation(session, metaAnnotationsFromPlugins)
@@ -424,31 +393,11 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
}
private fun FirProperty.moveJavaDeprecatedAnnotationToBackingField() {
val newPosition = extractBackingFieldAnnotationsFromProperty(this) ?: return
val newPosition = session.annotationPlatformSupport.extractBackingFieldAnnotationsFromProperty(this, session) ?: return
this.replaceAnnotations(newPosition.propertyAnnotations)
backingField?.replaceAnnotations(newPosition.backingFieldAnnotations)
}
fun extractBackingFieldAnnotationsFromProperty(
property: FirProperty,
propertyAnnotations: List<FirAnnotation> = property.annotations,
backingFieldAnnotations: List<FirAnnotation> = property.backingField?.annotations.orEmpty(),
): AnnotationsPosition? {
if (propertyAnnotations.isEmpty() || property.backingField == null) return null
val (newBackingFieldAnnotations, newPropertyAnnotations) = propertyAnnotations.partition {
it.toAnnotationClassIdSafe(session) == Java.Deprecated
}
if (newBackingFieldAnnotations.isEmpty()) return null
return AnnotationsPosition(
propertyAnnotations = newPropertyAnnotations,
backingFieldAnnotations = backingFieldAnnotations + newBackingFieldAnnotations,
)
}
class AnnotationsPosition(val backingFieldAnnotations: List<FirAnnotation>, val propertyAnnotations: List<FirAnnotation>)
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: Nothing?