[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
@@ -12,7 +12,12 @@ import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
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
import org.jetbrains.kotlin.fir.declarations.getAnnotationsByClassId
import org.jetbrains.kotlin.fir.declarations.getStringArgument
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
@@ -31,6 +36,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithSymbol
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeHiddenCandidateError
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -116,3 +122,11 @@ internal fun FirAnnotation.toKtAnnotationInfo(
*/
internal val FirResolvedQualifier.isImplicitDispatchReceiver: Boolean
get() = source?.kind == KtFakeSourceElementKind.ImplicitReceiver
fun FirAnnotationContainer.getJvmNameFromAnnotation(session: FirSession, target: AnnotationUseSiteTarget? = null): String? {
val annotationCalls = getAnnotationsByClassId(JvmNames.Annotations.JvmName, session)
return annotationCalls.firstNotNullOfOrNull { call ->
call.getStringArgument(StandardNames.NAME)
?.takeIf { target == null || call.useSiteTarget == target }
}
}
@@ -5,12 +5,7 @@
package org.jetbrains.kotlin.analysis.api.fir.annotations
import org.jetbrains.kotlin.analysis.api.annotations.AnnotationUseSiteTargetFilter
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationInfo
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
import org.jetbrains.kotlin.analysis.api.annotations.KtArrayAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtEnumEntryAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationInfo
import org.jetbrains.kotlin.analysis.utils.errors.withClassEntry
@@ -18,23 +13,15 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.resolvePhase
import org.jetbrains.kotlin.fir.declarations.resolved
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassIdSafe
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.resolvedAnnotationsWithArguments
import org.jetbrains.kotlin.fir.symbols.resolvedAnnotationsWithClassIds
import org.jetbrains.kotlin.fir.symbols.resolvedCompilerRequiredAnnotations
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import java.lang.annotation.ElementType
@@ -65,7 +52,7 @@ internal fun annotationsByClassId(
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
annotation.asKtAnnotationApplicationForTargetAnnotation(useSiteSession, index)
}
} else if (classId == StandardClassIds.Annotations.Java.Target && firSymbol.fir.resolvePhase < FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
} else if (classId == JvmNames.Annotations.Java.Target && firSymbol.fir.resolvePhase < FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
annotationContainer.resolvedAnnotationsWithClassIds(firSymbol)
.mapIndexedToAnnotationApplication(useSiteTargetFilter, useSiteSession, classId) { index, annotation ->
annotation.asKtAnnotationApplicationForJavaTargetAnnotation(useSiteSession, index)
@@ -140,7 +127,7 @@ private fun FirAnnotation.asKtAnnotationApplicationForJavaTargetAnnotation(
): KtAnnotationApplicationWithArgumentsInfo = asKtAnnotationApplicationForAnnotationWithEnumArgument(
useSiteSession = useSiteSession,
index = index,
expectedEnumClassId = StandardClassIds.Annotations.Java.ElementType,
expectedEnumClassId = JvmNames.Annotations.Java.ElementType,
annotationParameterName = StandardClassIds.Annotations.ParameterNames.value,
nameMapper = { ElementType.values().firstOrNull { enumValue -> enumValue.name == it }?.name },
)
@@ -193,7 +180,7 @@ internal fun hasAnnotation(
useSiteSession: FirSession,
annotationContainer: FirAnnotationContainer = firSymbol.fir,
): Boolean {
return if (firSymbol.isFromCompilerRequiredAnnotationsPhase(classId)) {
return if (firSymbol.isFromCompilerRequiredAnnotationsPhase(classId, useSiteSession)) {
// this loop by index is required to avoid possible ConcurrentModificationException
val annotations = annotationContainer.resolvedCompilerRequiredAnnotations(firSymbol)
for (index in annotations.indices) {
@@ -211,5 +198,7 @@ internal fun hasAnnotation(
}
}
private fun FirBasedSymbol<*>.isFromCompilerRequiredAnnotationsPhase(classId: ClassId): Boolean =
fir.resolvePhase < FirResolvePhase.TYPES && classId in CompilerRequiredAnnotationsHelper.REQUIRED_ANNOTATIONS
private fun FirBasedSymbol<*>.isFromCompilerRequiredAnnotationsPhase(classId: ClassId, session: FirSession): Boolean {
val requiredAnnotations = session.annotationPlatformSupport.requiredAnnotations
return fir.resolvePhase < FirResolvePhase.TYPES && classId in requiredAnnotations
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.api.fir.components
import org.jetbrains.kotlin.analysis.api.components.KtSymbolInfoProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.getJvmNameFromAnnotation
import org.jetbrains.kotlin.analysis.api.fir.symbols.*
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
@@ -61,6 +63,7 @@ internal class KtFirSymbolInfoProvider(
// Check the simple names of the Java annotations. While presence of such an annotation name does not prove deprecation, it is a
// necessary condition for it. Type aliases are not a problem here: Java code cannot access Kotlin type aliases. (Currently,
// deprecation annotation type aliases do not work in Kotlin, either, but this might change in the future.)
val deprecationAnnotationSimpleNames = analysisSession.useSiteSession.annotationPlatformSupport.deprecationAnnotationsSimpleNames
return annotationSimpleNames.any { it != null && it in deprecationAnnotationSimpleNames }
}
@@ -127,7 +130,7 @@ internal class KtFirSymbolInfoProvider(
}
private fun getJvmName(property: FirProperty, isSetter: Boolean): Name {
if (property.backingField?.symbol?.hasAnnotation(StandardClassIds.Annotations.JvmField, analysisSession.useSiteSession) == true) {
if (property.backingField?.symbol?.hasAnnotation(JvmNames.Annotations.JvmField, analysisSession.useSiteSession) == true) {
return property.name
}
return Name.identifier(getJvmNameAsString(property, isSetter))
@@ -19,12 +19,11 @@ import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyDelegatedConstructorCall
import org.jetbrains.kotlin.fir.extensions.registeredPluginAnnotations
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
internal object FirLazyBodiesCalculator {
@@ -319,15 +318,12 @@ private abstract class FirLazyAnnotationTransformer : FirTransformer<FirLazyAnno
return element
}
private val COMPILER_ANNOTATION_NAMES: Set<Name> = CompilerRequiredAnnotationsHelper.REQUIRED_ANNOTATIONS
.mapTo(mutableSetOf()) { it.shortClassName }
private fun canBeCompilerAnnotation(annotationCall: FirAnnotationCall, session: FirSession): Boolean {
val annotationTypeRef = annotationCall.annotationTypeRef
if (annotationTypeRef !is FirUserTypeRef) return false
if (session.registeredPluginAnnotations.annotations.isNotEmpty()) return true
val name = annotationTypeRef.qualifier.last().name
return name in COMPILER_ANNOTATION_NAMES
return name in session.annotationPlatformSupport.requiredAnnotationsShortClassNames
}
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: FirLazyAnnotationTransformerData): FirTypeRef {
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) {
override fun resolve(
@@ -197,8 +198,9 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver(
fun balanceAnnotations(target: FirElementWithResolveState) {
if (target !is FirProperty) return
val backingField = target.backingField ?: return
val updatedAnnotations = transformer.annotationTransformer.extractBackingFieldAnnotationsFromProperty(
val updatedAnnotations = transformer.session.annotationPlatformSupport.extractBackingFieldAnnotationsFromProperty(
target,
transformer.session,
annotationMap[target].orEmpty(),
annotationMap[backingField].orEmpty(),
) ?: return
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import java.lang.annotation.ElementType
@@ -143,7 +144,7 @@ private fun javaRetentionArguments(kotlinRetentionName: String?): List<KtNamedAn
name = StandardNames.DEFAULT_VALUE_PARAMETER,
expression = KtEnumEntryAnnotationValue(
callableId = CallableId(
StandardClassIds.Annotations.Java.RetentionPolicy,
JvmNames.Annotations.Java.RetentionPolicy,
Name.identifier(retentionMapping(kotlinRetentionName ?: AnnotationRetention.RUNTIME.name)),
),
sourcePsi = null,
@@ -226,7 +227,7 @@ private fun SymbolLightJavaAnnotation.computeTargetJavaAnnotationArguments(): Li
values = javaTargetNames.map {
KtEnumEntryAnnotationValue(
callableId = CallableId(
classId = StandardClassIds.Annotations.Java.ElementType,
classId = JvmNames.Annotations.Java.ElementType,
callableName = Name.identifier(it),
),
sourcePsi = null,
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.SmartList
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
@@ -95,7 +96,7 @@ internal class GranularAnnotationsBox(
* @see org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper
*/
private val specialAnnotationsListWithSafeArgumentsResolve: Map<String, ClassId> = listOf(
StandardClassIds.Annotations.JvmRecord,
JvmNames.Annotations.JvmRecord,
).associateBy { it.asFqNameString() }
/**
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.JvmNames.JVM_OVERLOADS_CLASS_ID
import org.jetbrains.kotlin.name.JvmNames.JVM_SYNTHETIC_ANNOTATION_CLASS_ID
import org.jetbrains.kotlin.name.StandardClassIds
@@ -52,7 +53,7 @@ internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(
internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(
useSiteTargetFilter: AnnotationUseSiteTargetFilter = AnyAnnotationUseSiteTargetFilter,
): String? {
val annotation = findAnnotation(StandardClassIds.Annotations.JvmName, useSiteTargetFilter)
val annotation = findAnnotation(JvmNames.Annotations.JvmName, useSiteTargetFilter)
return annotation?.let {
(it.arguments.firstOrNull()?.expression as? KtConstantAnnotationValue)?.constantValue?.value as? String
}
@@ -70,7 +71,7 @@ internal fun KtAnnotatedSymbol.isHiddenOrSynthetic(
useSiteTargetFilter: AnnotationUseSiteTargetFilter = annotationUseSiteTarget.toFilter(),
) = isHiddenByDeprecation(this, annotationUseSiteTarget) || hasJvmSyntheticAnnotation(useSiteTargetFilter)
internal fun KtAnnotatedSymbol.hasJvmFieldAnnotation(): Boolean = hasAnnotation(StandardClassIds.Annotations.JvmField)
internal fun KtAnnotatedSymbol.hasJvmFieldAnnotation(): Boolean = hasAnnotation(JvmNames.Annotations.JvmField)
internal fun KtAnnotatedSymbol.hasPublishedApiAnnotation(
useSiteTargetFilter: AnnotationUseSiteTargetFilter = AnyAnnotationUseSiteTargetFilter,
@@ -84,7 +85,7 @@ internal fun KtAnnotatedSymbol.hasJvmOverloadsAnnotation(): Boolean = hasAnnotat
internal fun KtAnnotatedSymbol.hasJvmStaticAnnotation(
useSiteTargetFilter: AnnotationUseSiteTargetFilter = AnyAnnotationUseSiteTargetFilter,
): Boolean = hasAnnotation(StandardClassIds.Annotations.JvmStatic, useSiteTargetFilter)
): Boolean = hasAnnotation(JvmNames.Annotations.JvmStatic, useSiteTargetFilter)
internal fun KtAnnotatedSymbol.hasInlineOnlyAnnotation(): Boolean = hasAnnotation(StandardClassIds.Annotations.InlineOnly)
@@ -109,7 +110,7 @@ internal fun KtAnnotatedSymbol.computeThrowsList(
builder.addReference(java.lang.NullPointerException::class.qualifiedName)
}
val annoApp = findAnnotation(StandardClassIds.Annotations.Throws, useSiteTargetFilter) ?: return
val annoApp = findAnnotation(JvmNames.Annotations.Throws, useSiteTargetFilter) ?: return
fun handleAnnotationValue(annotationValue: KtAnnotationValue) = when (annotationValue) {
is KtArrayAnnotationValue -> {
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.light.classes.symbol.isJvmField
import org.jetbrains.kotlin.light.classes.symbol.mapType
import org.jetbrains.kotlin.light.classes.symbol.methods.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -565,7 +566,7 @@ internal fun KtSymbolWithMembers.createInnerClasses(
if (containingClass is SymbolLightClassForAnnotationClass &&
this is KtNamedClassOrObjectSymbol &&
hasAnnotation(StandardClassIds.Annotations.Repeatable) &&
!hasAnnotation(StandardClassIds.Annotations.Java.Repeatable)
!hasAnnotation(JvmNames.Annotations.Java.Repeatable)
) {
result.add(SymbolLightClassForRepeatableAnnotationContainer(containingClass))
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
@@ -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?
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.name
object JvmNames {
val BASE_JVM_PACKAGE = StandardClassIds.BASE_KOTLIN_PACKAGE.child(Name.identifier("jvm"))
@JvmField
val JVM_NAME: FqName = FqName("kotlin.jvm.JvmName")
@@ -67,4 +69,37 @@ object JvmNames {
val TRANSIENT_ANNOTATION_CLASS_ID = ClassId.topLevel(TRANSIENT_ANNOTATION_FQ_NAME)
const val MULTIFILE_PART_NAME_DELIMITER = "__"
object Annotations {
val JvmStatic = "JvmStatic".jvmId()
val JvmName = "JvmName".jvmId()
val JvmField = "JvmField".jvmId()
val JvmDefault = "JvmDefault".jvmId()
val JvmRepeatable = "JvmRepeatable".jvmId()
val JvmRecord = "JvmRecord".jvmId()
val JvmVolatile = "Volatile".jvmId()
val Throws = "Throws".jvmId()
object Java {
val Deprecated = "Deprecated".javaLangId()
val Repeatable = "Repeatable".javaAnnotationId()
val Retention = "Retention".javaAnnotationId()
val Documented = "Documented".javaAnnotationId()
val Target = "Target".javaAnnotationId()
val ElementType = "ElementType".javaAnnotationId()
val RetentionPolicy = "RetentionPolicy".javaAnnotationId()
}
}
object Java {
val Record = "Record".javaLangId()
}
}
private fun String.jvmId() = ClassId(JvmNames.BASE_JVM_PACKAGE, Name.identifier(this))
private val JAVA_LANG_PACKAGE = FqName("java.lang")
private val JAVA_LANG_ANNOTATION_PACKAGE = JAVA_LANG_PACKAGE.child(Name.identifier("annotation"))
private fun String.javaLangId() = ClassId(JAVA_LANG_PACKAGE, Name.identifier(this))
private fun String.javaAnnotationId() = ClassId(JAVA_LANG_ANNOTATION_PACKAGE, Name.identifier(this))
@@ -166,15 +166,6 @@ object StandardClassIds {
val Repeatable = "Repeatable".annotationId()
val MustBeDocumented = "MustBeDocumented".annotationId()
val JvmStatic = "JvmStatic".jvmId()
val JvmName = "JvmName".jvmId()
val JvmField = "JvmField".jvmId()
val JvmDefault = "JvmDefault".jvmId()
val JvmRepeatable = "JvmRepeatable".jvmId()
val JvmRecord = "JvmRecord".jvmId()
val JvmVolatile = "Volatile".jvmId()
val Throws = "Throws".jvmId()
val Volatile = "Volatile".concurrentId()
val Test = "Test".testId()
@@ -199,16 +190,6 @@ object StandardClassIds {
val OptionalExpectation = "OptionalExpectation".baseId()
val ImplicitlyActualizedByJvmDeclaration = "ImplicitlyActualizedByJvmDeclaration".jvmId()
object Java {
val Deprecated = "Deprecated".javaLangId()
val Repeatable = "Repeatable".javaAnnotationId()
val Retention = "Retention".javaAnnotationId()
val Documented = "Documented".javaAnnotationId()
val Target = "Target".javaAnnotationId()
val ElementType = "ElementType".javaAnnotationId()
val RetentionPolicy = "RetentionPolicy".javaAnnotationId()
}
object ParameterNames {
val value = Name.identifier("value")
@@ -241,10 +222,6 @@ object StandardClassIds {
val contract = "contract".callableId(BASE_CONTRACTS_PACKAGE)
}
object Java {
val Record = "Record".javaLangId()
}
object Collections {
val baseCollectionToMutableEquivalent: Map<ClassId, ClassId> = mapOf(
StandardClassIds.Iterable to StandardClassIds.MutableIterable,
@@ -283,10 +260,4 @@ private fun String.testId() = ClassId(StandardClassIds.BASE_TEST_PACKAGE, Name.i
private fun String.callableId(packageName: FqName) = CallableId(packageName, Name.identifier(this))
private fun String.callableId(classId: ClassId) = CallableId(classId, Name.identifier(this))
private val JAVA_LANG_PACKAGE = FqName("java.lang")
private val JAVA_LANG_ANNOTATION_PACKAGE = JAVA_LANG_PACKAGE.child(Name.identifier("annotation"))
private fun String.javaLangId() = ClassId(JAVA_LANG_PACKAGE, Name.identifier(this))
private fun String.javaAnnotationId() = ClassId(JAVA_LANG_ANNOTATION_PACKAGE, Name.identifier(this))
private fun <K, V> Map<K, V>.inverseMap(): Map<V, K> = entries.associate { (k, v) -> v to k }
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.*
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializationJvmIrIntrinsicSupport
@@ -66,7 +63,7 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
referenceFunctions(CallableId(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, Name.identifier("intArrayOf"))).first()
// Kotlin stdlib declarations
internal val jvmFieldClassSymbol = referenceClass(StandardClassIds.Annotations.JvmField)!!
internal val jvmFieldClassSymbol = referenceClass(JvmNames.Annotations.JvmField)!!
internal val lazyModeClass = referenceClass(ClassId.topLevel(SerializationDependencies.LAZY_MODE_FQ))!!.owner
internal val lazyModePublicationEnumEntry =
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.*
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor
@@ -507,7 +508,7 @@ object KSerializerDescriptorResolver {
else this.makeNullable()
fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): SimpleFunctionDescriptor {
val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies(StandardClassIds.Annotations.JvmStatic)!!
val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies(JvmNames.Annotations.JvmStatic)!!
val jvmStaticAnnotation = AnnotationDescriptorImpl(jvmStaticClass.defaultType, mapOf(), jvmStaticClass.source)
val annotations = Annotations.create(listOfNotNull(jvmStaticAnnotation, thisClass.jsExportIgnore()))
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.platform.jvm.isJvm
@@ -107,7 +108,7 @@ class SerializationFirDeclarationsForMetadataProvider(session: FirSession) : Fir
private fun createJvmStaticAnnotation(): FirAnnotation? {
val jvmStatic =
session.symbolProvider.getClassLikeSymbolByClassId(StandardClassIds.Annotations.JvmStatic) as? FirRegularClassSymbol
session.symbolProvider.getClassLikeSymbolByClassId(JvmNames.Annotations.JvmStatic) as? FirRegularClassSymbol
?: return null
val jvmStaticCtor =
jvmStatic.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>() ?: return null
@@ -11,12 +11,12 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.containsRepeatableAnnotation
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.analysis.checkers.isSingleFieldValueClass
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull
import org.jetbrains.kotlin.fir.expressions.*
@@ -79,7 +79,7 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
context(CheckerContext)
private fun checkInheritableSerialInfoNotRepeatable(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
if (classSymbol.classKind != ClassKind.ANNOTATION_CLASS) return
if (!classSymbol.containsRepeatableAnnotation(session)) return
if (!session.annotationPlatformSupport.symbolContainsRepeatableAnnotation(classSymbol, session)) return
val anno = classSymbol.resolvedAnnotationsWithClassIds
.find { it.toAnnotationClassId(session) == SerializationAnnotations.inheritableSerialInfoClassId }
?: return
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.java.hasJvmFieldAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion