2017-02-04 71 views
0

用於Scala的類的實現I型有一些問題階宏和識別實現類型構造函數。 不知道,如果我在這裏做得不對或有什麼正確的調用會。 從文檔,它看起來像typeSignatureIn應該返回正確的信息,例如ClassTag [INT],但是當我運行宏,我居然得到ClassTag [U]這無法編譯爲U是類型參數,而不是實現類型。獲取使用宏

import scala.language.experimental.macros 
import scala.reflect.ClassTag 
import scala.reflect.macros.Context 

def macroImpl[T: c.WeakTypeTag](c: Context) = { 
    import c.universe._ 

    val typeToMock = weakTypeOf[T] 

    val primaryConstructorOpt = typeToMock.members.collectFirst { 
    case method: MethodSymbolApi if method.isPrimaryConstructor => method 
    } 

    val constructorArgumentsTypes = primaryConstructorOpt.map { 
    constructor => 
    val constructorTypeContext = constructor.typeSignatureIn(typeToMock) 
    val constructorArguments = constructor.paramss 
    constructorArguments.map { symbols => 
     symbols.map(_.typeSignatureIn(constructorTypeContext)) 
    } 
    } 

    println(typeToMock) 
    println(constructorArgumentsTypes) 

    c.literalUnit 
} 

def foo[T] = macro macroImpl[T] 

class Foo[U: ClassTag] 

foo[Foo[Int]] 

運行它:

scala> foo[Foo[Int]] 
Foo[Int] 
Some(List(List(), List(scala.reflect.ClassTag[U])) 

我需要得到ClassTag [INT]以某種方式能夠產生正確的樹後,任何想法?

回答

0

嘗試使用dealias在每個地方,你解決一個類型。即使知道他們所指的是什麼,Scala也會保留參考。 dealias會爲您提供替換引用的類型的副本(?)。

你也應該選擇使用黑盒或白牌宏,而不僅僅是scala.reflect.macros.Context

這似乎工作:

import scala.language.experimental.macros 
import scala.reflect.ClassTag 
import scala.reflect.macros.whitebox.Context 

def macroImpl[T: c.WeakTypeTag](c: Context) = { 
    import c.universe._ 

    val typeToMock = weakTypeOf[T].dealias 

    val primaryConstructorOpt = typeToMock.members.collectFirst { 
    case method: MethodSymbolApi if method.isPrimaryConstructor => method 
    } 

    val constructorArgumentsTypes = primaryConstructorOpt.map { constructor => 
    val constructorTypeContext = constructor.typeSignatureIn(typeToMock).dealias 
    val constructorArguments = constructorTypeContext.paramLists 
    constructorArguments.map { symbols => 
     symbols.map(_.typeSignatureIn(constructorTypeContext).dealias) 
    } 
    } 

    println(typeToMock) 
    println(constructorArgumentsTypes) 

    q"()" 
} 

def foo[T]: Any = macro macroImpl[T] 

class Foo[U: ClassTag] 

foo[Foo[Int]] 

結果

Foo[Int] 
Some(List(List(), List(scala.reflect.ClassTag[Int]))) 
+0

千恩萬謝。仍然在努力將其整合到更廣泛的代碼庫中,但它給了我一個很好的領導下一步要研究的內容 –