From 8cd1880805e0468f6152e2455752dde5b21a7323 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 27 Jun 2013 13:29:19 +0400 Subject: [PATCH] KT-3722: Write correct generic type information for generated fields #KT-3722 Fixed --- .../jet/codegen/PropertyCodegen.java | 2 +- .../signature/BothSignatureWriter.java | 18 ++++- .../jet/codegen/state/JetTypeMapper.java | 9 +++ .../fullJdk/genericBackingFieldSignature.kt | 75 +++++++++++++++++++ .../fullJdk/genericMethodSignature.kt | 60 +++++++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 10 +++ 6 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/fullJdk/genericBackingFieldSignature.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/fullJdk/genericMethodSignature.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index c30a10423c6..7ef0cf02f4f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -162,7 +162,7 @@ public class PropertyCodegen extends GenerationStateAware { String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate); return builder.newField(element, modifiers, name, type.getDescriptor(), - null, defaultValue); + typeMapper.mapFieldSignature(jetType), defaultValue); } private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/signature/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/signature/BothSignatureWriter.java index de3de631c4e..1b76b16aa17 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/signature/BothSignatureWriter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/signature/BothSignatureWriter.java @@ -43,7 +43,8 @@ public class BothSignatureWriter { public enum Mode { METHOD(CheckSignatureAdapter.METHOD_SIGNATURE), - CLASS(CheckSignatureAdapter.CLASS_SIGNATURE),; + CLASS(CheckSignatureAdapter.CLASS_SIGNATURE), + TYPE(CheckSignatureAdapter.TYPE_SIGNATURE); private final int asmType; @@ -61,6 +62,9 @@ public class BothSignatureWriter { RETURN_TYPE, METHOD_END, + FIELD, + FIELD_END, + SUPERS, CLASS_END, } @@ -341,6 +345,16 @@ public class BothSignatureWriter { checkState(State.PARAMETERS); } + public void writeFieldTypeStart() { + transitionState(State.START, State.FIELD); + jetSignatureWriter = new JetSignatureWriter(); + } + + public void writeFieldTypeEnd() { + jetSignatureWriter = null; + transitionState(State.FIELD, State.FIELD_END); + } + public void writeParameterType(JvmMethodParameterKind parameterKind) { transitionState(State.PARAMETERS, State.PARAMETER); @@ -486,7 +500,7 @@ public class BothSignatureWriter { @Nullable public String makeJavaGenericSignature() { - if (state != State.METHOD_END && state != State.CLASS_END) { + if (state != State.METHOD_END && state != State.CLASS_END && state != State.FIELD_END) { throw new IllegalStateException(); } checkTopLevel(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 119d1e12ce3..cb1dbc1145a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -636,6 +636,15 @@ public class JetTypeMapper extends BindingTraceAware { return signatureVisitor.makeJvmMethodSignature(methodName); } + @Nullable + public String mapFieldSignature(@NotNull JetType backingFieldType) { + BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE, true); + signatureVisitor.writeFieldTypeStart(); + mapType(backingFieldType, signatureVisitor, JetTypeMapperMode.VALUE); + signatureVisitor.writeFieldTypeEnd(); + return signatureVisitor.makeJavaGenericSignature(); + } + private void writeThisIfNeeded( @NotNull CallableMemberDescriptor descriptor, @NotNull OwnerKind kind, diff --git a/compiler/testData/codegen/boxWithStdlib/fullJdk/genericBackingFieldSignature.kt b/compiler/testData/codegen/boxWithStdlib/fullJdk/genericBackingFieldSignature.kt new file mode 100644 index 00000000000..83db5f3f65f --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/fullJdk/genericBackingFieldSignature.kt @@ -0,0 +1,75 @@ +//test for KT-3722 Write correct generic type information for generated fields +import kotlin.properties.Delegates + +class Z { + +} + +class TParam { + +} + +class Zout { + +} + +class Zin { + +} + + +class Test(val constructorProperty: T) { + + val classField1 : Z? = null + + val classField2 : Z? = null + + val classField3 : Zout? = null + + val classField4 : Zin? = null + + val delegates : Z? by Delegates.lazy {Z()} + + +} + +fun box(): String { + val clz = javaClass>() + + val constructorProperty = clz.getDeclaredField("constructorProperty"); + + if (constructorProperty.getGenericType().toString() != "T") + return "fail0: " + constructorProperty.getGenericType(); + + + val classField = clz.getDeclaredField("classField1"); + + if (classField.getGenericType().toString() != "Z") + return "fail1:" + classField.getGenericType(); + + + val classField2 = clz.getDeclaredField("classField2"); + + if (classField2.getGenericType().toString() != "Z") + return "fail2:" + classField2.getGenericType(); + + + val classField3 = clz.getDeclaredField("classField3"); + + if (classField3.getGenericType().toString() != "Zout") + return "fail3:" + classField3.getGenericType(); + + + val classField4 = clz.getDeclaredField("classField4"); + + if (classField4.getGenericType().toString() != "Zin") + return "fail4:" + classField4.getGenericType(); + + val classField5 = clz.getDeclaredField("delegates\$delegate"); + + if (classField5.getGenericType().toString() != "kotlin.properties.ReadOnlyProperty>") + return "fail5:" + classField5.getGenericType(); + + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/fullJdk/genericMethodSignature.kt b/compiler/testData/codegen/boxWithStdlib/fullJdk/genericMethodSignature.kt new file mode 100644 index 00000000000..1a82d49b589 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/fullJdk/genericMethodSignature.kt @@ -0,0 +1,60 @@ +class Z {} + +class TParam {} + +class Zout {} + +class Zin {} + +class Params(val methodIndex: Int, val paramClass: Class<*>, val expectedReturnType: String, val expecedParamType: String) + +class Test() { + + fun test1(p: T): T? = null + + fun test2(p: Z): Z? = null + + fun test3(p: Z): Z? = null + + fun test4(p: X): Zout? = null + + fun test5(p: Y): Zin? = null +} + +fun box(): String { + val clz = javaClass>() + + val params = listOf( + Params(1, javaClass(), "T", "T"), + Params(2, javaClass>(), "Z", "Z"), + Params(3, javaClass>(), "Z", "Z"), + Params(4, javaClass(), "Zout", "X"), + Params(5, javaClass(), "Zin", "Y") + ) + + + var result: String = "" + for(p in params) { + val fail = test(clz, p.methodIndex, p.paramClass, p.expectedReturnType, p.expecedParamType) + if (fail != "OK") { + result += fail + "\n"; + } + } + + return if (result.isEmpty()) "OK" else result; + +} + +fun test(clazz: Class<*>, methodIndex: Int, paramClass: Class<*>, expectedReturn : String, expectedParam : String): String { + val method = clazz.getDeclaredMethod("test$methodIndex", paramClass)!!; + + if (method.getGenericReturnType().toString() != expectedReturn) + return "fail$methodIndex: " + method.getGenericReturnType(); + + val test1Param = method.getGenericParameterTypes()!![0]; + + if (test1Param.toString() != expectedParam) + return "fail${methodIndex}_param: " + test1Param; + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index e187758dbe1..17e6c9b373d 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -336,6 +336,16 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithStdlib/fullJdk"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("genericBackingFieldSignature.kt") + public void testGenericBackingFieldSignature() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/fullJdk/genericBackingFieldSignature.kt"); + } + + @TestMetadata("genericMethodSignature.kt") + public void testGenericMethodSignature() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/fullJdk/genericMethodSignature.kt"); + } + @TestMetadata("ifInWhile.kt") public void testIfInWhile() throws Exception { doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/fullJdk/ifInWhile.kt");