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?
It's unfortunately very difficult to find good examples of Macros online - especially for 2.11. I was finally able to get everything working so I wanted to provide a link to the code for anyone struggling with the same problems later.
https://github.com/outr/scalarelational/blob/master/mapper/src/main/scala/org/scalarelational/mapper/typedTable.scala
Thanks again Eugene and Mario for your great answers that led me to finding my answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With