4

I'm trying to generate case objects for every case member of every child case class of a sealed trait. I'm able to generate the code in the macro but I don't know how to use this in my code.

Example usecase:

sealed trait Item
sealed trait Field {
  val name: String
}
case class Product(id: String, name: String) extends Item

It should generate the following case objects which are fields of Product.

case object ProductIdField extends Field {
  val name = "Product Id"
}
case object ProductNameField extends Field {
  val name = "Product Name"
}

Macro so far which generates the code

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object FieldGenerator {

  def generator[A](): Product = macro generate[A]

  def generate[A: c.WeakTypeTag](c: Context)(): c.Tree = {
    import c.universe._

    val subclasses: Set[c.universe.Symbol] = c.weakTypeOf[A].typeSymbol.asClass.knownDirectSubclasses

    val fieldObjects: Set[String] = subclasses.flatMap {
      (subClass: c.universe.Symbol) =>
        val itemName = subClass.name.toString
        val sealedTraitName = s"${itemName}Field"
        val fieldSealedTrait: String = s"sealed trait $sealedTraitName extends Field"
        val fieldCaseObjects: Iterable[String] = subClass.info.decls.collect {
          case m: MethodSymbol if m.isCaseAccessor =>
            val fieldName = m.name.toString.capitalize
            s"""case object ${itemName + fieldName}Field extends $sealedTraitName {
                  val name = "$itemName $fieldName"
               }
             """.stripMargin
        }
        List(fieldSealedTrait) ++ fieldCaseObjects
    }

    fieldObjects.foreach(println)

    q"..$fieldObjects"
  }
}

Here is how I am calling it

FieldGenerator.generator[Item]()

And I get the following compile time error

a pure expression does nothing in statement position; you may be omitting necessary parentheses

How can I import the generated code ?

user794783
  • 3,619
  • 7
  • 36
  • 58

0 Answers0