非常に単純なマクロ互換のマクロ注釈。Scalaマクロ:ValDefから型シグニチャを派生させる
def impl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
annottees.map(_.tree) match {
case (classDef @ q"$mods class $tpname[..$tparams] $ctorMods(...$params) extends { ..$earlydefns } with ..$parents { $self => ..$stats }")
:: Nil if mods.hasFlag(Flag.CASE) =>
val name = tpname.toTermName
val typeName = tpname.toTypeName
val res = q"""
$classDef
object $name {
..${doStuff(c)(typeName, name, params.head)}
}
"""
c.Expr[Any](res)
case _ => c.abort(c.enclosingPosition, "Invalid annotation target, this must be a case class")
}
}
だから、とても単純です。問題の原因となるビットは、上記の$params
に由来します。ちょうどList[List[ValDef]]
です。つまり、何とかタイプシグネチャが失われています。 ValDef
上
def accessors(c: blackbox.Context)(
params: Seq[c.universe.ValDef]
): Iterable[(c.universe.TermName, c.universe.TypeName)] = {
import c.universe._
params.map {
case ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) => {
// tpt.tpe = kaboom, null pointer
name -> TypeName(tpt.tpe.typeSymbol.fullName)
}
}
}
tpe
はnull
として戻ってくるので、DEFSはタイプされたが、私は私が望むものを達成するためのparamsの型シグネチャを必要とされていません。どのように私は爆破せずにパラメータの型署名を得ることができますか?
皮肉なことに、showCode(tpt)
は正しいタイプの文字列を生成するので、これはTypeName(tpt.toString)
で回避できますが、なぜtpe
にアクセスできないのか分かりません。この場合
/**
* Retrieves the accessor fields on a case class and returns an iterable of tuples of the form Name -> Type.
* For every single field in a case class, a reference to the string name and string type of the field are returned.
*
* Example:
*
* {{{
* case class Test(id: UUID, name: String, age: Int)
*
* accessors(Test) = Iterable("id" -> "UUID", "name" -> "String", age: "Int")
* }}}
*
* @param params The list of params retrieved from the case class.
* @return An iterable of tuples where each tuple encodes the string name and string type of a field.
*/
def accessors(
params: Seq[ValDef]
): Iterable[Accessor] = {
params.map {
case ValDef(_, name: TermName, tpt: Tree, _) => {
Accessor(
name,
c.typecheck(tq"$tpt", c.TYPEmode).tpe
)
}
}
}
Accessor
がimport c.universe._
が利用可能である範囲内で定義する必要がありますカスタムcase class
です:
:http://stackoverflow.com/questions/23671379/proper-way-to-pattern-match-the-値a-a-a-typero-from-a-valdef-in-scala-macro –