0
votes

model code(partly):

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CoreField {

  String mongoTag() default "";

  boolean needIndex() default false;
}


trait PackItemTrait {

  @BeanProperty
  @CoreField(mongoTag = "num")
  var number: Int = _
}


class UserResourceFragmentT_1 {

  @BeanProperty
  @CoreField(mongoTag = "num")
  var number: Int = _
}


class UserResourceFragmentT_2 extends PackItemTrait {

}

reflection code(partly):

val className = "xxx.xxxx.UserResourceFragmentT_1" // or UserResourceFragmentT_2 fullNme
val clzSymbol = mirror.staticClass(className)
val clzType = clzSymbol.toType
clzType.members.foreach { each =>
  if (each.isTerm) {
    val eachTerm = each.asTerm
    println("eachTerm:" + eachTerm.name.decoded)
    println("isAccessor:" + eachTerm.isAccessor)
    println("isGetter:" + eachTerm.isGetter)
    println("isSetter:" + eachTerm.isSetter)
    println("isVar:" + eachTerm.isVar)
    println("isVal:" + eachTerm.isVal)
    println("annotation size:" + eachTerm.annotations.size)
    println("")
    if (eachTerm.isVar || eachTerm.isVal) {

I test class UserResourceFragmentT_1 and UserResourceFragmentT_2. When reflect UserResourceFragmentT_1, the outprint annotation size is 2, that's right, on the other hand, when reflect UserResourceFragmentT_2 which is inherit trait class PackItemTrait, the field number could be parse, but print is not like to previous model.

println:

UserResourceFragmentT_1

[info] eachTerm:number
[info] isAccessor:false
[info] isGetter:false
[info] isSetter:false
[info] isVar:true
[info] isVal:false
[info] annotation size:2

[info] eachTerm:number_=
[info] isAccessor:true
[info] isGetter:false
[info] isSetter:true
[info] isVar:false
[info] isVal:false
[info] annotation size:0

UserResourceFragmentT_2

[info] eachTerm:number_=
[info] isAccessor:true
[info] isGetter:false
[info] isSetter:true
[info] isVar:false
[info] isVal:false
[info] annotation size:0

[info] eachTerm:number
[info] isAccessor:true
[info] isGetter:true
[info] isSetter:false
[info] isVar:false
[info] isVal:false
[info] annotation size:0

I don't really konw about scala inherit mechanism... I also test PackItemTrait as abstract class, normal class, case class, the result are same: scala reflection api can not parse java annotation with field which inherit from super class, Any one can help me???

2
Could you upload the entire project to github? I'll be glad to take a look.Eugene Burmako
There is too much code for entire project, i am not sure you can compile them in sbt easily, it cannot done easily. my problem is easy to reporduce.Mars
@EugeneBurmako it is simple to reproduce, runtimeMirror(clazz.getClassLoader).classSymbol(clazz).selfType.members returns all members including the inherited ones. The problem is that calling m.annotations on those inherited members return empty List even though they are annotated...lisak

2 Answers

0
votes

After some research, I find a way to go:

val mirror = ru.runtimeMirror(Thread.currentThread.getContextClassLoader)
  val clzSymbol = mirror.staticClass("xxx.XXX.UserEquipmentT")
  clzSymbol.baseClasses.filter(
    each => (each.name.decoded != "Any" && each.name.decoded != "Object")
  ).foreach { each =>
    each.asType.toType.members.foreach { each =>
      if (each.isTerm) {
        val eachTerm = each.asTerm
        if (eachTerm.isVal || eachTerm.isVar) {
          println("name:" + eachTerm.name.decoded)
          println("annotation size:" + eachTerm.annotations.size)
        }
      }
    }
  }
0
votes

This doesn't return annotations for inherited members, only direct ones. I don't know if it is bug or it is by design:

runtimeMirror(clazz.getClassLoader).classSymbol(clazz).selfType.members.flatMap(m => m.annotations)

This however returns annotations even for inherited members:

runtimeMirror(clazz.getClassLoader).classSymbol(clazz).baseClasses.map(_.typeSignature).flatMap(c => c.members).flatMap(m => m.annotations)