如何防止StaticAnnotation中的类型检查?

时间:2017-03-04 04:37:38

标签: scala annotations scala-macros typechecking scala-reflect

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

@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)宏?

1 个答案:

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