diff options
author | Mathias <mathias@decodified.com> | 2017-12-14 14:20:39 +0100 |
---|---|---|
committer | Mathias <mathias@decodified.com> | 2017-12-14 14:26:54 +0100 |
commit | 579cdb1281e7f3e16b13abc591c5e06b1aa32db5 (patch) | |
tree | b0575afd76ebcaa14a09cb42b2ea79f6b916c682 /core | |
parent | 379f0075ca8042945d8ff89212536894a96f56a8 (diff) | |
download | magnolia-579cdb1281e7f3e16b13abc591c5e06b1aa32db5.tar.gz magnolia-579cdb1281e7f3e16b13abc591c5e06b1aa32db5.tar.bz2 magnolia-579cdb1281e7f3e16b13abc591c5e06b1aa32db5.zip |
Add `CaseClass.rawConstruct` and new `Patcher` example
Diffstat (limited to 'core')
-rw-r--r-- | core/shared/src/main/scala/interface.scala | 17 | ||||
-rw-r--r-- | core/shared/src/main/scala/magnolia.scala | 27 |
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 193a6f9..86ef5b1 100644 --- a/core/shared/src/main/scala/interface.scala +++ b/core/shared/src/main/scala/interface.scala @@ -122,7 +122,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 f55dfa7..bc16a62 100644 --- a/core/shared/src/main/scala/magnolia.scala +++ b/core/shared/src/main/scala/magnolia.scala @@ -333,7 +333,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) @@ -381,15 +381,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] @@ -541,9 +544,9 @@ object Magnolia { obj: Boolean, valClass: Boolean, params: Array[Param[Tc, T]], - constructor: (Param[Tc, T] => Any) => 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) } } |