KT-3722: Write correct generic type information for generated fields

#KT-3722 Fixed
This commit is contained in:
Mikhael Bogdanov
2013-06-27 13:29:19 +04:00
parent a37be3c205
commit 8cd1880805
6 changed files with 171 additions and 3 deletions
@@ -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) {
@@ -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();
@@ -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,
@@ -0,0 +1,75 @@
//test for KT-3722 Write correct generic type information for generated fields
import kotlin.properties.Delegates
class Z<T> {
}
class TParam {
}
class Zout<out T> {
}
class Zin<in T> {
}
class Test<T>(val constructorProperty: T) {
val classField1 : Z<T>? = null
val classField2 : Z<String>? = null
val classField3 : Zout<String>? = null
val classField4 : Zin<TParam>? = null
val delegates : Z<TParam>? by Delegates.lazy {Z<TParam>()}
}
fun box(): String {
val clz = javaClass<Test<*>>()
val constructorProperty = clz.getDeclaredField("constructorProperty");
if (constructorProperty.getGenericType().toString() != "T")
return "fail0: " + constructorProperty.getGenericType();
val classField = clz.getDeclaredField("classField1");
if (classField.getGenericType().toString() != "Z<T>")
return "fail1:" + classField.getGenericType();
val classField2 = clz.getDeclaredField("classField2");
if (classField2.getGenericType().toString() != "Z<java.lang.String>")
return "fail2:" + classField2.getGenericType();
val classField3 = clz.getDeclaredField("classField3");
if (classField3.getGenericType().toString() != "Zout<? extends java.lang.String>")
return "fail3:" + classField3.getGenericType();
val classField4 = clz.getDeclaredField("classField4");
if (classField4.getGenericType().toString() != "Zin<? super TParam>")
return "fail4:" + classField4.getGenericType();
val classField5 = clz.getDeclaredField("delegates\$delegate");
if (classField5.getGenericType().toString() != "kotlin.properties.ReadOnlyProperty<? super java.lang.Object, ? extends Z<TParam>>")
return "fail5:" + classField5.getGenericType();
return "OK"
}
@@ -0,0 +1,60 @@
class Z<T> {}
class TParam {}
class Zout<out T> {}
class Zin<in T> {}
class Params(val methodIndex: Int, val paramClass: Class<*>, val expectedReturnType: String, val expecedParamType: String)
class Test<T, out X, in Y>() {
fun test1(p: T): T? = null
fun test2(p: Z<T>): Z<T>? = null
fun test3(p: Z<String>): Z<String>? = null
fun test4(p: X): Zout<out String>? = null
fun test5(p: Y): Zin<in TParam>? = null
}
fun box(): String {
val clz = javaClass<Test<*, *, *>>()
val params = listOf(
Params(1, javaClass<Any>(), "T", "T"),
Params(2, javaClass<Z<*>>(), "Z<T>", "Z<T>"),
Params(3, javaClass<Z<*>>(), "Z<java.lang.String>", "Z<java.lang.String>"),
Params(4, javaClass<Any>(), "Zout<? extends java.lang.String>", "X"),
Params(5, javaClass<Any>(), "Zin<? super TParam>", "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"
}
@@ -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");