I'm attempting to generate a companion object from a case class using Macros but I'm having a very hard time finding any examples of how to accomplish this.
For example:
case class Person(name: String, age: Int, id: Option[Int] = None)
If I do:
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")
}
Further, I want to be able to extend it and add additional fields as well:
object PersonTable extends TypedTable[Person] {
val created = column[Timestamp]("TIMESTAMP")
}
And it would 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 about macro annotations (thanks 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 attempted 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 the test method. How do I make it so that the test method is visible?