Scala Quasiquotes Destructuring a Type -
context:
i'm working on library working jmx in scala. 1 of objectives have strong typed interface managed beans. guess akin to spring framework jmx library.
objective: macro deserialise tabulardata case class:
// interface i'd generate implementation using 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 )
problem: there plenty of examples of composing tree's using q""
interpolators. can't figure out how use tq""
interpolator extract fields out of case class type context.
private def mkassembler[t <: product : c.weaktypetag](c: context): c.universe.tree = { import c.universe._ val tt = weaktypeof[t] }
question: how use quasiquote machinery destructure fields of case class i can loop on them , filter out fields annotation (my attribute
annotation not available approach taking"). implementation of following returns fields annotations in declaration order after.
private def harvestfieldswithannotations[t<: product: c.weaktypetag](c: context): list[(c.universe.name, string, c.universe.type, list[c.universe.annotation])] = ???
bonus: objective attribute fields, generate trees each field extract field tabulardata
, use these trees create jmxtabularassembler
functor. if show me how example above bootstrap efforts :d.
what have tried: started solving problem using reflection. not seem right way it. snippets:
... 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) } ...
the following method trick, not use quasi quotes. key access backing field of symbol representing field accessor of case class (the accessed
call).
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) } }
field annotations won't retained unless explicitly annotated scala.annotation.meta.field
.
so attribute
annotation should be:
@field case class attribute(name: string) extends staticannotation
Comments
Post a Comment