All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mdedetrich.utforsca.SealedContents.scala Maven / Gradle / Ivy

The newest version!
package org.mdedetrich.utforsca

import language.experimental.macros
import scala.reflect.macros._

/**
  * This provides a method to get all enumerations from an ADT (which is
  * an alternative from using the Enumeration type). Note that since this
  * is a macro, you have to explicitly supply the type signature
  *
  * Taken from http://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala
  */

object SealedContents {
  def values[A]: Set[A] = macro values_impl[A]

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

    val symbol = weakTypeOf[A].typeSymbol

    if (!symbol.isClass) c.abort(
      c.enclosingPosition,
      "Must be a class or a trait."
    )
    else if (!symbol.asClass.isSealed) c.abort(
      c.enclosingPosition,
      "Can only enumerate values of a sealed trait or class."
    )
    else {
      val children = symbol.asClass.knownDirectSubclasses.toList

      if (!children.forall(_.isModuleClass)) c.abort(
        c.enclosingPosition,
        "All children must be objects."
      )
      else c.Expr[Set[A]] {
        def sourceModuleRef(sym: Symbol) = Ident(sym.asInstanceOf[scala.reflect.internal.Symbols#Symbol].sourceModule.asInstanceOf[Symbol])
        Apply(Select(reify(Set).tree, newTermName("apply")), children.map(sourceModuleRef(_)))
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy