Fixed KT-2543 Constructor and function parameter annotations are ignored
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user