如何获得宏观注释的(“当前”)类型?
import scala.annotation.StaticAnnotation
import scala.reflect.macros._
import language.experimental.macros
class myself extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro myselfMacro.impl
}
object myselfMacro {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val a = annottees.head
println(s"static type = ${a.staticType}")
println(s"actual type = ${a.actualType}")
c.Expr[Any](Literal(Constant()))
}
}
测试:
@myself class Foo
输出:
static type = Nothing
actual type = null
我想要那种类型的原因是我想将它用作类型参数,例如Bar[Foo]
修改:
好的,所以我认为正确的方法是这样的:
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val v = annottees.head.asInstanceOf[ClassDef]
val tpe = v.tpe // <- tpe is null as the annotated type is not yet type checked!
val tpe2 = if (tpe == null)
c.typeCheck(v).tpe // <- fails with a compiler error (assertion failure)
else
tpe
println(s"Type of annottee: $tpe2")
???
}
但是given this post by Eugene Burmako,看起来像it is currently not possible ...
答案 0 :(得分:4)
当扩展宏注释时,注释者还没有为它创建一个符号(有时它会这样做,但它没有给定)。结果,它不能被符号/类型引用,只能由树引用,例如Ident(TypeName("Foo"))
。当然,c.typecheck的结果会给你一些符号/类型,但它只能用于内省,而不是作为参考点。
如果您避开卫生问题,这种方法应该可以正常工作。如果您的伴随对象定义了名为Foo
的类/类型成员,则Foo
中的Serializer[Foo]
将绑定到随播广告的成员,而不是原始类。目前还没有好办法解决这个问题(在为案例类生成apply / unapply方法时,scalac本身必须解决这个问题,但你不想知道它是如何完成的) 。我们正计划为此提供一个解决方案,但我们只会在下个月开始研究它,所以它会有一段时间,直到它落在行李箱甚至是天堂。