Quasiquotes and Generics in Scala -
i'm using play framework , trying write action can parse protobuf request following:
def asyncprotoaction(block: protorequesta => future[result]): action[anycontent] = { action.async { request => request.contenttype match { case some("application/protobuf") => request.body.asraw match { case some(raw) => raw.asbytes(1024 * 1024) match { case some(rawbytes) => val proto = protorequesta.parsefrom(rawbytes) block(proto) case _ => ... } } } } }
here, protorequesta
generated object using scalapb
. works, however, have lot of protobuf request objects. try rewrite using macro:
object actions { def asyncprotoaction[t](block: t => future[result]): action[anycontent] = macro asyncprotoaction_impl[t] def asyncprotoaction_impl[t: c.weaktypetag](c: blackbox.context) (block: c.tree) = { import c.universe._ val prototype = weaktypeof[t] q"""import play.api.mvc._ action.async { request => request.contenttype match { case some("application/protobuf") => request.body.asraw match { case some(raw) => raw.asbytes(1024 * 1024) match { case some(rawbytes) => val proto = $prototype.parsefrom(rawbytes) $block(proto) case _ => ... } } } }""" } }
this doesn't work. compilation error value parsefrom not member of packagename.protorequesta
.
i tried showraw(tq"$prototype")
in repl, output string = typetree()
. guess correct output should string = select(ident(termname("packagename")), typename("protorequesta"))
. should do?
you've identified problem, when interpolate protorequesta
type different protorequesta
companion object. 1 easy solution interpolate symbol of companion object, can type's symbol. here's simplified example:
import scala.language.experimental.macros import scala.reflect.macros.blackbox.context def companionobjectbarimpl[a: c.weaktypetag](c: context): c.tree = { import c.universe._ q"${ symbolof[a].companion }.bar" } def companionobjectbar[a]: int = macro companionobjectbarimpl[a]
this macro work on type companion object bar
method returns int
. example:
scala> class foo; object foo { def bar = 10 } defined class foo defined object foo scala> companionobjectbar[foo] res0: int = 10
you should able similar.
Comments
Post a Comment