aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJon Pretty <jon.pretty@propensive.com>2017-12-28 12:01:25 +0000
committerJon Pretty <jon.pretty@propensive.com>2017-12-28 12:01:25 +0000
commit038a0b1bf3c0f5db872bf1be289ff21f03cc6002 (patch)
tree949712e2583f76159cfaeb97b5c49e6583c7749b /core
parentd4f51be01aba1ff32707a91d44f85272b7c2f562 (diff)
parent579cdb1281e7f3e16b13abc591c5e06b1aa32db5 (diff)
downloadmagnolia-038a0b1bf3c0f5db872bf1be289ff21f03cc6002.tar.gz
magnolia-038a0b1bf3c0f5db872bf1be289ff21f03cc6002.tar.bz2
magnolia-038a0b1bf3c0f5db872bf1be289ff21f03cc6002.zip
Merge branch 'md/rawconstruct' of https://github.com/sirthias/magnolia into sirthias-md/rawconstruct
Diffstat (limited to 'core')
-rw-r--r--core/shared/src/main/scala/interface.scala17
-rw-r--r--core/shared/src/main/scala/magnolia.scala27
2 files changed, 31 insertions, 13 deletions
diff --git a/core/shared/src/main/scala/interface.scala b/core/shared/src/main/scala/interface.scala
index a82a54c..b06f350 100644
--- a/core/shared/src/main/scala/interface.scala
+++ b/core/shared/src/main/scala/interface.scala
@@ -123,7 +123,22 @@ abstract class CaseClass[Typeclass[_], Type] private[magnolia] (
* @param makeParam lambda for converting a generic [[Param]] into the value to be used for
* this parameter in the construction of a new instance of the case class
* @return a new instance of the case class */
- def construct[Return](makeParam: Param[Typeclass, Type] => Return): Type
+ final def construct[Return](makeParam: Param[Typeclass, Type] => Return): Type =
+ rawConstruct(parameters map makeParam)
+
+ /** constructs a new instance of the case class type
+ *
+ * Like [[construct]] this method is implemented by Magnolia and let's you construct case class
+ * instances generically in user code, without knowing their type concretely.
+ *
+ * `rawConstruct`, however, is more low-level in that it expects you to provide a [[Seq]]
+ * containing all the field values for the case class type, in order and with the correct types.
+ *
+ * @param fieldValues contains the field values for the case class instance to be constructed,
+ * in order and with the correct types.
+ * @return a new instance of the case class
+ * @throws IllegalArgumentException if the size of `paramValues` differs from the size of [[parameters]] */
+ def rawConstruct(fieldValues: Seq[Any]): Type
/** a sequence of [[Param]] objects representing all of the parameters in the case class
*
diff --git a/core/shared/src/main/scala/magnolia.scala b/core/shared/src/main/scala/magnolia.scala
index 2e7dae8..3445dbc 100644
--- a/core/shared/src/main/scala/magnolia.scala
+++ b/core/shared/src/main/scala/magnolia.scala
@@ -335,7 +335,7 @@ object Magnolia {
val caseParams = caseParamsReversed.reverse
val paramsVal: TermName = TermName(c.freshName("parameters"))
- val fnVal: TermName = TermName(c.freshName("fn"))
+ val fieldValues: TermName = TermName(c.freshName("fieldValues"))
val preAssignments = caseParams.map(_.typeclass)
@@ -383,15 +383,18 @@ object Magnolia {
false,
$isValueClass,
$paramsVal,
- ($fnVal: $magnoliaPkg.Param[$typeConstructor, $genericType] => Any) =>
- new $genericType(..${caseParams.zipWithIndex.map {
- case (typeclass, idx) =>
- val arg = q"$fnVal($paramsVal($idx)).asInstanceOf[${typeclass.paramType}]"
- if (typeclass.repeated) q"$arg: _*" else arg
- }})
- ))
- }"""
- )
+ ($fieldValues: $scalaPkg.Seq[Any]) => {
+ if ($fieldValues.lengthCompare($paramsVal.length) != 0) {
+ val msg = "`" + $className + "` has " + $paramsVal.length + " fields, not " + $fieldValues.size
+ throw new java.lang.IllegalArgumentException(msg)
+ }
+ new $genericType(..${
+ caseParams.zipWithIndex.map { case (typeclass, idx) =>
+ val arg = q"$fieldValues($idx).asInstanceOf[${typeclass.paramType}]"
+ if (typeclass.repeated) q"$arg: _*" else arg
+ }
+ })}))
+ }""")
)
} else if (isSealedTrait) {
val genericSubtypes = classType.get.knownDirectSubclasses.to[List]
@@ -542,9 +545,9 @@ object Magnolia {
obj: Boolean,
valClass: Boolean,
params: Array[Param[Tc, T]],
- constructor: (Param[Tc, T] => Any) => T): CaseClass[Tc, T] =
+ constructor: Seq[Any] => T): CaseClass[Tc, T] =
new CaseClass[Tc, T](name, obj, valClass, params) {
- def construct[R](param: Param[Tc, T] => R): T = constructor(param)
+ def rawConstruct(fieldValues: Seq[Any]): T = constructor(fieldValues)
}
}