From 16bcc7967e270aa6a33b11b833d550016e01ffee Mon Sep 17 00:00:00 2001 From: "Natalia.Ukhorskaya" Date: Wed, 8 Aug 2012 16:39:12 +0400 Subject: [PATCH] Fixed KT-2543 Constructor and function parameter annotations are ignored --- .../jet/codegen/AnnotationCodegen.java | 9 +++ .../jet/codegen/ClassBodyCodegen.java | 4 +- .../jet/codegen/FunctionCodegen.java | 3 +- .../codegen/ImplementationBodyCodegen.java | 1 + .../jet/codegen/AnnotationGenTest.java | 71 +++++++++++++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index fc649982437..ade7c42458c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -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); + } + }; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 840c48b01fa..0c64361d3fc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -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 { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 0920d789efb..a745a601f41 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -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()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index c03ef9aee18..36e3b05e7d6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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()); diff --git a/compiler/tests/org/jetbrains/jet/codegen/AnnotationGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/AnnotationGenTest.java index 26b983ab965..a571db0ef1b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/AnnotationGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/AnnotationGenTest.java @@ -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");