aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Wright <kevin.wright@bradyplc.com>2018-02-01 14:42:05 +0000
committerKevin Wright <kevin.wright@bradyplc.com>2018-02-01 14:42:05 +0000
commit6660480a75b240b7ac613ed308e5b7f7ddfc6459 (patch)
tree2c85897a2ab4010438538351340f89356a28ad6a
parentbd1ca071286987bc148fda830aa3141f56891efb (diff)
downloadmagnolia-6660480a75b240b7ac613ed308e5b7f7ddfc6459.tar.gz
magnolia-6660480a75b240b7ac613ed308e5b7f7ddfc6459.tar.bz2
magnolia-6660480a75b240b7ac613ed308e5b7f7ddfc6459.zip
Added top-level annotation capture
-rw-r--r--core/shared/src/main/scala/interface.scala30
-rw-r--r--core/shared/src/main/scala/magnolia.scala33
-rw-r--r--examples/shared/src/main/scala/show.scala5
-rw-r--r--tests/src/main/scala/tests.scala4
4 files changed, 55 insertions, 17 deletions
diff --git a/core/shared/src/main/scala/interface.scala b/core/shared/src/main/scala/interface.scala
index 427c84c..97ea5b7 100644
--- a/core/shared/src/main/scala/interface.scala
+++ b/core/shared/src/main/scala/interface.scala
@@ -92,7 +92,13 @@ trait Param[Typeclass[_], Type] {
* @return the parameter value */
def dereference(param: Type): PType
- def annotations: Seq[Any]
+ def annotationsArray: Array[Any]
+
+ /** a sequence of objects representing all of the annotations on the case class
+ *
+ * For efficiency, this sequence is implemented by an `Array`, but upcast to a
+ * [[scala.collection.Seq]] to hide the mutable collection API. */
+ final def annotations: Seq[Any] = annotationsArray
override def toString: String = s"Param($label)"
}
@@ -113,7 +119,8 @@ abstract class CaseClass[Typeclass[_], Type] private[magnolia] (
val typeName: TypeName,
val isObject: Boolean,
val isValueClass: Boolean,
- parametersArray: Array[Param[Typeclass, Type]]
+ parametersArray: Array[Param[Typeclass, Type]],
+ annotationsArray: Array[Any]
) {
override def toString: String = s"CaseClass(${typeName.full}, ${parameters.mkString(",")})"
@@ -152,6 +159,12 @@ abstract class CaseClass[Typeclass[_], Type] private[magnolia] (
* For efficiency, this sequence is implemented by an `Array`, but upcast to a
* [[scala.collection.Seq]] to hide the mutable collection API. */
final def parameters: Seq[Param[Typeclass, Type]] = parametersArray
+
+ /** a sequence of objects representing all of the annotations on the case class
+ *
+ * For efficiency, this sequence is implemented by an `Array`, but upcast to a
+ * [[scala.collection.Seq]] to hide the mutable collection API. */
+ final def annotations: Seq[Any] = annotationsArray
}
/** represents a sealed trait and the context required to construct a new typeclass instance
@@ -163,8 +176,11 @@ abstract class CaseClass[Typeclass[_], Type] private[magnolia] (
* @param subtypesArray an array of [[Subtype]] instances for each subtype in the sealed trait
* @tparam Typeclass type constructor for the typeclass being derived
* @tparam Type generic type of this parameter */
-final class SealedTrait[Typeclass[_], Type](val typeName: TypeName,
- subtypesArray: Array[Subtype[Typeclass, Type]]) {
+final class SealedTrait[Typeclass[_], Type](
+ val typeName: TypeName,
+ subtypesArray: Array[Subtype[Typeclass, Type]],
+ annotationsArray: Array[Any]
+) {
override def toString: String = s"SealedTrait($typeName, Array[${subtypes.mkString(",")}])"
@@ -192,6 +208,12 @@ final class SealedTrait[Typeclass[_], Type](val typeName: TypeName,
)
rec(0)
}
+
+ /** a sequence of objects representing all of the annotations on the topmost trait
+ *
+ * For efficiency, this sequence is implemented by an `Array`, but upcast to a
+ * [[scala.collection.Seq]] to hide the mutable collection API. */
+ final def annotations: Seq[Any] = annotationsArray
}
/**
diff --git a/core/shared/src/main/scala/magnolia.scala b/core/shared/src/main/scala/magnolia.scala
index 2e13061..00cf5ec 100644
--- a/core/shared/src/main/scala/magnolia.scala
+++ b/core/shared/src/main/scala/magnolia.scala
@@ -73,8 +73,6 @@ object Magnolia {
val magnoliaPkg = c.mirror.staticPackage("magnolia")
val scalaPkg = c.mirror.staticPackage("scala")
- val sciPkg = c.mirror.staticPackage("scala.collection.immutable")
-
val repeatedParamClass = definitions.RepeatedParamClass
val scalaSeqType = typeOf[Seq[_]].typeConstructor
@@ -163,6 +161,8 @@ object Magnolia {
val isCaseObject = classType.exists(_.isModuleClass)
val isSealedTrait = classType.exists(_.isSealed)
+ val classAnnotationTrees = typeSymbol.annotations.map(_.tree)
+
val primitives = Set(typeOf[Double],
typeOf[Float],
typeOf[Short],
@@ -187,8 +187,13 @@ object Magnolia {
val impl = q"""
$typeNameDef
${c.prefix}.combine($magnoliaPkg.Magnolia.caseClass[$typeConstructor, $genericType](
- $typeName, true, false, new $scalaPkg.Array(0), _ => ${genericType.typeSymbol.asClass.module})
- )
+ $typeName,
+ true,
+ false,
+ new $scalaPkg.Array(0),
+ $scalaPkg.Array(..$classAnnotationTrees),
+ _ => ${genericType.typeSymbol.asClass.module}
+ ))
"""
Some(impl)
} else if (isCaseClass || isValueClass) {
@@ -277,7 +282,12 @@ object Magnolia {
case (((CaseParam(param, repeated, typeclass, paramType, ref), defaultVal), annList), idx) =>
q"""$paramsVal($idx) = $magnoliaPkg.Magnolia.param[$typeConstructor, $genericType,
$paramType](
- ${param.name.decodedName.toString}, $repeated, $ref, $defaultVal, _.${param.name}, $sciPkg.List(..$annList)
+ ${param.name.decodedName.toString},
+ $repeated,
+ $ref,
+ $defaultVal,
+ _.${param.name},
+ $scalaPkg.Array(..$annList)
)"""
}
@@ -294,6 +304,7 @@ object Magnolia {
false,
$isValueClass,
$paramsVal,
+ $scalaPkg.Array(..$classAnnotationTrees),
($fieldValues: $scalaPkg.Seq[Any]) => {
if ($fieldValues.lengthCompare($paramsVal.length) != 0) {
val msg = "`" + $typeName.full + "` has " + $paramsVal.length + " fields, not " + $fieldValues.size
@@ -355,8 +366,9 @@ object Magnolia {
${c.prefix}.dispatch(new $magnoliaPkg.SealedTrait(
$typeName,
- $subtypesVal: $scalaPkg.Array[$magnoliaPkg.Subtype[$typeConstructor, $genericType]])
- ): $resultType
+ $subtypesVal: $scalaPkg.Array[$magnoliaPkg.Subtype[$typeConstructor, $genericType]],
+ $scalaPkg.Array(..$classAnnotationTrees)
+ )): $resultType
}""")
} else None
@@ -422,7 +434,7 @@ object Magnolia {
typeclassParam: => Tc[P],
defaultVal: => Option[P],
deref: T => P,
- annotationsParam: List[Any]
+ annotationsArrayParam: Array[Any]
): Param[Tc, T] = new Param[Tc, T] {
type PType = P
def label: String = name
@@ -430,7 +442,7 @@ object Magnolia {
def default: Option[PType] = defaultVal
def typeclass: Tc[PType] = typeclassParam
def dereference(t: T): PType = deref(t)
- def annotations: Seq[Any] = annotationsParam
+ def annotationsArray: Array[Any] = annotationsArrayParam
}
/** constructs a new [[CaseClass]] instance
@@ -441,8 +453,9 @@ object Magnolia {
obj: Boolean,
valClass: Boolean,
params: Array[Param[Tc, T]],
+ annotations: Array[Any],
constructor: Seq[Any] => T): CaseClass[Tc, T] =
- new CaseClass[Tc, T](name, obj, valClass, params) {
+ new CaseClass[Tc, T](name, obj, valClass, params, annotations) {
def rawConstruct(fieldValues: Seq[Any]): T = constructor(fieldValues)
}
}
diff --git a/examples/shared/src/main/scala/show.scala b/examples/shared/src/main/scala/show.scala
index 74914cb..9afc4c9 100644
--- a/examples/shared/src/main/scala/show.scala
+++ b/examples/shared/src/main/scala/show.scala
@@ -32,7 +32,10 @@ trait GenericShow[Out] {
s"${param.label}$attribStr=${param.typeclass.show(param.dereference(value))}"
}
- join(ctx.typeName.short, paramStrings)
+ val anns = ctx.annotations.filterNot(_.isInstanceOf[scala.SerialVersionUID])
+ val annotationStr = if (anns.isEmpty) "" else anns.mkString("{", ",", "}")
+
+ join(ctx.typeName.short + annotationStr, paramStrings)
}
}
diff --git a/tests/src/main/scala/tests.scala b/tests/src/main/scala/tests.scala
index 0f962d2..9153325 100644
--- a/tests/src/main/scala/tests.scala
+++ b/tests/src/main/scala/tests.scala
@@ -44,7 +44,7 @@ case object Blue extends Color
case class MyAnnotation(order: Int) extends StaticAnnotation
-case class Attributed(
+@MyAnnotation(0) case class Attributed(
@MyAnnotation(1) p1: String,
@MyAnnotation(2) p2: Int
)
@@ -369,7 +369,7 @@ object Tests extends TestApp {
test("capture attributes against params") {
Show.gen[Attributed].show(Attributed("xyz", 100))
- }.assert(_ == "Attributed(p1{MyAnnotation(1)}=xyz,p2{MyAnnotation(2)}=100)")
+ }.assert(_ == "Attributed{MyAnnotation(0)}(p1{MyAnnotation(1)}=xyz,p2{MyAnnotation(2)}=100)")
}
}