Skip to content

Commit

Permalink
Fix: generic fields default for Scala 3, find default value for Scala 2
Browse files Browse the repository at this point in the history
  • Loading branch information
987Nabil committed Jun 29, 2023
1 parent f8394c1 commit cec3285
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,7 @@ object DeriveSchema {
val defaultApply = tpe.companion.member(TermName(s"apply$$default$$${i + 1}"))
Some(i -> defaultInit)
.filter(_ => defaultInit != NoSymbol)
.orElse(Some(i -> defaultApply))
.filter(_ => defaultApply != NoSymbol)
.orElse(Some(i -> defaultApply).filter(_ => defaultApply != NoSymbol))
} else None
}
.toMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,12 @@ private case class DeriveSchema()(using val ctx: Quotes) extends ReflectionUtils
.declaredMethod(s"$$apply$$default$$$i")
.headOption
)
.map(Select(Ref(from.companionModule), _).asExpr)
).zip(from.primaryConstructor.paramSymss.flatten.map(_.name)).collect{case (Some(expr), name) => name -> expr}.toMap
.map { s =>
val select = Select(Ref(from.companionModule), s)
if (select.isExpr) select.asExpr
else select.appliedToType(TypeRepr.of[Any]).asExpr
}
).zip(from.primaryConstructor.paramSymss.flatten.filter(!_.isTypeParam).map(_.name)).collect{ case (Some(expr), name) => name -> expr }.toMap

private def fromConstructor(from: Symbol): scala.collection.Map[String, List[Expr[Any]]] = {
val defaults = defaultValues(from)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package zio.schema

import scala.annotation.nowarn
import scala.reflect.ClassTag

import zio.schema.Deriver.WrappedF
import zio.schema.Schema.Field
import zio.schema.StandardType.IntType
import zio.schema.annotation.fieldDefaultValue
import zio.test.{ Spec, TestEnvironment, ZIOSpecDefault, assertTrue }
import zio.{ Chunk, Scope }
import zio.test.{Spec, TestEnvironment, ZIOSpecDefault, assertTrue}
import zio.{Chunk, Scope}

object DeriveSpec extends ZIOSpecDefault with VersionSpecificDeriveSpec {
override def spec: Spec[TestEnvironment with Scope, Any] =
Expand Down Expand Up @@ -174,6 +174,19 @@ object DeriveSpec extends ZIOSpecDefault with VersionSpecificDeriveSpec {
.exists(a => a.isInstanceOf[fieldDefaultValue[_]] && a.asInstanceOf[fieldDefaultValue[Int]].value == 42)
)
},
test("use case class default values of generic class") {
val capturedSchema = Derive.derive[CapturedSchema, GenericRecordWithDefaultValue[Int]](schemaCapturer)
val annotations = capturedSchema.schema
.asInstanceOf[Schema.Record[GenericRecordWithDefaultValue[Int]]]
.fields(0)
.annotations
assertTrue {
annotations.exists { a =>
a.isInstanceOf[fieldDefaultValue[_]] &&
a.asInstanceOf[fieldDefaultValue[Option[Int]]].value == None
}
}
},
test("prefer field annotations over case class default values") {
val capturedSchema = Derive.derive[CapturedSchema, RecordWithDefaultValue](schemaCapturer)
val annotations = capturedSchema.schema
Expand Down Expand Up @@ -304,6 +317,15 @@ object DeriveSpec extends ZIOSpecDefault with VersionSpecificDeriveSpec {
implicit val schema: Schema[RecordWithDefaultValue] = DeriveSchema.gen[RecordWithDefaultValue]
}

case class GenericRecordWithDefaultValue[T](int: Option[T] = None, @fieldDefaultValue(52) int2: Int = 42)

object GenericRecordWithDefaultValue {
//explicitly Int, because generic implicit definition leads to "Schema derivation exceeded" error
implicit def schema: Schema[GenericRecordWithDefaultValue[Int]] = {
DeriveSchema.gen[GenericRecordWithDefaultValue[Int]]
}
}

sealed trait Enum1

object Enum1 {
Expand Down

0 comments on commit cec3285

Please sign in to comment.