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?

+3


source to share


1 answer


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.

https://github.com/outr/scalarelational/blob/master/mapper/src/main/scala/org/scalarelational/mapper/typedTable.scala



Thanks again to Eugene and Mario for your wonderful answers that led me to find my answer.

+3


source







All Articles