Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package macros
- import scala.language.experimental.macros
- import scala.reflect.macros.whitebox.Context
- trait TestMacro[T] {
- def check(row: List[Any]): Unit
- //def map(row: List[Any]): T
- //def unapply(obj: T): List[Any]
- }
- object TestMacro {
- implicit def method[T]: TestMacro[T] = macro methodImpl[T]
- def methodImpl[T: c.WeakTypeTag](c: Context): c.Expr[TestMacro[T]] = {
- import c.universe._
- val tpe = weakTypeOf[T]
- val decls = tpe.decls
- val ctor = decls.collectFirst { case m: MethodSymbol if m.isPrimaryConstructor => m}.get
- val params = ctor.paramLists.head
- val companion = tpe.typeSymbol.companion
- val typs = params.map(p => p.typeSignature)
- val vals = (1 to typs.length).map(x => TermName(s"v$x"))
- val patt = vals.zip(typs).map { case (v, t) => pq"$v: $t"}
- val copy = decls.collectFirst {case m: MethodSymbol if m.fullName.contains("copy") => m}.get
- val unapplyVals = params.map {
- case p =>
- val valName = p.name.toTermName
- q"obj.$valName"
- }
- val check = typs.zipWithIndex.map {
- case (t, i) =>
- val typ = q"row($i).getClass.toString"
- q"""
- if(!row($i).isInstanceOf[$t])
- throw new Exception("Error mapping " + row + ", type: " + $typ +
- ${s", row($i) should be " + t.toString}
- )"""
- }
- c.Expr[TestMacro[T]] {
- q"""
- new TestMacro[$tpe] {
- def check(row: List[Any]): Unit = {
- ..$check
- }
- def map(row: List[Any]) = {
- row match {
- case List(..$patt) => $copy(..$vals)
- case _ => throw new Exception("Can not map " + row)
- }
- }
- def unapply(obj: $tpe) = $unapplyVals
- }
- """
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement