2014-01-10 29 views
4

如何获得宏认证者的(“当前”)类型?宏认证者的类型

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

我以为宏注释并没有在2.11.x中发生。有改变吗? – wheaties

+1

他们已经发生在2.10和2.11通过宏观天堂插件。如果我们正在谈论被纳入标准分布,那么2.10香草和2.11香草都不会有它们。 –

+0

您能否详细说明用例?问题是,当宏注解被扩展时,被注释者没有为它创建的符号(有时它确实,但它不是给定的)。因此,它不能被符号/类型引用,只能通过树引用。当然,c.typecheck的结果会给你一些符号/类型,但它只能用于内省目的,而不能作为参考。 –

回答

4

当宏注释正在扩展,被注释者没有为其创建的符号它尚未(有时它确实,但它不是在给定的)。结果,它不能被一个符号/类型引用,只能被一棵树引用,例如, Ident(TypeName("Foo"))。当然,c.typecheck的结果会给你一些符号/类型,但它只能用于内省目的,而不能作为参考。

如果避开卫生问题,这种方法应该很好。如果您的伴侣对象定义了名为Foo的类/类型成员,则Serializer[Foo]中的Foo将绑定到伴侣的成员,而不是绑定到原始类。目前没有好的方法来处理这个问题(scalac本身必须解决这个问题,当生成适用/不适用于case case的方法时,但你不想知道它是如何完成的)。我们正计划为此提供一个解决方案,但我们只会在下个月开始研究它,所以它会持续一段时间,直到它出现在树干甚至天堂。

+0

“但你不想知道它是如何完成的......”但我们这样做。仍然无法找到任何方法来检查传递到宏注释中的moduleDef或classDef。 –