aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/scala/magnolia.scala
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/scala/magnolia.scala')
-rw-r--r--core/src/main/scala/magnolia.scala44
1 files changed, 27 insertions, 17 deletions
diff --git a/core/src/main/scala/magnolia.scala b/core/src/main/scala/magnolia.scala
index 8c3d823..c29c1fa 100644
--- a/core/src/main/scala/magnolia.scala
+++ b/core/src/main/scala/magnolia.scala
@@ -177,7 +177,11 @@ object Magnolia {
val isCaseClass = classType.map(_.isCaseClass).getOrElse(false)
val isCaseObject = classType.map(_.isModuleClass).getOrElse(false)
val isSealedTrait = classType.map(_.isSealed).getOrElse(false)
- val isValueClass = genericType <:< typeOf[AnyVal]
+
+ val primitives = Set(typeOf[Double], typeOf[Float], typeOf[Short], typeOf[Byte],
+ typeOf[Int], typeOf[Long], typeOf[Char], typeOf[Boolean])
+
+ val isValueClass = genericType <:< typeOf[AnyVal] && !primitives.exists(_ =:= genericType)
val resultType = appliedType(typeConstructor, genericType)
@@ -188,13 +192,14 @@ object Magnolia {
val className = obj.name.decodedName.toString
val impl = q"""
${c.prefix}.combine($magnoliaObj.caseClass[$typeConstructor, $genericType](
- $className, true, new $arrayCls(0), _ => $obj)
+ $className, true, false, new $arrayCls(0), _ => $obj)
)
"""
Some(Typeclass(genericType, impl))
- } else if (isCaseClass) {
+ } else if (isCaseClass || isValueClass) {
val caseClassParameters = genericType.decls.collect {
- case m: MethodSymbol if m.isCaseAccessor => m.asMethod
+ case m: MethodSymbol if m.isCaseAccessor || (isValueClass && m.isParamAccessor) =>
+ m.asMethod
}
val className = genericType.typeSymbol.name.decodedName.toString
@@ -203,6 +208,7 @@ object Magnolia {
paramType: c.Type,
ref: c.TermName)
+
val caseParamsReversed: List[CaseParam] = caseClassParameters.foldLeft(List[CaseParam]()) {
case (acc, param) =>
val paramName = param.name.decodedName.toString
@@ -214,7 +220,7 @@ object Magnolia {
val caseParamOpt = predefinedRef.map { backRef =>
CaseParam(param, q"()", paramType, backRef.ref) :: acc
}
-
+
caseParamOpt.getOrElse {
val derivedImplicit =
recurse(ProductType(paramName, genericType.toString), genericType, assignedName) {
@@ -236,17 +242,19 @@ object Magnolia {
val preAssignments = caseParams.map(_.typeclass)
- val caseClassCompanion = genericType.companion
- val constructorMethod = caseClassCompanion.decl(TermName("apply")).asMethod
- val indexedConstructorParams = constructorMethod.paramLists.head.map(_.asTerm).zipWithIndex
-
- val defaults = indexedConstructorParams.map {
- case (p, idx) =>
- if (p.isParamWithDefault) {
- val method = TermName("apply$default$" + (idx + 1))
- q"_root_.scala.Some(${genericType.typeSymbol.companionSymbol.asTerm}.$method)"
- } else q"_root_.scala.None"
- }
+ val defaults = if(!isValueClass) {
+ val caseClassCompanion = genericType.companion
+ val constructorMethod = caseClassCompanion.decl(TermName("apply")).asMethod
+ val indexedConstructorParams = constructorMethod.paramLists.head.map(_.asTerm).zipWithIndex
+
+ indexedConstructorParams.map {
+ case (p, idx) =>
+ if (p.isParamWithDefault) {
+ val method = TermName("apply$default$" + (idx + 1))
+ q"_root_.scala.Some(${genericType.typeSymbol.companionSymbol.asTerm}.$method)"
+ } else q"_root_.scala.None"
+ }
+ } else List(q"_root_.scala.None")
val assignments = caseParams.zip(defaults).zipWithIndex.map {
case ((CaseParam(param, typeclass, paramType, ref), defaultVal), idx) =>
@@ -268,6 +276,7 @@ object Magnolia {
${c.prefix}.combine($magnoliaObj.caseClass[$typeConstructor, $genericType](
$className,
false,
+ $isValueClass,
$paramsVal,
($fnVal: Param[$typeConstructor, $genericType] => Any) =>
new $genericType(..${caseParams.zipWithIndex.map {
@@ -421,9 +430,10 @@ object Magnolia {
* should not be called directly from users' code. */
def caseClass[Tc[_], T](name: String,
obj: Boolean,
+ valClass: Boolean,
params: Array[Param[Tc, T]],
constructor: (Param[Tc, T] => Any) => T) =
- new CaseClass[Tc, T](name, obj, params) {
+ new CaseClass[Tc, T](name, obj, valClass, params) {
def construct[R](param: Param[Tc, T] => R): T = constructor(param)
}
}