Skip to content

Instantly share code, notes, and snippets.

@charithe
Created March 29, 2016 09:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charithe/ac0c20d7b93e9c01feb3 to your computer and use it in GitHub Desktop.
Save charithe/ac0c20d7b93e9c01feb3 to your computer and use it in GitHub Desktop.
Scala macro for accessing Typesafe Config objects
import com.typesafe.config.Config
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.reflect.runtime.universe._
object TypesafeConfigMacros {
def asImpl[T: c.WeakTypeTag](c: whitebox.Context)(key: c.Expr[String])(tag: c.Expr[WeakTypeTag[T]]): c.Expr[Option[T]] = {
import c.universe._
def genPrimitiveGetter(conf: c.Expr[Config], key: c.Expr[String], tpe: String): c.Expr[Option[T]] = {
val methodName = TermName(s"get$tpe")
c.Expr[Option[T]](q"Some($conf.$methodName($key))")
}
def genListGetter(conf: c.Expr[Config], key: c.Expr[String], tpe: String): c.Expr[Option[T]] = {
val methodName = TermName(s"get${tpe}List")
c.Expr[Option[T]]( q"""Some(scala.collection.JavaConversions.asScalaBuffer($conf.$methodName($key)).toList)""")
}
val tpe = c.weakTypeOf[T]
val conf = c.Expr[Config](q"conf")
val expr = tpe match {
case x if tpe <:< typeOf[String] => genPrimitiveGetter(conf, key, tpe.toString)
case x if tpe <:< typeOf[Long] => genPrimitiveGetter(conf, key, tpe.toString)
case x if tpe <:< typeOf[Int] => genPrimitiveGetter(conf, key, tpe.toString)
case x if tpe <:< typeOf[Double] => genPrimitiveGetter(conf, key, tpe.toString)
case x if tpe <:< typeOf[Boolean] => genPrimitiveGetter(conf, key, tpe.toString)
case x if tpe <:< typeOf[Config] => genPrimitiveGetter(conf, key, "Config")
case x if tpe <:< typeOf[List[String]] => genListGetter(conf, key, "String")
case x if tpe <:< typeOf[List[Long]] => genListGetter(conf, key, "Long")
case x if tpe <:< typeOf[List[Int]] => genListGetter(conf, key, "Int")
case x if tpe <:< typeOf[List[Double]] => genListGetter(conf, key, "Double")
case x if tpe <:< typeOf[List[Boolean]] => genListGetter(conf, key, "Boolean")
case x if tpe <:< typeOf[List[Config]] => genListGetter(conf, key, "Config")
case _ => c.abort(c.enclosingPosition, s"Unsupported data type: ${tpe.toString}")
}
//println(showCode(q""" if($conf.hasPath($key)) { $expr } else { Option.empty[$tpe] } """))
c.Expr[Option[T]](q""" if($conf.hasPath($key)) { $expr } else { Option.empty[$tpe] } """)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment