K2: fix field annotation splitting and frontend checks

Related to KT-57135
This commit is contained in:
Mikhail Glukhikh
2023-03-22 16:13:51 +01:00
committed by Space Team
parent 37ed7beda0
commit dc38ce24f7
43 changed files with 497 additions and 119 deletions
@@ -39,6 +39,18 @@ public class FirOutOfContentRootLazyBodiesCalculatorTestGenerated extends Abstra
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@Test
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@Test
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@Test
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
@@ -39,6 +39,18 @@ public class FirSourceLazyBodiesCalculatorTestGenerated extends AbstractFirSourc
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@Test
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@Test
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@Test
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
@@ -6747,6 +6747,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/falseSamConversion.kt");
}
@Test
@TestMetadata("FieldAnnotationWithClasses.kt")
public void testFieldAnnotationWithClasses() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.kt");
}
@Test
@TestMetadata("immutableName.kt")
public void testImmutableName() throws Exception {
@@ -6747,6 +6747,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/falseSamConversion.kt");
}
@Test
@TestMetadata("FieldAnnotationWithClasses.kt")
public void testFieldAnnotationWithClasses() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.kt");
}
@Test
@TestMetadata("immutableName.kt")
public void testImmutableName() throws Exception {
@@ -1,5 +1,5 @@
FILE: concurrent.kt
@R|kotlin/jvm/Volatile|() public final var xx: R|kotlin/Int| = Int(2)
field:@R|kotlin/jvm/Volatile|() public final var xx: R|kotlin/Int| = Int(2)
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@R|kotlin/jvm/Synchronized|() public final fun foo(): R|kotlin/Unit| {
@@ -0,0 +1,34 @@
FILE: FieldAnnotationWithClasses.kt
public final annotation class Ann : R|kotlin/Annotation| {
public constructor(vararg allowedTypes: R|kotlin/Array<out kotlin/reflect/KClass<*>>|): R|Ann| {
super<R|kotlin/Any|>()
}
public final val allowedTypes: R|kotlin/Array<out kotlin/reflect/KClass<*>>| = R|<local>/allowedTypes|
public get(): R|kotlin/Array<out kotlin/reflect/KClass<*>>|
}
public final fun foo(): R|kotlin/Unit| {
local final class Local : R|kotlin/Any| {
public constructor(): R|Local| {
super<R|kotlin/Any|>()
}
field:@FIELD:R|Ann|(allowedTypes = vararg(allowedTypes = <implicitArrayOf>(<getClass>(Q|Some|), <getClass>(Q|Other|)))) public final val x: R|kotlin/Int| = Int(42)
public get(): R|kotlin/Int|
}
}
public final class Some : R|kotlin/Any| {
public constructor(): R|Some| {
super<R|kotlin/Any|>()
}
}
public final class Other : R|kotlin/Any| {
public constructor(): R|Other| {
super<R|kotlin/Any|>()
}
}
@@ -0,0 +1,15 @@
// WITH_REFLECT
import kotlin.reflect.*
annotation class Ann(vararg val allowedTypes: KClass<*>)
fun foo() {
class Local {
@field:Ann(allowedTypes = [Some::class, Other::class])
val x: Int = 42
}
}
class Some
class Other
@@ -6747,6 +6747,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/falseSamConversion.kt");
}
@Test
@TestMetadata("FieldAnnotationWithClasses.kt")
public void testFieldAnnotationWithClasses() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.kt");
}
@Test
@TestMetadata("immutableName.kt")
public void testImmutableName() throws Exception {
@@ -6747,6 +6747,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/falseSamConversion.kt");
}
@Test
@TestMetadata("FieldAnnotationWithClasses.kt")
public void testFieldAnnotationWithClasses() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.kt");
}
@Test
@TestMetadata("immutableName.kt")
public void testImmutableName() throws Exception {
@@ -39,7 +39,8 @@ import org.jetbrains.kotlin.name.StandardClassIds
object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val session = context.session
val annotation = declaration.getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID, session) ?: return
val annotation = declaration.backingField?.getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID, session)
?: return
val containingClassSymbol = declaration.containingClassLookupTag()?.toFirRegularClassSymbol(session)
val problem = when {
@@ -125,7 +126,7 @@ object FirJvmFieldApplicabilityChecker : FirPropertyChecker() {
}
private fun FirPropertySymbol.hasJvmFieldAnnotation(session: FirSession): Boolean {
return getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID, session) != null
return backingFieldSymbol?.getAnnotationByClassId(JVM_FIELD_ANNOTATION_CLASS_ID, session) != null
}
private fun isInsideJvmMultifileClassFile(context: CheckerContext): Boolean {
@@ -199,10 +199,8 @@ object FirJvmStaticChecker : FirBasicDeclarationChecker() {
reporter: DiagnosticReporter,
targetSource: KtSourceElement?,
) {
if (
declaration is FirProperty && declaration.isConst ||
declaration.hasAnnotationNamedAs(StandardClassIds.Annotations.JvmField)
) {
if (declaration !is FirProperty) return
if (declaration.isConst || declaration.backingField?.hasAnnotationNamedAs(StandardClassIds.Annotations.JvmField) == true) {
reporter.reportOn(targetSource, FirJvmErrors.JVM_STATIC_ON_CONST_OR_JVM_FIELD, context)
}
}
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.name.JvmNames.JVM_SYNTHETIC_ANNOTATION_CLASS_ID
object FirJvmSyntheticApplicabilityChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
val annotation = declaration.delegateFieldSymbol?.getAnnotationByClassId(JVM_SYNTHETIC_ANNOTATION_CLASS_ID, context.session)
val annotation = declaration.backingField?.getAnnotationByClassId(JVM_SYNTHETIC_ANNOTATION_CLASS_ID, context.session)
if (annotation != null && annotation.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) {
reporter.reportOn(annotation.source, FirJvmErrors.JVM_SYNTHETIC_ON_DELEGATE, context)
}
@@ -587,11 +587,15 @@ fun FirFunctionSymbol<*>.isFunctionForExpectTypeFromCastFeature(): Boolean {
return true
}
fun getActualTargetList(annotated: FirAnnotationContainer): AnnotationTargetList {
fun getActualTargetList(container: FirAnnotationContainer): AnnotationTargetList {
fun CallableId.isMember(): Boolean {
return classId != null || isLocal // TODO: Replace with .containingClass (after fixing)
}
val annotated =
if (container is FirBackingField && !container.propertySymbol.hasBackingField) container.propertyIfBackingField
else container
return when (annotated) {
is FirRegularClass -> {
AnnotationTargetList(
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.delegatedWrapperData
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.packageFqName
@@ -118,8 +119,8 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
propertySymbol.resolvedReceiverTypeRef == null && propertySymbol.resolvedContextReceivers.isEmpty()
val (hint, type) = when (annotation.useSiteTarget) {
FIELD -> "fields" to ((declaration as? FirProperty)?.backingField?.returnTypeRef ?: return)
PROPERTY_DELEGATE_FIELD -> "delegate fields" to ((declaration as? FirProperty)?.delegate?.typeRef ?: return)
FIELD -> "fields" to ((declaration as? FirBackingField)?.returnTypeRef ?: return)
PROPERTY_DELEGATE_FIELD -> "delegate fields" to ((declaration as? FirBackingField)?.propertySymbol?.delegate?.typeRef ?: return)
RECEIVER -> "receivers" to ((declaration as? FirCallableDeclaration)?.receiverParameter?.typeRef ?: return)
FILE, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, CONSTRUCTOR_PARAMETER, SETTER_PARAMETER, null -> when {
declaration is FirProperty && !declaration.isLocal -> {
@@ -216,12 +217,15 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
)
}
FIELD -> {
if (annotated is FirProperty && annotated.delegateFieldSymbol != null && !annotated.hasBackingField) {
reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD, context)
if (annotated is FirBackingField) {
val propertySymbol = annotated.propertySymbol
if (propertySymbol.delegateFieldSymbol != null && !propertySymbol.hasBackingField) {
reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD, context)
}
}
}
PROPERTY_DELEGATE_FIELD -> {
if (annotated is FirProperty && annotated.delegateFieldSymbol == null) {
if (annotated is FirBackingField && annotated.propertySymbol.delegateFieldSymbol == null) {
reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, context)
}
}
@@ -24,8 +24,7 @@ object FirVolatileAnnotationChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.source?.kind != KtRealSourceElementKind) return
val fieldAnnotation = declaration.annotations.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session)
?: declaration.backingField?.annotations?.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session)
val fieldAnnotation = declaration.backingField?.annotations?.getAnnotationByClassIds(VOLATILE_CLASS_IDS, context.session)
?: return
if (!declaration.isVar) {
@@ -5,28 +5,25 @@
package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.declarations.FirBackingField
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.useSiteTargetsFromMetaAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.util.isSetter
/**
* A generator that converts annotations in [FirAnnotationContainer] to annotations in [IrMutableAnnotationContainer].
*
* In general, annotations are bound to the target in the beginning, i.e., clearly targeted at source level. But, there are some cases that
* need special handling: [AnnotationUseSiteTarget]. In particular, [FirProperty] contains all annotations associated with that property,
* whose targets may vary. After all the necessary pieces of IR elements, e.g., backing field, are ready, this generator splits those
* annotations to the specified targets.
* Annotations are bound to the target already in frontend, e.g.
*
* Note: Annotations on primary constructor properties are already split between value parameters and properties in FIR. Before this change,
* it used to be done here.
* + Annotations on primary constructor properties are already split between value parameters, properties and backing fields in FIR.</li>
* + Annotations on regular properties are also already split between properties and backing fields.</li>
*
* So this class task is only to convert FirAnnotations to IrAnnotations.
* Some time before, it performed also annotation splitting between use-site targets.
*/
class AnnotationGenerator(private val components: Fir2IrComponents) : Fir2IrComponents by components {
@@ -39,56 +36,15 @@ class AnnotationGenerator(private val components: Fir2IrComponents) : Fir2IrComp
irContainer.annotations = firContainer.annotations.toIrAnnotations()
}
private fun FirAnnotation.target(applicable: List<AnnotationUseSiteTarget>): AnnotationUseSiteTarget? =
useSiteTarget ?: applicable.firstOrNull(useSiteTargetsFromMetaAnnotation(session)::contains)
companion object {
private val propertyTargets = listOf(AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.FIELD)
private val delegatedPropertyTargets = propertyTargets + listOf(AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD)
}
fun generate(irValueParameter: IrValueParameter, firValueParameter: FirValueParameter) {
irValueParameter.annotations += firValueParameter.annotations.toIrAnnotations()
}
fun generate(irProperty: IrProperty, property: FirProperty) {
val applicableTargets = if (irProperty.isDelegated) delegatedPropertyTargets else propertyTargets
irProperty.annotations += property.annotations
.filter { it.target(applicableTargets) == AnnotationUseSiteTarget.PROPERTY }
.toIrAnnotations()
irProperty.annotations += property.annotations.toIrAnnotations()
}
fun generate(irField: IrField, property: FirProperty) {
val irProperty = irField.correspondingPropertySymbol?.owner ?: throw AssertionError("$irField is not a property field")
val applicableTargets = if (irProperty.isDelegated) delegatedPropertyTargets else propertyTargets
property.backingField?.let {
irField.annotations += it.annotations.filter {
val target = it.target(applicableTargets)
target == AnnotationUseSiteTarget.FIELD || target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}.toIrAnnotations()
}
}
fun generate(propertyAccessor: IrFunction, property: FirProperty) {
assert(propertyAccessor.isPropertyAccessor) { "$propertyAccessor is not a property accessor." }
if (propertyAccessor.isSetter) {
propertyAccessor.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER }
.toIrAnnotations()
val parameter = propertyAccessor.valueParameters.last()
parameter.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER }
.toIrAnnotations()
} else {
propertyAccessor.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER }
.toIrAnnotations()
}
propertyAccessor.extensionReceiverParameter?.let { receiver ->
receiver.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER }
.toIrAnnotations()
}
fun generate(irField: IrField, backingField: FirBackingField) {
irField.annotations += backingField.annotations.toIrAnnotations()
}
}
@@ -267,7 +267,7 @@ internal class ClassMemberGenerator(
}
declarationStorage.leaveScope(this@initializeBackingField)
}
annotationGenerator.generate(irField, property)
property.backingField?.let { annotationGenerator.generate(irField, it) }
}
private fun IrSimpleFunction.setPropertyAccessorContent(
@@ -314,7 +314,6 @@ internal class ClassMemberGenerator(
}
}
annotationGenerator.generate(this, property)
}
private fun IrFieldAccessExpression.setReceiver(declaration: IrDeclaration): IrFieldAccessExpression {
@@ -318,13 +318,6 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
basePropertySymbols[delegateProperty] = baseSymbols
annotationGenerator.generate(delegateProperty, firDelegateProperty)
val getter = delegateProperty.getter!!
annotationGenerator.generate(getter, firDelegateProperty)
if (delegateProperty.isVar) {
val setter = delegateProperty.setter!!
annotationGenerator.generate(setter, firDelegateProperty)
}
return delegateProperty
}
@@ -154,6 +154,9 @@ class Fir2IrLazyProperty(
}
}?.apply {
this.parent = this@Fir2IrLazyProperty.parent
this.annotations = fir.backingField?.annotations?.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}.orEmpty()
}
}
@@ -70,7 +70,8 @@ fun FirAnnotationContainer.nonSourceAnnotations(session: FirSession): List<FirAn
annotations.nonSourceAnnotations(session)
@Suppress("NOTHING_TO_INLINE")
inline fun FirProperty.hasJvmFieldAnnotation(session: FirSession): Boolean = annotations.any { it.isJvmFieldAnnotation(session) }
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
@@ -1220,7 +1220,12 @@ class DeclarationsConverter(
typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, symbol) }
backingField = fieldDeclaration.convertBackingField(symbol, modifiers, returnType, isVar)
backingField = fieldDeclaration.convertBackingField(
symbol, modifiers, returnType, isVar,
if (isLocal) emptyList() else modifiers.annotations.filter {
it.useSiteTarget == FIELD || it.useSiteTarget == PROPERTY_DELEGATE_FIELD
}
)
if (isLocal) {
this.isLocal = true
@@ -1318,7 +1323,7 @@ class DeclarationsConverter(
}
}
annotations += if (isLocal) modifiers.annotations else modifiers.annotations.filter {
it.useSiteTarget != PROPERTY_GETTER &&
it.useSiteTarget != FIELD && it.useSiteTarget != PROPERTY_DELEGATE_FIELD && it.useSiteTarget != PROPERTY_GETTER &&
(!isVar || it.useSiteTarget != SETTER_PARAMETER && it.useSiteTarget != PROPERTY_SETTER)
}
@@ -1503,6 +1508,7 @@ class DeclarationsConverter(
propertyModifiers: Modifier,
propertyReturnType: FirTypeRef,
isVar: Boolean,
annotationsFromProperty: List<FirAnnotationCall>,
): FirBackingField {
var modifiers = Modifier()
var returnType: FirTypeRef = implicitType
@@ -1532,6 +1538,7 @@ class DeclarationsConverter(
symbol = FirBackingFieldSymbol(CallableId(name))
this.status = status
annotations += modifiers.annotations
annotations += annotationsFromProperty
this.propertySymbol = propertySymbol
this.initializer = backingFieldInitializer
this.isVar = isVar
@@ -1540,7 +1547,7 @@ class DeclarationsConverter(
} else {
FirDefaultPropertyBackingField(
moduleData = baseModuleData,
annotations = mutableListOf(),
annotations = annotationsFromProperty.toMutableList(),
returnTypeRef = propertyReturnType.copyWithNewSourceKind(KtFakeSourceElementKind.DefaultAccessor),
isVar = isVar,
propertySymbol = propertySymbol,
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.fir
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.Context
@@ -136,16 +137,16 @@ class ValueParameter(
}
backingField = FirDefaultPropertyBackingField(
moduleData = moduleData,
annotations = mutableListOf(),
annotations = modifiers.annotations.filter {
it.useSiteTarget == FIELD || it.useSiteTarget == PROPERTY_DELEGATE_FIELD
}.toMutableList(),
returnTypeRef = returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DefaultAccessor),
isVar = isVar,
propertySymbol = symbol,
status = status.copy(),
)
annotations += modifiers.annotations.filter {
it.useSiteTarget == null || it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY ||
it.useSiteTarget == AnnotationUseSiteTarget.FIELD ||
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
it.useSiteTarget == null || it.useSiteTarget == PROPERTY
}
val defaultAccessorSource = propertySource?.fakeElement(KtFakeSourceElementKind.DefaultAccessor)
getter = FirDefaultPropertyGetter(
@@ -46,6 +46,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
@@ -540,6 +540,7 @@ open class RawFirBuilder(
property: KtProperty,
propertySymbol: FirPropertySymbol,
propertyReturnType: FirTypeRef,
annotationsFromProperty: List<FirAnnotationCall>,
): FirBackingField {
val componentVisibility = if (this?.visibility != null && this.visibility != Visibilities.Unknown) {
this.visibility
@@ -558,6 +559,7 @@ open class RawFirBuilder(
returnTypeRef = returnType
this.status = status
extractAnnotationsTo(this)
this.annotations += annotationsFromProperty
name = BACKING_FIELD
symbol = FirBackingFieldSymbol(CallableId(name))
this.propertySymbol = propertySymbol
@@ -570,7 +572,7 @@ open class RawFirBuilder(
} else {
FirDefaultPropertyBackingField(
moduleData = baseModuleData,
annotations = mutableListOf(),
annotations = annotationsFromProperty.toMutableList(),
returnTypeRef = propertyReturnType.copyWithNewSourceKind(KtFakeSourceElementKind.DefaultAccessor),
isVar = property.isVar,
propertySymbol = propertySymbol,
@@ -654,7 +656,9 @@ open class RawFirBuilder(
isLocal = false
backingField = FirDefaultPropertyBackingField(
moduleData = baseModuleData,
annotations = mutableListOf(),
annotations = parameterAnnotations.filter {
it.useSiteTarget == FIELD || it.useSiteTarget == PROPERTY_DELEGATE_FIELD
}.toMutableList(),
returnTypeRef = returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DefaultAccessor),
isVar = isVar,
propertySymbol = symbol,
@@ -687,9 +691,7 @@ open class RawFirBuilder(
setter.replaceAnnotations(parameterAnnotations.filterUseSiteTarget(PROPERTY_SETTER))
} else null
annotations += parameterAnnotations.filter {
it.useSiteTarget == null || it.useSiteTarget == PROPERTY ||
it.useSiteTarget == FIELD ||
it.useSiteTarget == PROPERTY_DELEGATE_FIELD
it.useSiteTarget == null || it.useSiteTarget == PROPERTY
}
dispatchReceiverType = currentDispatchReceiverType()
@@ -1767,6 +1769,7 @@ open class RawFirBuilder(
this@toFirProperty,
propertySymbol = symbol,
propertyType,
emptyList(),
)
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL).apply {
@@ -1801,6 +1804,7 @@ open class RawFirBuilder(
this@toFirProperty,
propertySymbol = symbol,
propertyType,
propertyAnnotations.filter { it.useSiteTarget == FIELD || it.useSiteTarget == PROPERTY_DELEGATE_FIELD },
)
getter = this@toFirProperty.getter.toFirPropertyAccessor(
@@ -1856,7 +1860,7 @@ open class RawFirBuilder(
}
}
annotations += if (isLocal) propertyAnnotations else propertyAnnotations.filter {
it.useSiteTarget != PROPERTY_GETTER &&
it.useSiteTarget != FIELD && it.useSiteTarget != PROPERTY_DELEGATE_FIELD && it.useSiteTarget != PROPERTY_GETTER &&
(!isVar || it.useSiteTarget != SETTER_PARAMETER && it.useSiteTarget != PROPERTY_SETTER)
}
@@ -0,0 +1,36 @@
import kotlin.reflect.KProperty
annotation class Ann
class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
}
@field:Ann
class SomeClass {
@field:Ann
constructor()
@field:Ann
protected val simpleProperty: String = "text"
@field:[Ann]
protected val simplePropertyWithAnnotationList: String = "text"
@field:Ann
protected val delegatedProperty: String by CustomDelegate()
@field:Ann
val propertyWithCustomGetter: Int
get() = 5
@field:Ann
fun anotherFun(@field:Ann s: String) {
@field:Ann
val localVariable = 5
}
}
class WithPrimaryConstructor(@field:Ann val a: String)
@@ -0,0 +1,46 @@
FILE: annotationOnField.kt
public? final? annotation class Ann : R|kotlin/Annotation| {
public? constructor(): R|Ann| {
LAZY_super<R|kotlin/Any|>
}
}
public? final? class CustomDelegate : R|kotlin/Any| {
public? constructor(): R|CustomDelegate| {
LAZY_super<R|kotlin/Any|>
}
public? final? operator fun getValue(thisRef: Any?, prop: KProperty<*>): String { LAZY_BLOCK }
}
@FIELD:Ann() public? final? class SomeClass : R|kotlin/Any| {
@FIELD:Ann() public? constructor(): R|SomeClass| {
LAZY_super<R|kotlin/Any|>
}
field:@FIELD:Ann() protected final? val simpleProperty: String = LAZY_EXPRESSION
protected get(): String
field:@FIELD:Ann() protected final? val simplePropertyWithAnnotationList: String = LAZY_EXPRESSION
protected get(): String
field:@FIELD:Ann() protected final? val delegatedProperty: Stringby LAZY_EXPRESSION
protected get(): <implicit> {
^ this@R|/SomeClass|.D|/SomeClass.delegatedProperty|.getValue#(this@R|/SomeClass|, ::R|/SomeClass.delegatedProperty|)
}
field:@FIELD:Ann() public? final? val propertyWithCustomGetter: Int
public? get(): Int { LAZY_BLOCK }
@FIELD:Ann() public? final? fun anotherFun(@FIELD:Ann() s: String): R|kotlin/Unit| { LAZY_BLOCK }
}
public? final? class WithPrimaryConstructor : R|kotlin/Any| {
public? constructor(a: String): R|WithPrimaryConstructor| {
LAZY_super<R|kotlin/Any|>
}
field:@FIELD:Ann() public? final? val a: String = R|<local>/a|
public? get(): String
}
@@ -0,0 +1,52 @@
FILE: annotationOnField.kt
public? final? annotation class Ann : R|kotlin/Annotation| {
public? [ContainingClassKey=Ann] constructor(): R|Ann| {
super<R|kotlin/Any|>()
}
}
public? final? class CustomDelegate : R|kotlin/Any| {
public? [ContainingClassKey=CustomDelegate] constructor(): R|CustomDelegate| {
super<R|kotlin/Any|>()
}
public? final? operator fun getValue(thisRef: Any?, prop: KProperty<*>): String {
^getValue prop#.name#
}
}
@FIELD:Ann() public? final? class SomeClass : R|kotlin/Any| {
@FIELD:Ann() public? [ContainingClassKey=SomeClass] constructor(): R|SomeClass| {
super<R|kotlin/Any|>()
}
field:@FIELD:Ann() protected final? val simpleProperty: String = String(text)
protected [ContainingClassKey=SomeClass] get(): String
field:@FIELD:Ann() protected final? val simplePropertyWithAnnotationList: String = String(text)
protected [ContainingClassKey=SomeClass] get(): String
field:@FIELD:Ann() protected final? val delegatedProperty: Stringby CustomDelegate#()
protected [ContainingClassKey=SomeClass] get(): <implicit> {
^ this@R|/SomeClass|.D|/SomeClass.delegatedProperty|.getValue#(this@R|/SomeClass|, ::R|/SomeClass.delegatedProperty|)
}
field:@FIELD:Ann() public? final? val propertyWithCustomGetter: Int
public? [ContainingClassKey=SomeClass] get(): Int {
^ IntegerLiteral(5)
}
@FIELD:Ann() public? final? fun anotherFun(@FIELD:Ann() s: String): R|kotlin/Unit| {
@FIELD:Ann() lval localVariable: <implicit> = IntegerLiteral(5)
}
}
public? final? class WithPrimaryConstructor : R|kotlin/Any| {
public? [ContainingClassKey=WithPrimaryConstructor] constructor([CorrespondingProperty=/WithPrimaryConstructor.a] a: String): R|WithPrimaryConstructor| {
super<R|kotlin/Any|>()
}
field:@FIELD:Ann() public? final? [IsFromPrimaryConstructor=true] val a: String = R|<local>/a|
public? [ContainingClassKey=WithPrimaryConstructor] get(): String
}
@@ -0,0 +1,21 @@
annotation class Ann
@field:Ann
val x: Int = 1
@property:Ann
val y: Int = 2
@Ann
val z: Int = 3
class Some(@field:Ann val x: Int, @property: Ann val y: Int, @param:Ann val z: Int, val w: Int) {
@field:Ann
val a: Int = 1
@property:Ann
val b: Int = 2
@Ann
val c: Int = 3
}
@@ -0,0 +1,40 @@
FILE: annotationOnProperty.kt
public? final? annotation class Ann : R|kotlin/Annotation| {
public? constructor(): R|Ann| {
LAZY_super<R|kotlin/Any|>
}
}
field:@FIELD:Ann() public? final? val x: Int = LAZY_EXPRESSION
public? get(): Int
@PROPERTY:Ann() public? final? val y: Int = LAZY_EXPRESSION
public? get(): Int
@Ann() public? final? val z: Int = LAZY_EXPRESSION
public? get(): Int
public? final? class Some : R|kotlin/Any| {
public? constructor(x: Int, y: Int, @CONSTRUCTOR_PARAMETER:Ann() z: Int, w: Int): R|Some| {
LAZY_super<R|kotlin/Any|>
}
field:@FIELD:Ann() public? final? val x: Int = R|<local>/x|
public? get(): Int
@PROPERTY:Ann() public? final? val y: Int = R|<local>/y|
public? get(): Int
public? final? val z: Int = R|<local>/z|
public? get(): Int
public? final? val w: Int = R|<local>/w|
public? get(): Int
field:@FIELD:Ann() public? final? val a: Int = LAZY_EXPRESSION
public? get(): Int
@PROPERTY:Ann() public? final? val b: Int = LAZY_EXPRESSION
public? get(): Int
@Ann() public? final? val c: Int = LAZY_EXPRESSION
public? get(): Int
}
@@ -0,0 +1,40 @@
FILE: annotationOnProperty.kt
public? final? annotation class Ann : R|kotlin/Annotation| {
public? [ContainingClassKey=Ann] constructor(): R|Ann| {
super<R|kotlin/Any|>()
}
}
field:@FIELD:Ann() public? final? val x: Int = IntegerLiteral(1)
public? get(): Int
@PROPERTY:Ann() public? final? val y: Int = IntegerLiteral(2)
public? get(): Int
@Ann() public? final? val z: Int = IntegerLiteral(3)
public? get(): Int
public? final? class Some : R|kotlin/Any| {
public? [ContainingClassKey=Some] constructor([CorrespondingProperty=/Some.x] x: Int, [CorrespondingProperty=/Some.y] y: Int, [CorrespondingProperty=/Some.z] @CONSTRUCTOR_PARAMETER:Ann() z: Int, [CorrespondingProperty=/Some.w] w: Int): R|Some| {
super<R|kotlin/Any|>()
}
field:@FIELD:Ann() public? final? [IsFromPrimaryConstructor=true] val x: Int = R|<local>/x|
public? [ContainingClassKey=Some] get(): Int
@PROPERTY:Ann() public? final? [IsFromPrimaryConstructor=true] val y: Int = R|<local>/y|
public? [ContainingClassKey=Some] get(): Int
public? final? [IsFromPrimaryConstructor=true] val z: Int = R|<local>/z|
public? [ContainingClassKey=Some] get(): Int
public? final? [IsFromPrimaryConstructor=true] val w: Int = R|<local>/w|
public? [ContainingClassKey=Some] get(): Int
field:@FIELD:Ann() public? final? val a: Int = IntegerLiteral(1)
public? [ContainingClassKey=Some] get(): Int
@PROPERTY:Ann() public? final? val b: Int = IntegerLiteral(2)
public? [ContainingClassKey=Some] get(): Int
@Ann() public? final? val c: Int = IntegerLiteral(3)
public? [ContainingClassKey=Some] get(): Int
}
@@ -46,6 +46,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
@@ -46,6 +46,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationsOnNullableParenthesizedTypes.kt");
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers
import kotlinx.collections.immutable.*
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.correspondingProperty
@@ -147,7 +148,7 @@ open class FirTypeResolveTransformer(
if (result.isPrimary) {
for (valueParameter in result.valueParameters) {
if (valueParameter.correspondingProperty != null) {
valueParameter.removeIrrelevantAnnotations()
valueParameter.moveOrDeleteIrrelevantAnnotations()
}
}
}
@@ -218,10 +219,7 @@ open class FirTypeResolveTransformer(
unboundCyclesInTypeParametersSupertypes(property)
if (property.source?.kind == KtFakeSourceElementKind.PropertyFromParameter) {
property.removeIrrelevantAnnotations()
}
property.moveOrDeleteIrrelevantAnnotations()
calculateDeprecations(property)
property
}
@@ -486,37 +484,43 @@ open class FirTypeResolveTransformer(
* class Foo(@Ann val x: String)
* ```
* This ambiguity may be resolved by specifying the use-site explicitly, i.e. `@field:Ann` or by analysing the allowed targets from
* the [kotlin.annotation.Target] meta-annotation. In latter case, the method will assign a use-site target to the corresponding
* annotation.
* the [kotlin.annotation.Target] meta-annotation.
* In latter case, the method will ensure that the annotation is moved to the correct element (field or parameter) or left at the property.
*/
private fun FirVariable.removeIrrelevantAnnotations() {
private fun FirVariable.moveOrDeleteIrrelevantAnnotations() {
if (annotations.isEmpty()) return
val backingFieldAnnotations by lazy(LazyThreadSafetyMode.NONE) { backingField?.annotations?.toMutableList() ?: mutableListOf() }
var replaceBackingFieldAnnotations = false
replaceAnnotations(annotations.filter { annotation ->
when(annotation.useSiteTarget) {
when (annotation.useSiteTarget) {
null -> {
val allowedTargets = annotation.useSiteTargetsFromMetaAnnotation(session)
when {
this is FirValueParameter -> AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER in allowedTargets
this.source?.kind == KtFakeSourceElementKind.PropertyFromParameter && AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER in allowedTargets -> false
this is FirProperty && AnnotationUseSiteTarget.FIELD in allowedTargets && AnnotationUseSiteTarget.PROPERTY !in allowedTargets && backingField != null -> {
(this as? FirProperty)?.backingField?.replaceAnnotations(backingField!!.annotations + annotation)
this is FirValueParameter -> CONSTRUCTOR_PARAMETER in allowedTargets
this.source?.kind == KtFakeSourceElementKind.PropertyFromParameter && CONSTRUCTOR_PARAMETER in allowedTargets -> false
this is FirProperty && backingField != null && annotationShouldBeMovedToField(allowedTargets) -> {
backingFieldAnnotations += annotation
replaceBackingFieldAnnotations = true
false
}
else -> true
}
}
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> this is FirValueParameter
AnnotationUseSiteTarget.FIELD -> {
(this as? FirProperty)?.backingField?.replaceAnnotations(backingField!!.annotations + annotation)
false
}
else -> true
}
})
if (replaceBackingFieldAnnotations) {
backingField?.replaceAnnotations(backingFieldAnnotations)
}
}
private fun annotationShouldBeMovedToField(allowedTargets: Set<AnnotationUseSiteTarget>): Boolean =
(FIELD in allowedTargets || PROPERTY_DELEGATE_FIELD in allowedTargets) && PROPERTY !in allowedTargets
private fun calculateDeprecations(callableDeclaration: FirCallableDeclaration) {
if (callableDeclaration.deprecationsProvider is UnresolvedDeprecationProvider) {
callableDeclaration.replaceDeprecationsProvider(callableDeclaration.getDeprecationsProvider(session))
}
}
}
@@ -128,7 +128,7 @@ open class FirDeclarationsResolveTransformer(
val bodyResolveState = property.bodyResolveState
if (bodyResolveState == FirPropertyBodyResolveState.EVERYTHING_RESOLVED) return property
val canHaveDeepImplicitTypeRefs = property.hasExplicitBackingField
val canHaveDeepImplicitTypeRefs = property.backingField != null
if (returnTypeRefBeforeResolve !is FirImplicitTypeRef && implicitTypeOnly && !canHaveDeepImplicitTypeRefs) {
return property
}
@@ -930,6 +930,7 @@ open class FirDeclarationsResolveTransformer(
else -> ResolutionMode.ContextDependent
}
backingField.transformInitializer(transformer, initializerData)
backingField.transformAnnotations(transformer, data)
if (
backingField.returnTypeRef is FirErrorTypeRef ||
backingField.returnTypeRef is FirResolvedTypeRef
@@ -167,7 +167,7 @@ open class FirImplicitAwareBodyResolveTransformer(
return transform()
}
val canHaveDeepImplicitTypeRefs = member is FirProperty && member.hasExplicitBackingField
val canHaveDeepImplicitTypeRefs = member is FirProperty && member.backingField != null
if (member.returnTypeRef is FirResolvedTypeRef && !canHaveDeepImplicitTypeRefs) return member
val symbol = member.symbol
@@ -171,6 +171,7 @@ private class FirDeclarationsResolveTransformerForAnnotationArgumentsMapping(
.transformReturnTypeRef(transformer, data)
.transformGetter(transformer, data)
.transformSetter(transformer, data)
.transformBackingField(transformer, data)
}
return property
@@ -212,6 +213,11 @@ private class FirDeclarationsResolveTransformerForAnnotationArgumentsMapping(
return field
}
override fun transformBackingField(backingField: FirBackingField, data: ResolutionMode): FirStatement {
backingField.transformAnnotations(transformer, data)
return backingField
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias {
doTransformTypeParameters(typeAlias)
typeAlias.transformAnnotations(transformer, data)
@@ -199,6 +199,13 @@ class FirRenderer(
override fun visitCallableDeclaration(callableDeclaration: FirCallableDeclaration) {
renderContexts(callableDeclaration.contextReceivers)
annotationRenderer?.render(callableDeclaration)
if (callableDeclaration is FirProperty) {
val backingField = callableDeclaration.backingField
if (backingField?.annotations?.isNotEmpty() == true) {
print("field:")
annotationRenderer?.render(backingField)
}
}
visitMemberDeclaration(callableDeclaration)
val receiverParameter = callableDeclaration.receiverParameter
if (callableDeclaration !is FirProperty || callableDeclaration.isCatchParameter != true) {
@@ -38,6 +38,12 @@ open class FirPropertySymbol(
val delegateFieldSymbol: FirDelegateFieldSymbol?
get() = fir.delegateFieldSymbol
val delegate: FirExpression?
get() = fir.delegate
val hasDelegate: Boolean
get() = fir.delegate != null
val hasInitializer: Boolean
get() = fir.initializer != null
@@ -47,9 +53,6 @@ open class FirPropertySymbol(
return fir.initializer
}
val hasDelegate: Boolean
get() = fir.delegate != null
val controlFlowGraphReference: FirControlFlowGraphReference?
get() {
lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
@@ -4,7 +4,7 @@ FILE: test.kt
super<R|kotlin/Any|>()
}
@R|FieldOnly|() public final var param: R|kotlin/Int| = R|<local>/param|
field:@R|FieldOnly|() public final var param: R|kotlin/Int| = R|<local>/param|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -40,7 +40,7 @@ FILE: targetOnPrimaryCtorParameter.kt
super<R|kotlin/Any|>()
}
@R|PropertyOnly|() @R|PropertyOnly2|() @R|FieldOnly|() public final var param: R|kotlin/Int| = R|<local>/param|
@R|PropertyOnly|() @R|PropertyOnly2|() field:@R|FieldOnly|() public final var param: R|kotlin/Int| = R|<local>/param|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
@@ -39,6 +39,18 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@Test
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@Test
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@Test
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
@@ -39,6 +39,18 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotation.kt");
}
@Test
@TestMetadata("annotationOnField.kt")
public void testAnnotationOnField() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnField.kt");
}
@Test
@TestMetadata("annotationOnProperty.kt")
public void testAnnotationOnProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/annotationOnProperty.kt");
}
@Test
@TestMetadata("annotationsOnNullableParenthesizedTypes.kt")
public void testAnnotationsOnNullableParenthesizedTypes() throws Exception {
@@ -231,7 +231,8 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
if (classSymbol.resolvedSuperTypes.any { it.classId == JAVA_SERIALIZABLE_ID }) return // do not check
for (property in properties) {
if (property.transient) continue
val incorrectTransient = property.propertySymbol.annotations.getAnnotationByClassId(TRANSIENT_ANNOTATION_CLASS_ID, session)
val incorrectTransient =
property.propertySymbol.backingFieldSymbol?.annotations?.getAnnotationByClassId(TRANSIENT_ANNOTATION_CLASS_ID, session)
if (incorrectTransient != null) {
reporter.reportOn(
source = incorrectTransient.source ?: property.propertySymbol.source,