Skip to content

Instantly share code, notes, and snippets.

@i-am-the-slime
Last active August 29, 2015 14:12
Show Gist options
  • Save i-am-the-slime/066c8f709e94310bd1a5 to your computer and use it in GitHub Desktop.
Save i-am-the-slime/066c8f709e94310bd1a5 to your computer and use it in GitHub Desktop.
package co.aryaapp.macros
import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
package co.aryaapp.macros
object Util {
def unCamelCase(s:String):String = {
(s.head.toLower :: s.tail.flatMap( c =>
if (c.isUpper)
'_' :: c.toLower :: Nil
else c :: Nil
) :: Nil).mkString("")
}
}
object argonautMacro {
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val (className, classFields:List[ValDef]) = annottees(0).tree match {
case q"case class $name(..$fields)" => (name, fields)
}
val fields = classFields.map{ vd:ValDef => (vd.name, vd.tpt) }
val fieldNamesWithUnderscores = fields.map{ case (name, _) => Util.unCamelCase(name.toString) }
val casecodecN = TermName("casecodec"+fields.length.toString)
val reunited = fields.map{ case (name, tpe) => q" $name: $tpe " }
val cnCodecJson = TermName(s"${className}CodecJson")
val cn = TermName(className.toString)
c.Expr[Any](q"""
case class $className ( ..$reunited )
object $cn { implicit def $cnCodecJson : CodecJson[ $className ] = $casecodecN ($cn.apply, $cn.unapply)(..$fieldNamesWithUnderscores) }
""")
}
}
object Macros {
class argonaut extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro argonautMacro.impl
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment