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

How to prevent typecheck in StaticAnnotation?

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

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

这些信息在StaticAnnotation@info中编码为foo(bar, baz)

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,其中包含未经类型检查的 foo(bar, baz)

如何创建 dontTypecheck 宏?

一个想法是使用另一个注释保存信息

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