4lex1v
4lex1v

Reputation: 21557

Matching against subclasses in macro

I need to convert a string value into an actual type, so i decided to try a macro-way to do this. I have a bunch of data types:

sealed abstract class Tag(val name: String)
case object Case1 extends Tag("case1")
case object Case2 extends Tag("case2")
case object Case3 extends Tag("case3")
etc...

I want to write a simple resolver:

val tag: Tag = TagResolver.fromString("case2")

This line should return Case2 respectively. I manager to do the following:

def typeFromString(c: Context)(name: c.Expr[String]): c.Expr[Tag] = {
    import c.universe._
    val tag = typeTag[Tag]
    val accSymb = tag.tpe.typeSymbol.asClass
    val subclasses = accSymb.knownDirectSubclasses // all my cases

    subclasses.map { sub =>
      val name = sub.typeSignature.member(newTermName("name")).asMethod // name field
      ???
    }
  }

But how can i match name: c.Expr[String] against value of name field and if matched return the appropriate tag?

Upvotes: 4

Views: 308

Answers (1)

Eugene Burmako
Eugene Burmako

Reputation: 13048

I don't think there's reliable way of doing this, because knownDirectSubclasses can refer to classes that haven't been compiled yet, so we can't evaluate them.

If you can put these values as annotations on the classes, then these annotations can be read even when classes are being compiled in the current compilation run (via the Symbol.annotations API). Please note, however, that knownDirectSubclasses has known issues: https://issues.scala-lang.org/browse/SI-7046.

Upvotes: 1

Related Questions