简体   繁体   中英

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?

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM