Last active
March 5, 2017 14:48
-
-
Save tototoshi/ac9de2c2d683b64c3ac0e59c660f2710 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example | |
import java.time.LocalDateTime | |
@ToString | |
case class UserName( | |
firs: String, | |
last: String | |
) | |
@ToString | |
case class User( | |
id: Int, | |
name: UserName, | |
country: String, | |
createdAt: LocalDateTime | |
) | |
@Logger | |
object Main { | |
def main(args: Array[String]): Unit = { | |
val user = User(1, UserName("Toshiyuki", "Takahashi"), "Japan", LocalDateTime.now()) | |
logger.info(user.toString) | |
// output | |
// 23:44:35.499 [run-main-3a] INFO com.example.Main$ - User(id=1, name=UserName(firs=Toshiyuki, last=Takahashi), country=Japan, createdAt=2017-03-05T23:44:35.498) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example | |
import scala.collection.immutable.Seq | |
import scala.meta._ | |
class ToString extends scala.annotation.StaticAnnotation { | |
inline def apply(defn: Any): Any = meta { | |
def addStat(classDefn: Defn.Class, stat: Stat): Defn.Class = { | |
val templ = classDefn.templ | |
val stats = templ.stats.getOrElse(Seq.empty[Stat]) | |
val newStats = stats :+ stat | |
val newTempl = templ.copy(stats = Some(newStats)) | |
classDefn.copy(templ = newTempl) | |
} | |
def addToStringMethod(classDefn: Defn.Class, objDefn: Defn.Object): Stat = { | |
val className = classDefn.name.toString | |
val paramNames = classDefn.ctor.paramss.flatten.map { param => | |
val fieldName = param.name.toString | |
q"""${Lit(fieldName)} + "=" + ${Term.Name(fieldName)}""" | |
} | |
val body = paramNames.reduce { (a, b) => q"""$a + ", " + $b""" } | |
val method = q"""override def toString(): String = ${Lit(className)} + "(" + $body + ")"""" | |
val classDefnWithToString = addStat(classDefn, method) | |
Term.Block(scala.collection.immutable.Seq(classDefnWithToString, objDefn)) | |
} | |
defn match { | |
case Term.Block(Seq(classDefn: Defn.Class, objDefn: Defn.Object)) => | |
addToStringMethod(classDefn, objDefn) | |
case classDefn: Defn.Class => | |
val objName = Term.Name(classDefn.name.toString) | |
val objDefn = q"object $objName {}" | |
addToStringMethod(classDefn, objDefn) | |
case _ => sys.error("error") | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example | |
import scala.annotation.StaticAnnotation | |
import scala.meta._ | |
import scala.collection.immutable.Seq | |
class Logger extends StaticAnnotation { | |
inline def apply(defn: Any): Any = meta { | |
def addStatToTempl(templ: Template, stat: Stat): Template = { | |
val stats = templ.stats.getOrElse(Seq.empty[Stat]) | |
val newStats = stat +: stats | |
templ.copy(stats = Some(newStats)) | |
} | |
def addStatToClassDefn(classDefn: Defn.Class, stat: Stat): Defn.Class = { | |
val templ = classDefn.templ | |
val newTempl = addStatToTempl(templ, stat) | |
classDefn.copy(templ = newTempl) | |
} | |
def addStatToObjDefn(objDefn: Defn.Object, stat: Stat): Defn.Object = { | |
val templ = objDefn.templ | |
val newTempl = addStatToTempl(templ, stat) | |
objDefn.copy(templ = newTempl) | |
} | |
def loggerMethod: Stat = { | |
q""" | |
private val logger = { | |
import org.slf4j.LoggerFactory | |
LoggerFactory.getLogger(getClass) | |
} | |
""" | |
} | |
defn match { | |
case objDefn: Defn.Object => | |
addStatToObjDefn(objDefn, loggerMethod) | |
case classDefn: Defn.Class => | |
addStatToClassDefn(classDefn, loggerMethod) | |
case Term.Block(Seq(classDefn: Defn.Class, objDefn: Defn.Object)) => | |
Term.Block( | |
Seq( | |
addStatToClassDefn(classDefn, loggerMethod), | |
addStatToObjDefn(objDefn, loggerMethod) | |
) | |
) | |
case _ => sys.error("error") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment