diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 6b6e4f81ee9..29d6a119620 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -168,7 +168,8 @@ public class FunctionCodegen { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod); } - generateAnnotationsForMethod(functionDescriptor, asmMethod, mv, true); + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType()); + generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor)); if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature); @@ -215,21 +216,10 @@ 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, - boolean recordParametersIndices + @NotNull JvmMethodSignature jvmSignature ) { Iterator iterator = functionDescriptor.getValueParameters().iterator(); List kotlinParameterTypes = jvmSignature.getValueParameters(); @@ -244,9 +234,7 @@ public class FunctionCodegen { if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = iterator.next(); - if (recordParametersIndices) { - v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i); - } + v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i); AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType()); } } @@ -613,7 +601,9 @@ public class FunctionCodegen { getThrownExceptions(functionDescriptor, typeMapper) ); - generateAnnotationsForMethod(functionDescriptor, defaultMethod, mv, false); + // Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases; + // enum constructors have two additional synthetic parameters which somewhat complicate this task + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType()); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (this.owner instanceof PackageFacadeContext) { diff --git a/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt b/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt index 54d179a5831..3ae2dd93f86 100644 --- a/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt +++ b/compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt @@ -1,43 +1,36 @@ 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) fun foo(x: Int, y: Int = 2, z: Int) {} - Ann(1) constructor(Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) + Ann(1) constructor(x: Int, y: Int = 2, z: Int) } -class B [Ann(1)] (Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) {} +class B @Ann(1) constructor(x: Int, y: Int = 2, 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 test(name: String, annotations: Array) { + assertEquals(1, annotations.filterIsInstance().single().x, "$name[0]") } fun box(): String { val foo = javaClass().getDeclaredMethods().first { it.getName() == "foo" } - test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations()) + test("foo", foo.getDeclaredAnnotations()) val fooDefault = javaClass().getDeclaredMethods().first { it.getName() == "foo\$default" } - test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations()) + test("foo", foo.getDeclaredAnnotations()) 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()) + test("secondary", secondary[0].getDeclaredAnnotations()) + test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations()) 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()) + test("primary", primary[0].getDeclaredAnnotations()) + test("primary\$default", primaryDefault[0].getDeclaredAnnotations()) return "OK" } diff --git a/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.java b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.java new file mode 100644 index 00000000000..e8a7012d315 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.java @@ -0,0 +1,7 @@ +// KT-7892 Parameter with default value in enum's constructor breaks Java compilation + +package test; + +public class DefaultArgumentInEnumConstructor { + static K entry = K.ENTRY; +} diff --git a/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.kt b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.kt new file mode 100644 index 00000000000..08e5ecac9e4 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.kt @@ -0,0 +1,5 @@ +package test + +enum class K(private val default: String = "default") { + ENTRY() +} diff --git a/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.txt b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.txt new file mode 100644 index 00000000000..0b7bea2a192 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.txt @@ -0,0 +1,28 @@ +package test + +public open class DefaultArgumentInEnumConstructor { + public constructor DefaultArgumentInEnumConstructor() + + // Static members + public/*package*/ final var entry: test.K! +} + +internal final enum class K : kotlin.Enum { + public enum entry ENTRY : test.K { + private constructor ENTRY() + invisible_fake final /*fake_override*/ val default: kotlin.String + public final /*fake_override*/ fun compareTo(/*0*/ test.K): kotlin.Int + public final /*fake_override*/ fun name(): kotlin.String + public final /*fake_override*/ fun ordinal(): kotlin.Int + } + + private constructor K(/*0*/ kotlin.String = ...) + private final val default: kotlin.String + public final /*fake_override*/ fun compareTo(/*0*/ test.K): kotlin.Int + public final /*fake_override*/ fun name(): kotlin.String + public final /*fake_override*/ fun ordinal(): kotlin.Int + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.K + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java index bba19e38f59..310d6f16f6e 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileJavaAgainstKotlinTestGenerated.java @@ -122,6 +122,21 @@ public class CompileJavaAgainstKotlinTestGenerated extends AbstractCompileJavaAg } } + @TestMetadata("compiler/testData/compileJavaAgainstKotlin/enum") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Enum extends AbstractCompileJavaAgainstKotlinTest { + public void testAllFilesPresentInEnum() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/compileJavaAgainstKotlin/enum"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("DefaultArgumentInEnumConstructor.kt") + public void testDefaultArgumentInEnumConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/compileJavaAgainstKotlin/enum/DefaultArgumentInEnumConstructor.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/compileJavaAgainstKotlin/method") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)