aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.scalafmt.conf2
-rw-r--r--macros/src/main/scala/macro.scala93
2 files changed, 62 insertions, 33 deletions
diff --git a/.scalafmt.conf b/.scalafmt.conf
new file mode 100644
index 0000000..2b811a2
--- /dev/null
+++ b/.scalafmt.conf
@@ -0,0 +1,2 @@
+style=intellij
+maxColumn=80 \ No newline at end of file
diff --git a/macros/src/main/scala/macro.scala b/macros/src/main/scala/macro.scala
index 87e0000..a3f61db 100644
--- a/macros/src/main/scala/macro.scala
+++ b/macros/src/main/scala/macro.scala
@@ -7,7 +7,8 @@ import scala.language.experimental.macros
import scala.language.higherKinds
trait ProductWriters[Writer[_]] {
- implicit def productWriter[P]: Writer[P] = macro ProductMapperBundle.productWriterImpl[Writer[_], P]
+ implicit def productWriter[P]: Writer[P] =
+ macro ProductMapperBundle.productWriterImpl[Writer[_], P]
}
class ProductMapperBundle(val c: Context) {
@@ -15,14 +16,11 @@ class ProductMapperBundle(val c: Context) {
/** Summon an implicit value and return the tree representing its
* invocation, or fail if no implicit is available. */
- private def implicitlyOrFail(tpe: Type, message: String): Tree = {
- c.typecheck(
- q"""{
+ private def implicitlyOrFail(tpe: Type, message: String): Tree = {
+ c.typecheck(q"""{
import ${c.prefix}._
implicitly[$tpe]
- }""",
- silent = true
- ) match {
+ }""", silent = true) match {
case EmptyTree => c.abort(c.enclosingPosition, message)
case tree => tree
}
@@ -31,19 +29,22 @@ class ProductMapperBundle(val c: Context) {
private case class TypeClass(baseType: Type, method: MethodSymbol)
private def writerTypeClass[T: c.WeakTypeTag]: TypeClass = {
- val baseType = weakTypeOf[T]
+ val baseType = weakTypeOf[T]
val typeParam: Symbol = baseType.typeSymbol.asType.typeParams.head
// extract methods that take one type parameter, matching the type classes type parameter
- val methods = baseType.decls.collect{
- case m: MethodSymbol if m.isAbstract => m
- }.filter{ m =>
- m.paramLists match {
- case (param :: Nil) :: Nil =>
- param.info.typeSymbol == typeParam
- case _ => false
+ val methods = baseType.decls
+ .collect {
+ case m: MethodSymbol if m.isAbstract => m
}
- }.toList
+ .filter { m =>
+ m.paramLists match {
+ case (param :: Nil) :: Nil =>
+ param.info.typeSymbol == typeParam
+ case _ => false
+ }
+ }
+ .toList
methods match {
case head :: Nil => TypeClass(baseType, head)
@@ -64,18 +65,33 @@ class ProductMapperBundle(val c: Context) {
* @param genericType the elemnt type of the new writer to create
* @param body a function that generates the writer's body from a given parameter name
*/
- private def newWriter(tc: TypeClass, genericType: Type, body: TermName => Tree): Block = {
+ private def newWriter(tc: TypeClass,
+ genericType: Type,
+ body: TermName => Tree): Block = {
val parent = appliedType(tc.baseType.typeConstructor, genericType)
val paramName = TermName("value")
- val param = ValDef(Modifiers(Flag.PARAM), paramName, TypeTree(genericType), EmptyTree)
- val defn = DefDef(Modifiers(), tc.method.name, Nil, List(List(param)), TypeTree(tc.method.returnType), body(paramName))
+ val param = ValDef(
+ Modifiers(Flag.PARAM),
+ paramName,
+ TypeTree(genericType),
+ EmptyTree
+ )
+ val defn = DefDef(
+ Modifiers(),
+ tc.method.name,
+ Nil,
+ List(List(param)),
+ TypeTree(tc.method.returnType),
+ body(paramName)
+ )
val tree = Block(
- List(
- q"final class $$anon extends $parent { $defn }"
- ),
- Apply(Select(New(Ident(TypeName("$anon"))), termNames.CONSTRUCTOR), List())
+ List(q"final class $$anon extends $parent { $defn }"),
+ Apply(
+ Select(New(Ident(TypeName("$anon"))), termNames.CONSTRUCTOR),
+ List()
+ )
)
tree
}
@@ -85,25 +101,36 @@ class ProductMapperBundle(val c: Context) {
val writer: TypeClass = writerTypeClass[W]
if (!(product <:< weakTypeOf[Product])) {
- c.abort(c.enclosingPosition, s"Cannot generate product writer for non-product type $product")
+ c.abort(
+ c.enclosingPosition,
+ s"Cannot generate product writer for non-product type $product"
+ )
}
- val mapType: Type = appliedType(typeOf[Map[_, _]], typeOf[String], writer.method.returnType)
+ val mapType: Type =
+ appliedType(typeOf[Map[_, _]], typeOf[String], writer.method.returnType)
- val mapWriter = implicitlyOrFail(appliedType(writer.baseType, mapType),
- s"No implicit decomposer available for ${appliedType(writer.baseType, product)}. Make sure an implicit $mapType is in scope.")
+ val mapWriter = implicitlyOrFail(
+ appliedType(writer.baseType, mapType),
+ s"No implicit decomposer available for ${appliedType(writer.baseType, product)}. Make sure an implicit $mapType is in scope."
+ )
- val fields: List[(TermName, Type)] = product.decls.collect{
+ val fields: List[(TermName, Type)] = product.decls.collect {
case m: MethodSymbol if m.isCaseAccessor =>
m.name -> m.info.resultType
}.toList
- val fieldWriters: List[(TermName, Tree)] = fields.map{ case (name, tpe) =>
- val writerType = appliedType(writer.baseType, tpe)
- name -> implicitlyOrFail(writerType, s"Cannot create writer for $product: no implicit writer available for $product.$name of type $tpe")
+ val fieldWriters: List[(TermName, Tree)] = fields.map {
+ case (name, tpe) =>
+ val writerType = appliedType(writer.baseType, tpe)
+ name -> implicitlyOrFail(
+ writerType,
+ s"Cannot create writer for $product: no implicit writer available for $product.$name of type $tpe"
+ )
}
- def mapBody(param: TermName): List[Tree] = fieldWriters.map{ case (name, fieldWriter) =>
- q"""(${name.toString}, $fieldWriter.${writer.method.name}($param.$name))"""
+ def mapBody(param: TermName): List[Tree] = fieldWriters.map {
+ case (name, fieldWriter) =>
+ q"""(${name.toString}, $fieldWriter.${writer.method.name}($param.$name))"""
}
def data(param: TermName): Tree = q"""{