diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 89fac9e4f7b..96acc8e1dc2 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -166,7 +166,7 @@ class DescriptorSerializer private constructor( val hasAnnotations = hasAnnotations(descriptor) || hasAnnotations(descriptor.backingField) || hasAnnotations(descriptor.delegateField) - val propertyFlags = Flags.getAccessorFlags( + val defaultAccessorFlags = Flags.getAccessorFlags( hasAnnotations, ProtoEnumFlags.visibility(normalizeVisibility(descriptor)), ProtoEnumFlags.modality(descriptor.modality), @@ -177,7 +177,7 @@ class DescriptorSerializer private constructor( if (getter != null) { hasGetter = true val accessorFlags = getAccessorFlags(getter) - if (accessorFlags != propertyFlags) { + if (accessorFlags != defaultAccessorFlags) { builder.getterFlags = accessorFlags } } @@ -186,7 +186,7 @@ class DescriptorSerializer private constructor( if (setter != null) { hasSetter = true val accessorFlags = getAccessorFlags(setter) - if (accessorFlags != propertyFlags) { + if (accessorFlags != defaultAccessorFlags) { builder.setterFlags = accessorFlags } diff --git a/compiler/testData/codegen/box/annotations/annotationsOnNonExistentAccessors.kt b/compiler/testData/codegen/box/annotations/annotationsOnNonExistentAccessors.kt index c7871e0f92c..833f4c5f78a 100644 --- a/compiler/testData/codegen/box/annotations/annotationsOnNonExistentAccessors.kt +++ b/compiler/testData/codegen/box/annotations/annotationsOnNonExistentAccessors.kt @@ -3,25 +3,6 @@ // Please make sure that this test is consistent with the diagnostic test "annotationsTargetingNonExistentAccessor.kt" -// FILE: Temporary.java - -// see https://youtrack.jetbrains.com/issue/KT-25499 - -class Temporary { - public static void checkX2FromStaticsHasAnnotations() { - try { - if (Statics.Companion.getClass().getDeclaredMethod("getX2").getAnnotations().length == 0) { - throw new RuntimeException("there are no annotations"); - } - } - catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } -} - -// FILE: test.kt - import kotlin.reflect.KAnnotatedElement import kotlin.reflect.KProperty @@ -152,9 +133,9 @@ class Statics { check(::x0.getter, annotationExists = false) check(::x1.getter, annotationExists = false) - check(::x2.getter, annotationExists = false) // https://youtrack.jetbrains.com/issue/KT-25499 - check(::x2.setter, annotationExists = false) - check(::x2.setter.parameters.first(), annotationExists = false) + check(::x2.getter, annotationExists = true) + check(::x2.setter, annotationExists = true) + check(::x2.setter.parameters.first(), annotationExists = false /* TODO */) check(::x3.getter, annotationExists = false) @@ -185,7 +166,6 @@ fun box(): String { PrivateProperties(0, "").test() EffetivelyPrivate.test() Statics().test() - Temporary.checkX2FromStaticsHasAnnotations() Delegate().test() return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/annotations/setparam.kt b/compiler/testData/codegen/box/reflection/annotations/setparam.kt new file mode 100644 index 00000000000..7eb284ff0f7 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/annotations/setparam.kt @@ -0,0 +1,21 @@ +// WITH_REFLECT +// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE + +import kotlin.test.assertEquals + +annotation class Ann1 +annotation class Ann2 + +class Foo { + @setparam:Ann1 + var delegate = " " + set(@Ann2 value) {} +} + +fun box(): String { + val setterParameters = Foo::delegate.setter.parameters + assertEquals(2, setterParameters.size) + assertEquals("[]", setterParameters.first().annotations.toString()) + assertEquals("[@Ann2(), @Ann1()]", setterParameters.last().annotations.toString()) + return "OK" +} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt b/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt new file mode 100644 index 00000000000..fa3140be2e8 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt @@ -0,0 +1,18 @@ +package test + +annotation class A(val value: String) +annotation class B(val value: Array) + +interface I { + @A("property") + @get:B(["getter"]) + var propertyAndGetter: Int + + @A("property") + @set:B(["setter"]) + var propertyAndSetter: Int + + @get:A("getter") + @set:B(["setter"]) + var getterAndSetter: Int +} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt b/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt new file mode 100644 index 00000000000..3d5419b0068 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt @@ -0,0 +1,25 @@ +package test + +public final annotation class A : kotlin.Annotation { + /*primary*/ public constructor A(/*0*/ value: kotlin.String) + public final val value: kotlin.String + public final fun (): kotlin.String +} + +public final annotation class B : kotlin.Annotation { + /*primary*/ public constructor B(/*0*/ value: kotlin.Array) + public final val value: kotlin.Array + public final fun (): kotlin.Array +} + +public interface I { + public abstract var getterAndSetter: kotlin.Int + @test.A(value = "getter") public abstract fun (): kotlin.Int + @test.B(value = {"setter"}) public abstract fun (/*0*/ : kotlin.Int): kotlin.Unit + @test.A(value = "property") public abstract var propertyAndGetter: kotlin.Int + @test.B(value = {"getter"}) public abstract fun (): kotlin.Int + public abstract fun (/*0*/ : kotlin.Int): kotlin.Unit + @test.A(value = "property") public abstract var propertyAndSetter: kotlin.Int + public abstract fun (): kotlin.Int + @test.B(value = {"setter"}) public abstract fun (/*0*/ : kotlin.Int): kotlin.Unit +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 0c47e6c8414..e158503d8be 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -17555,6 +17555,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/annotations/retentions.kt"); } + @TestMetadata("setparam.kt") + public void testSetparam() throws Exception { + runTest("compiler/testData/codegen/box/reflection/annotations/setparam.kt"); + } + @TestMetadata("simpleClassAnnotation.kt") public void testSimpleClassAnnotation() throws Exception { runTest("compiler/testData/codegen/box/reflection/annotations/simpleClassAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 348bbd82798..f2c75c9fdbb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17555,6 +17555,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/annotations/retentions.kt"); } + @TestMetadata("setparam.kt") + public void testSetparam() throws Exception { + runTest("compiler/testData/codegen/box/reflection/annotations/setparam.kt"); + } + @TestMetadata("simpleClassAnnotation.kt") public void testSimpleClassAnnotation() throws Exception { runTest("compiler/testData/codegen/box/reflection/annotations/simpleClassAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index e2a1c054f65..48aafbca736 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -17555,6 +17555,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/annotations/retentions.kt"); } + @TestMetadata("setparam.kt") + public void testSetparam() throws Exception { + runTest("compiler/testData/codegen/box/reflection/annotations/setparam.kt"); + } + @TestMetadata("simpleClassAnnotation.kt") public void testSimpleClassAnnotation() throws Exception { runTest("compiler/testData/codegen/box/reflection/annotations/simpleClassAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index bc8b1b96f44..920dcc92396 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -2147,6 +2147,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java index f14f5b3294c..4d916d8b7de 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadKotlinWithTypeTableTestGenerated.java @@ -491,6 +491,11 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java index 9f61c6d65aa..70406512b5b 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java @@ -2147,6 +2147,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index 0ad2a5271f0..e817011d63a 100644 --- a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -493,6 +493,11 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt index 5407d46c34b..dcb91f2c92f 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt @@ -67,11 +67,20 @@ class MemberDeserializer(private val c: DeserializationContext) { } ) + // Per documentation on Property.getter_flags in metadata.proto, if an accessor flags field is absent, its value should be computed + // by taking hasAnnotations/visibility/modality from property flags, and using false for the rest + val defaultAccessorFlags = Flags.getAccessorFlags( + Flags.HAS_ANNOTATIONS.get(flags), + Flags.VISIBILITY.get(flags), + Flags.MODALITY.get(flags), + false, false, false + ) + val getter = if (hasGetter) { - val getterFlags = proto.getterFlags - val isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags) - val isExternal = proto.hasGetterFlags() && Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags) - val isInline = proto.hasGetterFlags() && Flags.IS_INLINE_ACCESSOR.get(getterFlags) + val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags + val isNotDefault = Flags.IS_NOT_DEFAULT.get(getterFlags) + val isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(getterFlags) + val isInline = Flags.IS_INLINE_ACCESSOR.get(getterFlags) val annotations = getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER) val getter = if (isNotDefault) { PropertyGetterDescriptorImpl( @@ -94,10 +103,10 @@ class MemberDeserializer(private val c: DeserializationContext) { } val setter = if (Flags.HAS_SETTER.get(flags)) { - val setterFlags = proto.setterFlags - val isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags) - val isExternal = proto.hasSetterFlags() && Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags) - val isInline = proto.hasSetterFlags() && Flags.IS_INLINE_ACCESSOR.get(setterFlags) + val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags + val isNotDefault = Flags.IS_NOT_DEFAULT.get(setterFlags) + val isExternal = Flags.IS_EXTERNAL_ACCESSOR.get(setterFlags) + val isInline = Flags.IS_INLINE_ACCESSOR.get(setterFlags) val annotations = getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER) if (isNotDefault) { val setter = PropertySetterDescriptorImpl( diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java index c21753c3862..99cff0f6860 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/LoadJavaClsStubTestGenerated.java @@ -491,6 +491,11 @@ public class LoadJavaClsStubTestGenerated extends AbstractLoadJavaClsStubTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java index 7ef843f6a23..d722931ea6f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java @@ -491,6 +491,11 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/FieldTarget.kt"); } + @TestMetadata("PropertyAndAccessor.kt") + public void testPropertyAndAccessor() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.kt"); + } + @TestMetadata("ReceiverTarget.kt") public void testReceiverTarget() throws Exception { runTest("compiler/testData/loadJava/compiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 6cbef43390d..76a4cd415c7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -15695,6 +15695,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/annotations/retentions.kt"); } + @TestMetadata("setparam.kt") + public void testSetparam() throws Exception { + runTest("compiler/testData/codegen/box/reflection/annotations/setparam.kt"); + } + @TestMetadata("simpleClassAnnotation.kt") public void testSimpleClassAnnotation() throws Exception { runTest("compiler/testData/codegen/box/reflection/annotations/simpleClassAnnotation.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 920d9ed2bf5..eaa4aa6b588 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -16760,6 +16760,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/annotations/retentions.kt"); } + @TestMetadata("setparam.kt") + public void testSetparam() throws Exception { + runTest("compiler/testData/codegen/box/reflection/annotations/setparam.kt"); + } + @TestMetadata("simpleClassAnnotation.kt") public void testSimpleClassAnnotation() throws Exception { runTest("compiler/testData/codegen/box/reflection/annotations/simpleClassAnnotation.kt");