How do I create a class or object in Scala macros?
I'm trying to create a companion object from a case class using macros, but I'm having a very hard time finding examples of how to do this.
For example:
case class Person(name: String, age: Int, id: Option[Int] = None)
If I do this:
object PersonTable extends TypedTable[Person]
I want it to generate:
object PersonTable extends Table("PERSON") {
val name = column[String]("NAME")
val age = column[Int]("AGE")
val id = column[Option[Int]]("ID")
}
Also, I want to be able to extend it and add additional fields:
object PersonTable extends TypedTable[Person] {
val created = column[Timestamp]("TIMESTAMP")
}
And it will generate:
object PersonTable extends Table("PERSON") {
val name = column[String]("NAME")
val age = column[Int]("AGE")
val id = column[Option[Int]]("ID")
val created = column[Timestamp]("TIMESTAMP")
}
Edit
After reading the macros (thanks to Eugene and Mario), I created the following code:
class table[T] extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro TableGenerator.impl
}
object TableGenerator {
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
def modifiedObject(objectDef: ModuleDef): c.Expr[Any] = {
val ModuleDef(_, objectName, template) = objectDef
val ret = q"""
object $objectName {
def test() = println("Wahoo!")
}
"""
c.Expr[Any](ret)
}
annottees.map(_.tree) match {
case (objectDecl: ModuleDef) :: _ => modifiedObject(objectDecl)
case x => c.abort(c.enclosingPosition, s"@table can only be applied to an object, not to $x")
}
}
}
And then tried to use it like this:
@table[String] object MyCoolObject
MyCoolObject.test()
The first line works fine, but the second line says it can't find a test method. How do I make the validation method visible?
source to share
Unfortunately, it is very difficult to find good examples of Macros online - especially for 2.11. I was finally able to get everything to work, so I would like to provide a link to the code for anyone struggling with the same issues later.
Thanks again to Eugene and Mario for your wonderful answers that led me to find my answer.
source to share