I'm trying to create a Scala macro which defines a single a Class argument, and which modifies the class to which it is attached based on the implementation of the Class which is provided as an argument.
//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
I've managed to create a simple macro that is able to extract the argument from the annotation, resulting in a TypeName object that contains a string representation of the full class name.
The problem is now that I need to access the definition of A from the macro implementation (specifically, I want to see what the constructor arguments are).
Is there a way to access/create a TypeTag[A] in some way? Is there a way I can access the AST of class A?
To illustrate what I'm trying to achieve, this is what I currently have as a macro definition:
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)
}
}