gist:066c8f709e94310bd1a5

Mark Eibes
2015-01-04T18:57:16Z

gistfile1.scala

| 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
| }
|
| }