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;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.asm4.FieldVisitor;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Opcodes;
|
import org.jetbrains.asm4.Opcodes;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
@@ -117,7 +118,8 @@ public abstract class ClassBodyCodegen {
|
|||||||
modifiers |= Opcodes.ACC_VOLATILE;
|
modifiers |= Opcodes.ACC_VOLATILE;
|
||||||
}
|
}
|
||||||
Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
|
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 {
|
else {
|
||||||
|
|||||||
@@ -170,8 +170,9 @@ public class FunctionCodegen {
|
|||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||||
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
|
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
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.writeName(parameterDescriptor.getName().getName());
|
||||||
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
|
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
|
||||||
av.writeNullable(parameterDescriptor.getType().isNullable());
|
av.writeNullable(parameterDescriptor.getType().isNullable());
|
||||||
|
|||||||
@@ -594,6 +594,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
||||||
|
AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(valueParameter);
|
||||||
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
||||||
jetValueParameterAnnotation.writeName(valueParameter.getName().getName());
|
jetValueParameterAnnotation.writeName(valueParameter.getName().getName());
|
||||||
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
|
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
|
||||||
|
|||||||
@@ -60,6 +60,77 @@ public class AnnotationGenTest extends CodegenTestCase {
|
|||||||
assertNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
|
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 {
|
public void testConstructor() throws NoSuchFieldException, NoSuchMethodException {
|
||||||
loadText("class A [Deprecated] () {}");
|
loadText("class A [Deprecated] () {}");
|
||||||
Class aClass = generateClass("A");
|
Class aClass = generateClass("A");
|
||||||
|
|||||||
Reference in New Issue
Block a user