Scala Quasiquotes解构类型

时间:2015-07-22 12:02:04

标签: scala scala-macros scala-quasiquotes

上下文

我正在使用一个库来处理Scala中的JMX。其中一个目标是为Managed Beans提供强大的类型接口。我想类似于Spring框架JMX库。

目标:将TabularData反序列化为案例类的宏:

// interface for which I'd like to generate an implementation using a macro
trait JMXTabularAssembler[T <: Product] {
  def assemble(data: TabularData): T
}

object JMXAnnotations {
  case class Attribute(name: String) extends StaticAnnotation
}
case class example(
  @Attribute("name") name: String,
  @Attribute("age") age: Int,
  unmarked: String
)

问题:有很多使用q""插值器组成树的示例。但我无法弄清楚如何使用tq""插值器 从类型上下文中提取案例类中的字段。

private def mkAssembler[T <: Product : c.WeakTypeTag](c: Context): c.universe.Tree = {
  import c.universe._
  val tt = weakTypeOf[T]
}

问题:如何使用QuasiQuote机制来解构我的case类的字段,以便我可以遍历它们并使用我的注释过滤掉字段(< strong>我的Attribute注释无法从我正在采用的方法中获得&#34; )。下面的实现返回带有注释的字段,这是我所追求的。

private def harvestFieldsWithAnnotations[T<: Product: c.WeakTypeTag](c: Context): 
    List[(c.universe.Name, String, c.universe.Type,   List[c.universe.Annotation])] = ???

加分:目标是获取属性字段,为每个从TabularData中提取字段的字段生成树,并使用这些树来创建JMXTabularAssembler Functor 。如果您可以告诉我如何为上面的示例执行此操作,它将引导我的努力:D。

我尝试了什么:我开始使用反射来解决问题。这似乎不是正确的方法。片段:

...
val dec = tt.decls.sorted
def getFields = dec.withFilter( t=> t.isTerm && ! t.isMethod)
def getCaseAccessors = dec.withFilter( t => t.isMethod && t.asMethod.isCaseAccessor)

dec.foreach { d=>
  println(d.name, d.annotations)
}

getFields.foreach { f =>
  println(f.annotations)
}

val types = getCaseAccessors.map { d =>
  println(d.annotations)
  (d.name, tt.member(d.name).asMethod.returnType)
}
...

1 个答案:

答案 0 :(得分:0)

以下方法可以解决问题,它不使用准引号。关键是访问表示案例类(accessed调用)的字段访问者的符号的后备字段。

private def harvestFieldsWithAnnotations[T <: Product : c.WeakTypeTag](c: Context) = {
    import c.universe._
    val tt = weakTypeOf[T]

    tt.decls.sorted.filter(t => t.isMethod && t.asMethod.isCaseAccessor).map { ca =>
      val asMethod = tt.member(ca.name).asMethod
      (ca.name, asMethod.returnType, asMethod.accessed.annotations)
    }
  }

除非使用scala.annotation.meta.field明确注释字段注释,否则不会保留字段注释。

所以Attribute注释应该是:

@field
case class Attribute(name: String) extends StaticAnnotation