diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 16 | ||||
-rw-r--r-- | test/files/jvm/annotations.check | 11 | ||||
-rw-r--r-- | test/files/jvm/annotations.scala | 31 |
3 files changed, 46 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 92dd368ac5..f503a797bb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1330,7 +1330,9 @@ trait Typers { self: Analyzer => val value = stat.symbol val allAnnots = value.annotations if (!isDeferred) - value.setAnnotations(memberAnnots(allAnnots, FieldTargetClass)) + // keepClean: by default annotations go to the field, except if the field is + // generated for a class parameter (PARAMACCESSOR). + value.setAnnotations(memberAnnots(allAnnots, FieldTargetClass, keepClean = !mods.hasFlag(PARAMACCESSOR))) val getter = if (isDeferred) value else value.getter(value.owner) assert(getter != NoSymbol, stat) @@ -1410,10 +1412,12 @@ trait Typers { self: Analyzer => List(stat) } - /** The annotations amongst `annots` that should go on a member of class - * `memberClass` (field, getter, setter, beanGetter, beanSetter, param) + /** + * The annotations amongst `annots` that should go on a member of class + * `memberClass` (field, getter, setter, beanGetter, beanSetter, param) + * If 'keepClean' is true, annotations without any meta-annotation are kept */ - protected def memberAnnots(annots: List[AnnotationInfo], memberClass: Symbol) = { + protected def memberAnnots(annots: List[AnnotationInfo], memberClass: Symbol, keepClean: Boolean = false) = { def hasMatching(metaAnnots: List[AnnotationInfo], orElse: => Boolean) = { // either one of the meta-annotations matches the `memberClass` @@ -1430,7 +1434,7 @@ trait Typers { self: Analyzer => // there was no meta-annotation on `ann`. Look if the class annotations of // `ann` has a `target` annotation, otherwise put `ann` only on fields. def noMetaAnnot(ann: AnnotationInfo) = { - hasMatching(ann.atp.typeSymbol.annotations, memberClass == FieldTargetClass) + hasMatching(ann.atp.typeSymbol.annotations, keepClean) } annots.filter(ann => ann.atp match { @@ -1702,7 +1706,7 @@ trait Typers { self: Analyzer => for (vparams <- ddef.vparamss; vd <- vparams) { if (vd hasFlag PARAMACCESSOR) { val sym = vd.symbol - sym.setAnnotations(memberAnnots(sym.annotations, ParamTargetClass)) + sym.setAnnotations(memberAnnots(sym.annotations, ParamTargetClass, keepClean = true)) } } } diff --git a/test/files/jvm/annotations.check b/test/files/jvm/annotations.check index 128f8e8f6e..fe14289381 100644 --- a/test/files/jvm/annotations.check +++ b/test/files/jvm/annotations.check @@ -23,7 +23,7 @@ public Test4$Foo6(java.lang.String) public Test4$Foo7() @test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=constructor val) -private final int Test4$Foo8.n +public Test4$Foo8(int) @test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=http://eppli.com) private int Test4$Foo9.z @@ -37,5 +37,14 @@ public int Test4$Foo9.x() @test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=http://uppla.com) public void Test4$Foo9.setY(int) +@test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=on param 1) +public Test4$Foo10(java.lang.String) + +@test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=on param 2) +private final java.lang.String Test4$Foo11.name + +@test.SourceAnnotation(mails={bill.gates@bloodsuckers.com}, value=on param 3) +public void Test4$Foo12.name_$eq(java.lang.String) + 0 99 diff --git a/test/files/jvm/annotations.scala b/test/files/jvm/annotations.scala index 12760beb4e..136aae6675 100644 --- a/test/files/jvm/annotations.scala +++ b/test/files/jvm/annotations.scala @@ -102,17 +102,20 @@ object Test4 { type myAnn = SourceAnnotation @beanGetter @field @BeanProperty @myAnn("http://eppli.com") var z = 0 } + class Foo10(@SourceAnnotation("on param 1") val name: String) + class Foo11(@(SourceAnnotation @scala.annotation.target.field)("on param 2") val name: String) + class Foo12(@(SourceAnnotation @scala.annotation.target.setter)("on param 3") var name: String) def run { import java.lang.annotation.Annotation import java.lang.reflect.AnnotatedElement + def printSourceAnnotation(a: Annotation) { + val ann = a.asInstanceOf[SourceAnnotation] + println("@test.SourceAnnotation(mails=" + ann.mails.deepMkString("{", ",", "}") + + ", value=" + ann.value + ")") + } def printSourceAnnotations(target: AnnotatedElement) { //print SourceAnnotation in a predefined way to insure // against difference in the JVMs (e.g. Sun's vs IBM's) - def printSourceAnnotation(a: Annotation) { - val ann = a.asInstanceOf[SourceAnnotation] - println("@test.SourceAnnotation(mails=" + ann.mails.deepMkString("{", ",", "}") + - ", value=" + ann.value + ")") - } val anns = target.getAnnotations() anns foreach printSourceAnnotation if (anns.length > 0) { @@ -120,6 +123,14 @@ object Test4 { println } } + def printParamSourceAnnotations(target: { def getParameterAnnotations(): Array[Array[Annotation]] }) { + val anns = target.getParameterAnnotations().flatten + anns foreach printSourceAnnotation + if (anns.length > 0) { + println(target) + println + } + } printSourceAnnotations(classOf[Foo1]) printSourceAnnotations(classOf[Foo2]) printSourceAnnotations(classOf[Foo3]) @@ -130,8 +141,18 @@ object Test4 { classOf[Foo7].getDeclaredConstructors foreach printSourceAnnotations classOf[Foo8].getDeclaredFields foreach printSourceAnnotations classOf[Foo8].getDeclaredMethods foreach printSourceAnnotations + classOf[Foo8].getDeclaredConstructors foreach printParamSourceAnnotations classOf[Foo9].getDeclaredFields.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations classOf[Foo9].getDeclaredMethods.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo10].getDeclaredFields.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo10].getDeclaredMethods.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo10].getDeclaredConstructors foreach printParamSourceAnnotations + classOf[Foo11].getDeclaredFields.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo11].getDeclaredMethods.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo11].getDeclaredConstructors foreach printParamSourceAnnotations + classOf[Foo12].getDeclaredFields.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo12].getDeclaredMethods.sortWith((x, y) => x.toString < y.toString) foreach printSourceAnnotations + classOf[Foo12].getDeclaredConstructors foreach printParamSourceAnnotations } } |