From 0ac02be5347bd2d3a018aaa7a08adbc4f0e9e639 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Mon, 15 May 2023 13:45:27 +0200 Subject: [PATCH] [FIR] Generate annotations to data class copy method parameters #KT-57003 Fixed --- .../StubBasedClassDeserialization.kt | 27 ++++++----- ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ ...sticCompilerFE10TestDataTestGenerated.java | 6 +++ .../testData/resolve/incorrectDataClass.kt | 1 + .../annotationUseSites.fir.txt | 2 +- ...eeOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 +++ .../converter/DeclarationsConverter.kt | 7 +++ .../fir/lightTree/fir/ValueParameter.kt | 13 ++--- .../kotlin/fir/builder/RawFirBuilder.kt | 26 +++++----- .../kotlin/fir/builder/BaseFirBuilder.kt | 17 +++++-- .../kotlin/fir/builder/ConversionUtils.kt | 5 ++ .../transformers/FirTypeResolveTransformer.kt | 31 +++++++++++- .../kotlin/fir/expressions/FirAnnotation.kt | 2 + .../fir/expressions/FirAnnotationCall.kt | 2 + .../fir/expressions/FirErrorAnnotationCall.kt | 2 + .../expressions/impl/FirAnnotationCallImpl.kt | 6 ++- .../fir/expressions/impl/FirAnnotationImpl.kt | 6 ++- .../impl/FirErrorAnnotationCallImpl.kt | 6 ++- .../fir/tree/generator/NodeConfigurator.kt | 2 +- .../kotlin/psi/stubs/KotlinStubVersions.kt | 2 +- .../annotationsOnDataClassCopy.fir.txt | 48 +++++++++++++++++++ .../annotations/annotationsOnDataClassCopy.kt | 19 ++++++++ .../annotationsOnDataClassCopy.txt | 44 +++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 +++ 25 files changed, 255 insertions(+), 43 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.fir.txt create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.txt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedClassDeserialization.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedClassDeserialization.kt index ca312046965..2fa283ac359 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedClassDeserialization.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedClassDeserialization.kt @@ -164,18 +164,21 @@ internal fun deserializeClassToSymbol( if (classOrObject.isData() && firPrimaryConstructor != null) { val zippedParameters = - classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() } zip declarations.filterIsInstance() - addDeclaration(createDataClassCopyFunction(classId, classOrObject, context.dispatchReceiver, zippedParameters, - createClassTypeRefWithSourceKind = { - firPrimaryConstructor.returnTypeRef.copyWithNewSourceKind( - it - ) - }, - createParameterTypeRefWithSourceKind = { property, newKind -> - property.returnTypeRef.copyWithNewSourceKind(newKind) - }) { src, kind -> - KtFakeSourceElement(src as PsiElement, kind) - }) + classOrObject.primaryConstructorParameters zip declarations.filterIsInstance() + addDeclaration( + createDataClassCopyFunction( + classId, + classOrObject, + context.dispatchReceiver, + zippedParameters, + createClassTypeRefWithSourceKind = { firPrimaryConstructor.returnTypeRef.copyWithNewSourceKind(it) }, + createParameterTypeRefWithSourceKind = { property, newKind -> + property.returnTypeRef.copyWithNewSourceKind(newKind) + }, + toFirSource = { src, kind -> KtFakeSourceElement(src as PsiElement, kind) }, + addValueParameterAnnotations = { annotations += context.annotationDeserializer.loadAnnotations(it) }, + ) + ) } addCloneForArrayIfNeeded(classId, context.dispatchReceiver) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index c502e5a50c7..b241d6b5a03 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -1446,6 +1446,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt"); } + @Test + @TestMetadata("annotationsOnDataClassCopy.kt") + public void testAnnotationsOnDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt"); + } + @Test @TestMetadata("annotationsOnLambdaAsCallArgument.kt") public void testAnnotationsOnLambdaAsCallArgument() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 560ffe49c42..354ab69f4ee 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -1446,6 +1446,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt"); } + @Test + @TestMetadata("annotationsOnDataClassCopy.kt") + public void testAnnotationsOnDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt"); + } + @Test @TestMetadata("annotationsOnLambdaAsCallArgument.kt") public void testAnnotationsOnLambdaAsCallArgument() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt index 6936109905b..b8506629cf3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt @@ -1,4 +1,5 @@ // ISSUE: KT-44554 +// FIR_DUMP data class Foo(a: Int, val b: Int) { val c = 4 diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/annotationUseSites.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/annotationUseSites.fir.txt index 49aa68b10b7..4afb1612135 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/annotationUseSites.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/annotationUseSites.fir.txt @@ -15,7 +15,7 @@ FILE: test.kt public final operator fun component1(): R|kotlin/String| - public final fun copy(message: R|kotlin/String| = this@R|/KotlinResult|.R|/KotlinResult.message|): R|KotlinResult| + public final fun copy(@R|KotlinMessage|() message: R|kotlin/String| = this@R|/KotlinResult|.R|/KotlinResult.message|): R|KotlinResult| } public open class Some : R|kotlin/Any| { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index e832103060e..1523450f0b8 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -1446,6 +1446,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt"); } + @Test + @TestMetadata("annotationsOnDataClassCopy.kt") + public void testAnnotationsOnDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt"); + } + @Test @TestMetadata("annotationsOnLambdaAsCallArgument.kt") public void testAnnotationsOnLambdaAsCallArgument() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 4f548c70992..863cd2318b7 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -1446,6 +1446,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt"); } + @Test + @TestMetadata("annotationsOnDataClassCopy.kt") + public void testAnnotationsOnDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt"); + } + @Test @TestMetadata("annotationsOnLambdaAsCallArgument.kt") public void testAnnotationsOnLambdaAsCallArgument() throws Exception { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index eb18f10bddc..28aba37bf85 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -599,6 +599,13 @@ class DeclarationsConverter( context.className, createClassTypeRefWithSourceKind = { firPrimaryConstructor.returnTypeRef }, createParameterTypeRefWithSourceKind = { property, _ -> property.returnTypeRef }, + addValueParameterAnnotations = { valueParam -> + valueParam.forEachChildren { + if (it.tokenType == MODIFIER_LIST) convertModifierList(it).annotations.filterTo(annotations) { + it.useSiteTarget.appliesToPrimaryConstructorParameter() + } + } + }, ).generate() } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt index 4dc3645990b..c4d76c0df07 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt @@ -7,11 +7,11 @@ 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 +import org.jetbrains.kotlin.fir.builder.appliesToPrimaryConstructorParameter import org.jetbrains.kotlin.fir.builder.filterUseSiteTarget import org.jetbrains.kotlin.fir.builder.initContainingClassAttr import org.jetbrains.kotlin.fir.copy @@ -67,10 +67,7 @@ class ValueParameter( if (!isFromPrimaryConstructor) addAll(modifiers.annotations) else - modifiers.annotations.filterTo(this) { - val useSiteTarget = it.useSiteTarget - useSiteTarget == null || useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER || useSiteTarget == AnnotationUseSiteTarget.RECEIVER || useSiteTarget == AnnotationUseSiteTarget.FILE - } + modifiers.annotations.filterTo(this) { it.useSiteTarget.appliesToPrimaryConstructorParameter() } addAll(additionalAnnotations) } } @@ -162,7 +159,7 @@ class ValueParameter( symbol, ).also { it.initContainingClassAttr(context) - it.replaceAnnotations(modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.PROPERTY_GETTER)) + it.replaceAnnotations(modifiers.annotations.filterUseSiteTarget(PROPERTY_GETTER)) } setter = if (this.isVar) FirDefaultPropertySetter( defaultAccessorSource, @@ -171,10 +168,10 @@ class ValueParameter( type.copyWithNewSourceKind(KtFakeSourceElementKind.DefaultAccessor), modifiers.getVisibility(), symbol, - parameterAnnotations = modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.SETTER_PARAMETER) + parameterAnnotations = modifiers.annotations.filterUseSiteTarget(SETTER_PARAMETER) ).also { it.initContainingClassAttr(context) - it.replaceAnnotations(modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.PROPERTY_SETTER)) + it.replaceAnnotations(modifiers.annotations.filterUseSiteTarget(PROPERTY_SETTER)) } else null }.apply { if (firValueParameter.isVararg) { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 466b0d246d7..30b84fe2155 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -604,21 +604,24 @@ open class RawFirBuilder( isNoinline = hasModifier(NOINLINE_KEYWORD) isVararg = isVarArg containingFunctionSymbol = functionSymbol - val isFromPrimaryConstructor = valueParameterDeclaration == ValueParameterDeclaration.PRIMARY_CONSTRUCTOR - for (annotationEntry in annotationEntries) { - annotationEntry.convert().takeIf { - !isFromPrimaryConstructor || it.useSiteTarget == null || - it.useSiteTarget == CONSTRUCTOR_PARAMETER || - it.useSiteTarget == RECEIVER || - it.useSiteTarget == FILE - }?.let { - this.annotations += it - } - } + addAnnotationsFrom( + this@toFirValueParameter, + isFromPrimaryConstructor = valueParameterDeclaration == ValueParameterDeclaration.PRIMARY_CONSTRUCTOR + ) annotations += additionalAnnotations } } + private fun FirValueParameterBuilder.addAnnotationsFrom(ktParameter: KtParameter, isFromPrimaryConstructor: Boolean) { + for (annotationEntry in ktParameter.annotationEntries) { + annotationEntry.convert().takeIf { + !isFromPrimaryConstructor || it.useSiteTarget.appliesToPrimaryConstructorParameter() + }?.let { + annotations += it + } + } + } + private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty { require(hasValOrVar()) val type = typeReference.convertSafe() ?: createNoTypeForParameterTypeRef() @@ -1323,6 +1326,7 @@ open class RawFirBuilder( (property.returnTypeRef.psi as KtTypeReference?).toFirOrImplicitType() } }, + addValueParameterAnnotations = { addAnnotationsFrom(it as KtParameter, isFromPrimaryConstructor = true) }, ).generate() } diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index b85944f4bb8..c9bc8b43d22 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -855,6 +855,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte private val classFqName: FqName, private val createClassTypeRefWithSourceKind: (KtFakeSourceElementKind) -> FirTypeRef, private val createParameterTypeRefWithSourceKind: (FirProperty, KtFakeSourceElementKind) -> FirTypeRef, + private val addValueParameterAnnotations: FirValueParameterBuilder.(T) -> Unit, ) { fun generate() { if (classBuilder.classKind != ClassKind.OBJECT) { @@ -870,9 +871,8 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte if (!firProperty.isVal && !firProperty.isVar) continue val name = Name.identifier("component$componentIndex") componentIndex++ - val parameterSource = sourceNode?.toFirSourceElement() val componentFunction = buildSimpleFunction { - source = parameterSource?.fakeElement(KtFakeSourceElementKind.DataClassGeneratedMembers) + source = sourceNode?.toFirSourceElement(KtFakeSourceElementKind.DataClassGeneratedMembers) moduleData = baseModuleData origin = FirDeclarationOrigin.Source returnTypeRef = firProperty.returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DataClassGeneratedMembers) @@ -898,8 +898,10 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte currentDispatchReceiverType(), zippedParameters, createClassTypeRefWithSourceKind, - createParameterTypeRefWithSourceKind - ) { src, kind -> src?.toFirSourceElement(kind) } + createParameterTypeRefWithSourceKind, + { src, kind -> src?.toFirSourceElement(kind) }, + addValueParameterAnnotations, + ) ) } } @@ -1033,7 +1035,8 @@ fun FirRegularClassBuilder.createDataClassCopyFunction( zippedParameters: List>, createClassTypeRefWithSourceKind: (KtFakeSourceElementKind) -> FirTypeRef, createParameterTypeRefWithSourceKind: (FirProperty, KtFakeSourceElementKind) -> FirTypeRef, - toFirSource: (T?, KtFakeSourceElementKind) -> KtSourceElement? + toFirSource: (T?, KtFakeSourceElementKind) -> KtSourceElement?, + addValueParameterAnnotations: FirValueParameterBuilder.(T) -> Unit, ): FirSimpleFunction { fun generateComponentAccess( parameterSource: KtSourceElement?, @@ -1086,6 +1089,10 @@ fun FirRegularClassBuilder.createDataClassCopyFunction( isCrossinline = false isNoinline = false isVararg = false + addValueParameterAnnotations(ktParameter) + for (annotation in annotations) { + annotation.replaceUseSiteTarget(null) + } } } // Refer to FIR backend ClassMemberGenerator for body generation. diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 76eb25fc0c9..8a4c84036f1 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -659,3 +659,8 @@ fun buildBalancedOrExpressionTree(conditions: List, lower: Int = (leftNode.source ?: rightNode.source)?.fakeElement(KtFakeSourceElementKind.WhenCondition) ) } + +fun AnnotationUseSiteTarget?.appliesToPrimaryConstructorParameter() = this == null || + this == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER || + this == AnnotationUseSiteTarget.RECEIVER || + this == AnnotationUseSiteTarget.FILE \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index 5d9b53033f1..8e4a89e2613 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -9,6 +9,7 @@ import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* import org.jetbrains.kotlin.fir.* @@ -248,9 +249,20 @@ open class FirTypeResolveTransformer( withScopeCleanup { withDeclaration(simpleFunction) { addTypeParametersScope(simpleFunction) - transformDeclaration(simpleFunction, data).also { + val result = transformDeclaration(simpleFunction, data).also { unboundCyclesInTypeParametersSupertypes(it as FirTypeParametersOwner) } + + if (result.source?.kind == KtFakeSourceElementKind.DataClassGeneratedMembers && + result is FirSimpleFunction && + result.name == StandardNames.DATA_CLASS_COPY + ) { + for (valueParameter in result.valueParameters) { + valueParameter.moveOrDeleteIrrelevantAnnotations() + } + } + + result } } as FirSimpleFunction } @@ -521,3 +533,20 @@ open class FirTypeResolveTransformer( private fun annotationShouldBeMovedToField(allowedTargets: Set): Boolean = (FIELD in allowedTargets || PROPERTY_DELEGATE_FIELD in allowedTargets) && PROPERTY !in allowedTargets } + +annotation class NoTarget + +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class Param + +@Target(AnnotationTarget.PROPERTY) +annotation class Prop + +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) +annotation class Both + +data class Foo( + @NoTarget @Param @Prop @Both val p1: Int, + @param:NoTarget @param:Both val p2: String, + @property:NoTarget @property:Both val p3: Boolean, +) \ No newline at end of file diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotation.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotation.kt index bcc395e3dc8..86483b2cfd4 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotation.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotation.kt @@ -36,6 +36,8 @@ abstract class FirAnnotation : FirExpression() { abstract override fun replaceAnnotations(newAnnotations: List) + abstract fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) + abstract fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) abstract fun replaceArgumentMapping(newArgumentMapping: FirAnnotationArgumentMapping) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotationCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotationCall.kt index e6e6b101960..76520b6e7b0 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotationCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirAnnotationCall.kt @@ -40,6 +40,8 @@ abstract class FirAnnotationCall : FirAnnotation(), FirCall, FirResolvable { abstract override fun replaceAnnotations(newAnnotations: List) + abstract override fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) + abstract override fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) abstract override fun replaceTypeArguments(newTypeArguments: List) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirErrorAnnotationCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirErrorAnnotationCall.kt index 97910ac15bd..51258732044 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirErrorAnnotationCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirErrorAnnotationCall.kt @@ -43,6 +43,8 @@ abstract class FirErrorAnnotationCall : FirAnnotationCall(), FirDiagnosticHolder abstract override fun replaceAnnotations(newAnnotations: List) + abstract override fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) + abstract override fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) abstract override fun replaceTypeArguments(newTypeArguments: List) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationCallImpl.kt index 91b0b9c523a..8a6817f233b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationCallImpl.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty internal class FirAnnotationCallImpl( override val source: KtSourceElement?, - override val useSiteTarget: AnnotationUseSiteTarget?, + override var useSiteTarget: AnnotationUseSiteTarget?, override var annotationTypeRef: FirTypeRef, override var typeArguments: MutableOrEmptyList, override var argumentList: FirArgumentList, @@ -77,6 +77,10 @@ internal class FirAnnotationCallImpl( override fun replaceAnnotations(newAnnotations: List) {} + override fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) { + useSiteTarget = newUseSiteTarget + } + override fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) { annotationTypeRef = newAnnotationTypeRef } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationImpl.kt index 826d104362c..885b3d70102 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirAnnotationImpl.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty internal class FirAnnotationImpl( override val source: KtSourceElement?, - override val useSiteTarget: AnnotationUseSiteTarget?, + override var useSiteTarget: AnnotationUseSiteTarget?, override var annotationTypeRef: FirTypeRef, override var argumentMapping: FirAnnotationArgumentMapping, override var typeArguments: MutableOrEmptyList, @@ -63,6 +63,10 @@ internal class FirAnnotationImpl( override fun replaceAnnotations(newAnnotations: List) {} + override fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) { + useSiteTarget = newUseSiteTarget + } + override fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) { annotationTypeRef = newAnnotationTypeRef } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirErrorAnnotationCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirErrorAnnotationCallImpl.kt index 9e453c6a3e1..fa887772a84 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirErrorAnnotationCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirErrorAnnotationCallImpl.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty internal class FirErrorAnnotationCallImpl( override val source: KtSourceElement?, - override val useSiteTarget: AnnotationUseSiteTarget?, + override var useSiteTarget: AnnotationUseSiteTarget?, override var annotationTypeRef: FirTypeRef, override var typeArguments: MutableOrEmptyList, override var argumentList: FirArgumentList, @@ -79,6 +79,10 @@ internal class FirErrorAnnotationCallImpl( override fun replaceAnnotations(newAnnotations: List) {} + override fun replaceUseSiteTarget(newUseSiteTarget: AnnotationUseSiteTarget?) { + useSiteTarget = newUseSiteTarget + } + override fun replaceAnnotationTypeRef(newAnnotationTypeRef: FirTypeRef) { annotationTypeRef = newAnnotationTypeRef } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 22626ddcd73..56217a74501 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -519,7 +519,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild } annotation.configure { - +field("useSiteTarget", annotationUseSiteTargetType, nullable = true) + +field("useSiteTarget", annotationUseSiteTargetType, nullable = true, withReplace = true) +field("annotationTypeRef", typeRef, withReplace = true).withTransform() +field("argumentMapping", annotationArgumentMapping, withReplace = true) +typeArguments.withTransform() diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt index 6073e2333bc..5d63f8d7cf3 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt @@ -28,7 +28,7 @@ object KotlinStubVersions { // Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed // or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder). // Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files). - private const val BINARY_STUB_VERSION = 90 + private const val BINARY_STUB_VERSION = 91 // Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile) // Increasing this version will lead to reindexing of all classfiles. diff --git a/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.fir.txt b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.fir.txt new file mode 100644 index 00000000000..166059ccc5a --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.fir.txt @@ -0,0 +1,48 @@ +FILE: annotationsOnDataClassCopy.kt + public final annotation class NoTarget : R|kotlin/Annotation| { + public constructor(): R|NoTarget| { + super() + } + + } + @R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|)) public final annotation class Param : R|kotlin/Annotation| { + public constructor(): R|Param| { + super() + } + + } + @R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|)) public final annotation class Prop : R|kotlin/Annotation| { + public constructor(): R|Prop| { + super() + } + + } + @R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|)) public final annotation class Both : R|kotlin/Annotation| { + public constructor(): R|Both| { + super() + } + + } + public final data class Foo : R|kotlin/Any| { + public constructor(@R|NoTarget|() @R|Param|() @R|Both|() p1: R|kotlin/Int|, @CONSTRUCTOR_PARAMETER:R|NoTarget|() @CONSTRUCTOR_PARAMETER:R|Both|() p2: R|kotlin/String|, p3: R|kotlin/Boolean|): R|Foo| { + super() + } + + @R|Prop|() public final val p1: R|kotlin/Int| = R|/p1| + public get(): R|kotlin/Int| + + public final val p2: R|kotlin/String| = R|/p2| + public get(): R|kotlin/String| + + @PROPERTY:R|NoTarget|() @PROPERTY:R|Both|() public final val p3: R|kotlin/Boolean| = R|/p3| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|kotlin/Int| + + public final operator fun component2(): R|kotlin/String| + + public final operator fun component3(): R|kotlin/Boolean| + + public final fun copy(@R|NoTarget|() @R|Param|() @R|Both|() p1: R|kotlin/Int| = this@R|/Foo|.R|/Foo.p1|, @R|NoTarget|() @R|Both|() p2: R|kotlin/String| = this@R|/Foo|.R|/Foo.p2|, p3: R|kotlin/Boolean| = this@R|/Foo|.R|/Foo.p3|): R|Foo| + + } diff --git a/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt new file mode 100644 index 00000000000..7cf3104f38d --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// FIR_DUMP + +annotation class NoTarget + +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class Param + +@Target(AnnotationTarget.PROPERTY) +annotation class Prop + +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) +annotation class Both + +data class Foo( + @NoTarget @Param @Prop @Both val p1: Int, + @param:NoTarget @param:Both val p2: String, + @property:NoTarget @property:Both val p3: Boolean, +) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.txt b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.txt new file mode 100644 index 00000000000..5a0b10897f7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.txt @@ -0,0 +1,44 @@ +package + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER}) public final annotation class Both : kotlin.Annotation { + public constructor Both() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final data class Foo { + public constructor Foo(/*0*/ @NoTarget @Param @Both p1: kotlin.Int, /*1*/ @NoTarget @Both p2: kotlin.String, /*2*/ p3: kotlin.Boolean) + @Prop public final val p1: kotlin.Int + public final val p2: kotlin.String + @NoTarget @Both public final val p3: kotlin.Boolean + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final operator /*synthesized*/ fun component2(): kotlin.String + public final operator /*synthesized*/ fun component3(): kotlin.Boolean + public final /*synthesized*/ fun copy(/*0*/ @NoTarget @Param @Both p1: kotlin.Int = ..., /*1*/ @NoTarget @Both p2: kotlin.String = ..., /*2*/ p3: kotlin.Boolean = ...): Foo + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final annotation class NoTarget : kotlin.Annotation { + public constructor NoTarget() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.VALUE_PARAMETER}) public final annotation class Param : kotlin.Annotation { + public constructor Param() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY}) public final annotation class Prop : kotlin.Annotation { + public constructor Prop() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index fcee0cf4729..404715f3cc1 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -1446,6 +1446,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt"); } + @Test + @TestMetadata("annotationsOnDataClassCopy.kt") + public void testAnnotationsOnDataClassCopy() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/annotationsOnDataClassCopy.kt"); + } + @Test @TestMetadata("annotationsOnLambdaAsCallArgument.kt") public void testAnnotationsOnLambdaAsCallArgument() throws Exception {