0

我正在创建一些宏库,它们从enclosing方法的注释中读取一些信息。

@info(foo(bar, baz))
def enclosing() = {
  myMacro()
}

这些信息被编码foo(bar, baz)StaticAnnotation @info.

foo(bar, baz)myMacro但是,包含需要的信息,foo(bar, baz)无法在该位置进行类型检查@info,并在类型检查时导致编译器错误foo(bar, baz)

我想知道我是否可以创建一个dontTypecheck防止foo(bar, baz)类型检查的宏。这样我就可以创建类似的东西:

@info(dontTypecheck {
  foo(bar, baz)
})
def enclosing() = {
  myMacro()
}

dontTypecheck宏应该产生一个Tree包含 untype-checked的foo(bar, baz)

如何创建dontTypecheck宏?

4

1 回答 1

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
        )
    }
  }
}

// 测试

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))

于 2017-03-04T09:32:56.563 回答