Fixed KT-2543 Constructor and function parameter annotations are ignored

This commit is contained in:
Natalia.Ukhorskaya
2012-08-08 16:39:12 +04:00
parent 4f68b926fb
commit 16bcc7967e
5 changed files with 86 additions and 2 deletions
@@ -233,4 +233,13 @@ public abstract class AnnotationCodegen {
}
};
}
public static AnnotationCodegen forParameter(final int parameter, final MethodVisitor mv, JetTypeMapper mapper) {
return new AnnotationCodegen(mapper) {
@Override
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
return mv.visitParameterAnnotation(parameter, descr, visible);
}
};
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.asm4.FieldVisitor;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.asm4.Type;
@@ -117,7 +118,8 @@ public abstract class ClassBodyCodegen {
modifiers |= Opcodes.ACC_VOLATILE;
}
Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, null);
FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, null);
AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor);
}
}
else {
@@ -170,8 +170,9 @@ public class FunctionCodegen {
av.visitEnd();
}
for(int i = 0; i != paramDescrs.size(); ++i) {
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(parameterDescriptor);
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
av.writeName(parameterDescriptor.getName().getName());
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
av.writeNullable(parameterDescriptor.getType().isNullable());
@@ -594,6 +594,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(valueParameter);
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
jetValueParameterAnnotation.writeName(valueParameter.getName().getName());
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
@@ -60,6 +60,77 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
}
public void testAnnotationForParamInGlobalFunction() throws NoSuchFieldException, NoSuchMethodException {
loadText("fun x([Deprecated] i: Int) {}");
Class aClass = generateNamespaceClass();
Method x = aClass.getMethod("x", int.class);
assertNotNull(x);
// Get annotations for first parameter
Annotation[] annotations = x.getParameterAnnotations()[0];
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testAnnotationForParamInLocalFunction() throws NoSuchFieldException, NoSuchMethodException {
loadText("class A() { fun x([Deprecated] i: Int) {}}");
Class aClass = generateClass("A");
Method x = aClass.getMethod("x", int.class);
assertNotNull(x);
// Get annotations for first parameter
Annotation[] annotations = x.getParameterAnnotations()[0];
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testParamInConstructor() throws NoSuchFieldException, NoSuchMethodException {
loadText("class A ([Deprecated] x: Int) {}");
Class aClass = generateClass("A");
Constructor constructor = aClass.getDeclaredConstructor(int.class);
assertNotNull(constructor);
// Get annotations for first parameter
Annotation[] annotations = constructor.getParameterAnnotations()[0];
assertNotNull(getDeprecatedAnnotationFromList(annotations));
}
public void testPropFieldInConstructor() throws NoSuchFieldException, NoSuchMethodException {
loadText("class A ([Deprecated] var x: Int) {}");
Class aClass = generateClass("A");
Constructor constructor = aClass.getDeclaredConstructor(int.class);
assertNotNull(constructor);
// Get annotations for first parameter
Annotation[] annotations = constructor.getParameterAnnotations()[0];
assertNotNull(getDeprecatedAnnotationFromList(annotations));
assertNull(aClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
}
public void testAnnotationWithParamForParamInFunction() throws NoSuchFieldException, NoSuchMethodException {
loadText("import java.lang.annotation.*\n" +
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
"fun x(A(\"239\") i: Int) {}");
Class aClass = generateNamespaceClass();
Method x = aClass.getMethod("x", int.class);
assertNotNull(x);
// Get annotations for first parameter
Annotation[] annotations = x.getParameterAnnotations()[0];
Annotation resultAnnotation = null;
for (Annotation annotation : annotations) {
if (annotation.annotationType().getCanonicalName().equals("A")) {
resultAnnotation = annotation;
break;
}
}
assertNotNull(resultAnnotation);
}
private Deprecated getDeprecatedAnnotationFromList(Annotation[] annotations) {
for (Annotation annotation : annotations) {
if (annotation instanceof Deprecated) {
return (Deprecated) annotation;
}
}
return null;
}
public void testConstructor() throws NoSuchFieldException, NoSuchMethodException {
loadText("class A [Deprecated] () {}");
Class aClass = generateClass("A");