我正在创建一些宏库,它们从封闭方法的注释中读取一些信息。
@info(foo(bar, baz))
def enclosing() = {
myMacro()
}
这些信息在foo(bar, baz)
StaticAnnotation
中编码为@info
。
foo(bar, baz)
包含myMacro
需要的信息,但foo(bar, baz)
无法在@info
位置进行类型检查,并在类型检查{{}时导致编译器错误1}}。
我想知道是否可以创建一个阻止foo(bar, baz)
类型检查的宏dontTypecheck
。这样我就可以创建类似的东西:
foo(bar, baz)
@info(dontTypecheck {
foo(bar, baz)
})
def enclosing() = {
myMacro()
}
宏应该生成一个dontTypecheck
,其中包含无法检查的Tree
。
如何创建foo(bar, baz)
宏?
答案 0 :(得分:1)
一个想法是使用另一个注释保存信息
class Info[T](t: T) extends scala.annotation.StaticAnnotation {
}
class AnnInfo extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro AnnInfImpl.impl
}
trait AnnotationUtils {
val c: scala.reflect.macros.blackbox.Context
import c.universe._
final def getAnnotation(x: MemberDef) = x.mods.annotations
}
class AnnInfImpl(val c: blackbox.Context) extends AnnotationUtils {
import c.universe._
// edit 1
def impl(annottees: Tree*): Tree = {
annottees.head match {
case x: DefDef =>
// collect value from `@Info(value)`
val info: List[Tree] = getAnnotation(x).collect { case q"new $name ($value)" => value }
val newBody =
q"""
{
val info = ${info.map(e => show(e))}
println(info)// just print it
${x.rhs}
}"""
DefDef(
mods = Modifiers(), //dropMods
name = x.name,
tparams = x.tparams,
vparamss = x.vparamss,
tpt = x.tpt,
rhs = newBody
)
}
}
}
// test
class AnnInfoTest {
val a = 1
val b = 2
def f(a: Int, b: Int) = a + b
@Info(f(a, b))
@AnnInfo
def e = ???
}
如果您致电e
,则会打印List(f(a, b))