単一のクラス引数を定義し、引数として提供されるクラスの実装に基づいてアタッチ先のクラスを変更する Scala マクロを作成しようとしています。
//Simple class with a few arguments
class A(a: String, b: String)
//Definition of this class should be modified based on class definition of A
@parameterized(classOf[A])
class B
注釈から引数を抽出できる単純なマクロを作成することができました。その結果、完全なクラス名の文字列表現を含む TypeName オブジェクトが生成されます。
問題は、マクロの実装から A の定義にアクセスする必要があることです (具体的には、コンストラクターの引数が何であるかを確認したい)。
何らかの方法で TypeTag[A] にアクセス/作成する方法はありますか? クラス A の AST にアクセスする方法はありますか?
私が達成しようとしていることを説明するために、これは私が現在マクロ定義として持っているものです:
object parameterizedMacro {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
import Flag._
//Extract the parameter type which was provided as an argument (rather hacky way of getting this info)
val parameterType = c.macroApplication match {
case Apply(Select(Apply(_, List(
TypeApply(Ident(TermName("classOf")), List(Ident(TypeName(parameterType))))
)) , _), _) => parameterType
case _ =>
sys.error("Could not match @parameterized arguments. Was a class provided?")
}
//Should generate method list based on the code of parameterType
val methods = ???
val result = {
annottees.map(_.tree).toList match {
case q"object $name extends ..$parents { ..$body }" :: Nil =>
q"""
object $name extends ..$parents {
..${methods}
..$body
}
"""
case q"class $name (..$args) extends ..$parents { ..$body }" :: Nil =>
q"""
class $name (..$args) extends ..$parents {
..${methods}
..$body
}
"""
}
}
c.Expr[Any](result)
}
}