diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index cd37b9d7475..ffc855931bc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -169,9 +169,7 @@ public class FunctionCodegen { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod); } - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType()); - - generateParameterAnnotations(functionDescriptor, mv, jvmSignature); + generateAnnotationsForMethod(functionDescriptor, asmMethod, mv, true); if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature); @@ -218,10 +216,21 @@ public class FunctionCodegen { methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext); } + private void generateAnnotationsForMethod( + @NotNull FunctionDescriptor functionDescriptor, + Method asmMethod, + MethodVisitor mv, + boolean recordParametersIndices + ) { + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType()); + generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor), recordParametersIndices); + } + private void generateParameterAnnotations( @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodVisitor mv, - @NotNull JvmMethodSignature jvmSignature + @NotNull JvmMethodSignature jvmSignature, + boolean recordParametersIndices ) { Iterator iterator = functionDescriptor.getValueParameters().iterator(); List kotlinParameterTypes = jvmSignature.getValueParameters(); @@ -236,7 +245,9 @@ public class FunctionCodegen { if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = iterator.next(); - v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i); + if (recordParametersIndices) { + v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i); + } AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType()); } } @@ -603,6 +614,8 @@ public class FunctionCodegen { getThrownExceptions(functionDescriptor, typeMapper) ); + generateAnnotationsForMethod(functionDescriptor, defaultMethod, mv, false); + if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (this.owner instanceof PackageFacadeContext) { mv.visitCode(); diff --git a/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt b/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt new file mode 100644 index 00000000000..54d179a5831 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt @@ -0,0 +1,43 @@ +import java.lang.annotation.* +import kotlin.reflect.jvm.java +import kotlin.test.assertEquals + +Retention(RetentionPolicy.RUNTIME) +annotation class Ann(val x: Int) +class A { + Ann(1) fun foo(Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) {} + + Ann(1) constructor(Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) +} + +class B [Ann(1)] (Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) {} + +fun Array.ann() = filterIsInstance() + +fun test(name: String, annotations: Array, parameters: Array>) { + assertEquals(1, annotations.ann()[0].x, "$name[0]") + + assertEquals(2, parameters[0].ann()[0].x, "$name-param[0]") + assertEquals(0, parameters[1].ann().size(), "$name-param[1]") + assertEquals(3, parameters[2].ann()[0].x, "$name-param[2]") +} + +fun box(): String { + val foo = javaClass().getDeclaredMethods().first { it.getName() == "foo" } + test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations()) + + val fooDefault = javaClass().getDeclaredMethods().first { it.getName() == "foo\$default" } + test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations()) + + val (secondary, secondaryDefault) = javaClass().getDeclaredConstructors().partition { it.getParameterTypes().size() == 3 } + + test("secondary", secondary[0].getDeclaredAnnotations(), secondary[0].getParameterAnnotations()) + test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations(), secondaryDefault[0].getParameterAnnotations()) + + val (primary, primaryDefault) = javaClass().getConstructors().partition { it.getParameterTypes().size() == 3 } + + test("primary", primary[0].getDeclaredAnnotations(), primary[0].getParameterAnnotations()) + test("secondary\$default", primaryDefault[0].getDeclaredAnnotations(), primaryDefault[0].getParameterAnnotations()) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index f47c2eea510..94602274ac0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -49,6 +49,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("annotationsOnDefault.kt") + public void testAnnotationsOnDefault() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("defaultParameterValues.kt") public void testDefaultParameterValues() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/defaultParameterValues.kt");