2014-01-10 28 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。 –