diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 7cd6f853322..f64b2a53581 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.AnnotationChecker; +import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker; import org.jetbrains.kotlin.resolve.constants.*; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; @@ -166,10 +167,17 @@ public abstract class AnnotationCodegen { if (isInvisibleFromTheOutside(descriptor)) return; if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return; + // No need to annotate annotation methods since they're always non-null + if (descriptor instanceof PropertyGetterDescriptor && + DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) { + return; + } + if (returnType != null && !AsmUtil.isPrimitive(returnType)) { generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent); } } + if (unwrapped instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped; if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index f4d1f62119e..d3588d8d098 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -232,7 +232,7 @@ public class FunctionCodegen { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod); } - generateMethodAnnotations(functionDescriptor, asmMethod, mv); + generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper); generateParameterAnnotations(functionDescriptor, mv, jvmSignature); GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0); @@ -474,14 +474,6 @@ public class FunctionCodegen { ); } - private void generateMethodAnnotations( - @NotNull FunctionDescriptor functionDescriptor, - Method asmMethod, - MethodVisitor mv - ) { - generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper); - } - public static void generateMethodAnnotations( @NotNull FunctionDescriptor functionDescriptor, Method asmMethod, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 73fc552281d..99836fdf66e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -266,15 +266,20 @@ public class PropertyCodegen { @Nullable FunctionDescriptor expectedAnnotationConstructor ) { JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor); - String name = parameter.getName(); - if (name == null) return; + Method asmMethod = signature.getAsmMethod(); MethodVisitor mv = v.newMethod( - JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor), ACC_PUBLIC | ACC_ABSTRACT, name, - signature.getAsmMethod().getDescriptor(), + JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor), + ACC_PUBLIC | ACC_ABSTRACT, + asmMethod.getName(), + asmMethod.getDescriptor(), signature.getGenericsSignature(), null ); + PropertyGetterDescriptor getter = descriptor.getGetter(); + assert getter != null : "Annotation property should have a getter: " + descriptor; + FunctionCodegen.generateMethodAnnotations(getter, asmMethod, mv, memberCodegen, typeMapper); + KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor); if (defaultValue != null) { ConstantValue constant = ExpressionCodegen.getCompileTimeConstant( diff --git a/compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt b/compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt new file mode 100644 index 00000000000..aa997e27071 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME + +import kotlin.test.assertEquals + +annotation class Name(val value: String) + +annotation class Anno( + @get:Name("O") val o: String, + @get:Name("K") val k: String +) + +fun box(): String { + val ms = Anno::class.java.declaredMethods + + return (ms.single { it.name == "o" }.annotations.single() as Name).value + + (ms.single { it.name == "k" }.annotations.single() as Name).value +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3a1d9a30778..d608e2fe4b8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -41,6 +41,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("annotatedAnnotationParameter.kt") + public void testAnnotatedAnnotationParameter() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt"); + } + @TestMetadata("annotatedEnumEntry.kt") public void testAnnotatedEnumEntry() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c553aa90ee9..9ecc9c0efc9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -46,6 +46,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("annotatedAnnotationParameter.kt") + public void testAnnotatedAnnotationParameter() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt"); + } + @TestMetadata("annotatedEnumEntry.kt") public void testAnnotatedEnumEntry() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index fbbf0cc7bfb..19ecb9a9964 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -41,6 +41,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("annotatedAnnotationParameter.kt") + public void testAnnotatedAnnotationParameter() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt"); + } + @TestMetadata("annotatedEnumEntry.kt") public void testAnnotatedEnumEntry() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");