Do not generate annotations of method parameters on its $default synthetic method
#KT-7892 Fixed
This commit is contained in:
@@ -168,7 +168,8 @@ public class FunctionCodegen {
|
|||||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
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) {
|
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
|
||||||
generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
|
generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
|
||||||
@@ -215,21 +216,10 @@ public class FunctionCodegen {
|
|||||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
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(
|
private void generateParameterAnnotations(
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
@NotNull MethodVisitor mv,
|
@NotNull MethodVisitor mv,
|
||||||
@NotNull JvmMethodSignature jvmSignature,
|
@NotNull JvmMethodSignature jvmSignature
|
||||||
boolean recordParametersIndices
|
|
||||||
) {
|
) {
|
||||||
Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
|
Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
|
||||||
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
|
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
|
||||||
@@ -244,9 +234,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
if (kind == JvmMethodParameterKind.VALUE) {
|
if (kind == JvmMethodParameterKind.VALUE) {
|
||||||
ValueParameterDescriptor parameter = iterator.next();
|
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());
|
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,7 +601,9 @@ public class FunctionCodegen {
|
|||||||
getThrownExceptions(functionDescriptor, typeMapper)
|
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 (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
if (this.owner instanceof PackageFacadeContext) {
|
if (this.owner instanceof PackageFacadeContext) {
|
||||||
|
|||||||
+11
-18
@@ -1,43 +1,36 @@
|
|||||||
import java.lang.annotation.*
|
import java.lang.annotation.*
|
||||||
import kotlin.reflect.jvm.java
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
Retention(RetentionPolicy.RUNTIME)
|
Retention(RetentionPolicy.RUNTIME)
|
||||||
annotation class Ann(val x: Int)
|
annotation class Ann(val x: Int)
|
||||||
class A {
|
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<out Annotation>.ann() = filterIsInstance<Ann>()
|
fun test(name: String, annotations: Array<out Annotation>) {
|
||||||
|
assertEquals(1, annotations.filterIsInstance<Ann>().single().x, "$name[0]")
|
||||||
fun test(name: String, annotations: Array<out Annotation>, parameters: Array<out Array<out Annotation>>) {
|
|
||||||
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 {
|
fun box(): String {
|
||||||
val foo = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo" }
|
val foo = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo" }
|
||||||
test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations())
|
test("foo", foo.getDeclaredAnnotations())
|
||||||
|
|
||||||
val fooDefault = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo\$default" }
|
val fooDefault = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo\$default" }
|
||||||
test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations())
|
test("foo", foo.getDeclaredAnnotations())
|
||||||
|
|
||||||
val (secondary, secondaryDefault) = javaClass<A>().getDeclaredConstructors().partition { it.getParameterTypes().size() == 3 }
|
val (secondary, secondaryDefault) = javaClass<A>().getDeclaredConstructors().partition { it.getParameterTypes().size() == 3 }
|
||||||
|
|
||||||
test("secondary", secondary[0].getDeclaredAnnotations(), secondary[0].getParameterAnnotations())
|
test("secondary", secondary[0].getDeclaredAnnotations())
|
||||||
test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations(), secondaryDefault[0].getParameterAnnotations())
|
test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations())
|
||||||
|
|
||||||
val (primary, primaryDefault) = javaClass<B>().getConstructors().partition { it.getParameterTypes().size() == 3 }
|
val (primary, primaryDefault) = javaClass<B>().getConstructors().partition { it.getParameterTypes().size() == 3 }
|
||||||
|
|
||||||
test("primary", primary[0].getDeclaredAnnotations(), primary[0].getParameterAnnotations())
|
test("primary", primary[0].getDeclaredAnnotations())
|
||||||
test("secondary\$default", primaryDefault[0].getDeclaredAnnotations(), primaryDefault[0].getParameterAnnotations())
|
test("primary\$default", primaryDefault[0].getDeclaredAnnotations())
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -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;
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
enum class K(private val default: String = "default") {
|
||||||
|
ENTRY()
|
||||||
|
}
|
||||||
+28
@@ -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<test.K> {
|
||||||
|
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<test.K>
|
||||||
|
}
|
||||||
+15
@@ -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")
|
@TestMetadata("compiler/testData/compileJavaAgainstKotlin/method")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user