Skip to content

Commit eb24b9e

Browse files
authored
Restore ability to derive schemas with Scala 2 for hierarchy of sum types(#822)
1 parent df60431 commit eb24b9e

File tree

3 files changed

+32
-69
lines changed

3 files changed

+32
-69
lines changed

zio-schema-derivation/shared/src/main/scala-2/zio/schema/DeriveSchema.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ object DeriveSchema {
563563
child.typeSignature
564564
val childClass = child.asClass
565565
if (childClass.isSealed && childClass.isTrait)
566-
Set(childClass.asType.toType)
566+
knownSubclassesOf(childClass)
567567
else if (childClass.isCaseClass || (childClass.isClass && childClass.isAbstract)) {
568568
val st = concreteType(concreteType(tpe, parent.asType.toType), child.asType.toType)
569569
Set(appliedSubtype(st))

zio-schema-derivation/shared/src/test/scala/zio/schema/DeriveSchemaSpec.scala

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -564,16 +564,6 @@ object DeriveSchemaSpec extends ZIOSpecDefault with VersionSpecificDeriveSchemaS
564564
)
565565
assert(derived)(hasSameSchema(expected))
566566
},
567-
test(
568-
"correctly derives schema for sealed trait with intermediate traits, having leaf classes for Scala2"
569-
) {
570-
intermediateTraitTest(enum2Annotations = Chunk.empty)
571-
} @@ TestAspect.scala2Only,
572-
test(
573-
"correctly derives schema for sealed trait with intermediate traits, having leaf classes for Scala3"
574-
) {
575-
intermediateTraitTest(enum2Annotations = Chunk(simpleEnum(automaticallyAdded = true)))
576-
} @@ TestAspect.scala3Only,
577567
test(
578568
"correctly derives schema for abstract sealed class with intermediate subclasses, having case class leaf classes"
579569
) {
@@ -628,62 +618,4 @@ object DeriveSchemaSpec extends ZIOSpecDefault with VersionSpecificDeriveSchemaS
628618
versionSpecificSuite
629619
)
630620

631-
// Needed as I think is an unrelated existing bug in Scala 3 DeriveSchema whereby it adds simpleEnum annotation at the
632-
// top level of the EnumN schema when one of the cases is a simple enum - however this does not happen with the Scala 2 macro.
633-
// I think the Scala2 behavior is correct ie this should be a the leaf schema level.
634-
// Create issue https://github.com/zio/zio-schema/issues/750 to track this
635-
private def intermediateTraitTest(enum2Annotations: Chunk[Annotation]) = {
636-
val derived: Schema.Enum2[TraitLeaf.type, MiddleTrait, TraitWithMiddleTrait] =
637-
DeriveSchema.gen[TraitWithMiddleTrait]
638-
639-
val middleTraitLeafSchema = Schema.CaseClass0(
640-
TypeId.fromTypeName("zio.schema.DeriveSchemaSpec.MiddleTraitLeaf"),
641-
() => MiddleTraitLeaf,
642-
Chunk.empty
643-
)
644-
val middleTraitLeafCase = Schema.Case[MiddleTrait, MiddleTraitLeaf.type](
645-
"MiddleTraitLeaf",
646-
middleTraitLeafSchema,
647-
(a: MiddleTrait) => a.asInstanceOf[MiddleTraitLeaf.type],
648-
(a: MiddleTraitLeaf.type) => a.asInstanceOf[MiddleTrait],
649-
(a: MiddleTrait) => a.isInstanceOf[MiddleTraitLeaf.type]
650-
)
651-
val middleTraitSchema = Schema.Enum1[MiddleTraitLeaf.type, MiddleTrait](
652-
TypeId.parse("zio.schema.DeriveSchemaSpec.MiddleTrait"),
653-
middleTraitLeafCase,
654-
Chunk(simpleEnum(automaticallyAdded = true))
655-
)
656-
657-
val traitLeafSchema = Schema.CaseClass0(
658-
TypeId.fromTypeName("zio.schema.DeriveSchemaSpec.TraitLeaf"),
659-
() => TraitLeaf,
660-
Chunk.empty
661-
)
662-
val traitLeafCase = Schema.Case[TraitWithMiddleTrait, TraitLeaf.type](
663-
"TraitLeaf",
664-
traitLeafSchema,
665-
(a: TraitWithMiddleTrait) => a.asInstanceOf[TraitLeaf.type],
666-
(a: TraitLeaf.type) => a.asInstanceOf[TraitWithMiddleTrait],
667-
(a: TraitWithMiddleTrait) => a.isInstanceOf[TraitLeaf.type]
668-
)
669-
670-
val middleTraitCase = Schema.Case[TraitWithMiddleTrait, MiddleTrait](
671-
"MiddleTrait",
672-
middleTraitSchema,
673-
(a: TraitWithMiddleTrait) => a.asInstanceOf[MiddleTrait],
674-
(a: MiddleTrait) => a.asInstanceOf[TraitWithMiddleTrait],
675-
(a: TraitWithMiddleTrait) => a.isInstanceOf[MiddleTrait]
676-
)
677-
678-
val expected =
679-
Schema.Enum2[TraitLeaf.type, MiddleTrait, TraitWithMiddleTrait](
680-
TypeId.parse("zio.schema.DeriveSchemaSpec.TraitWithMiddleTrait"),
681-
traitLeafCase,
682-
middleTraitCase,
683-
enum2Annotations
684-
)
685-
686-
assert(derived)(hasSameSchema(expected))
687-
}
688-
689621
}

zio-schema-json/shared/src/test/scala/zio/schema/codec/JsonCodecSpec.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,12 @@ object JsonCodecSpec extends ZIOSpecDefault {
17891789
RecordExampleWithDiscriminator(f1 = Some("test"), f2 = None)
17901790
)
17911791
},
1792+
test("nested ADT with discriminator field") {
1793+
assertEncodesThenDecodes(
1794+
Schema[GeoJSON.GeoJSON],
1795+
GeoJSON.Feature(geometry = GeoJSON.Point(1.0 -> 2.0))
1796+
)
1797+
} @@ TestAspect.scala2Only,
17921798
test("of case classes with discriminator") {
17931799
assertEncodesThenDecodes(Schema[Command], Command.Cash) &>
17941800
assertEncodesThenDecodes(Schema[Command], Command.Buy(100))
@@ -3094,4 +3100,29 @@ object JsonCodecSpec extends ZIOSpecDefault {
30943100
object BigProduct {
30953101
implicit val schema: Schema[BigProduct] = DeriveSchema.gen
30963102
}
3103+
3104+
object GeoJSON {
3105+
@discriminatorName("type") sealed trait Geometry extends Product with Serializable
3106+
@discriminatorName("type") sealed trait SimpleGeometry extends Geometry
3107+
case class Point(coordinates: (Double, Double)) extends SimpleGeometry
3108+
case class MultiPoint(coordinates: Chunk[(Double, Double)]) extends SimpleGeometry
3109+
case class LineString(coordinates: Chunk[(Double, Double)]) extends SimpleGeometry
3110+
case class MultiLineString(coordinates: Chunk[Chunk[(Double, Double)]]) extends SimpleGeometry
3111+
case class Polygon(coordinates: Chunk[Chunk[(Double, Double)]]) extends SimpleGeometry
3112+
case class MultiPolygon(coordinates: Chunk[Chunk[Chunk[(Double, Double)]]]) extends SimpleGeometry
3113+
case class GeometryCollection(geometries: Chunk[SimpleGeometry]) extends Geometry
3114+
@discriminatorName("type") sealed trait GeoJSON extends Product with Serializable
3115+
@discriminatorName("type") sealed trait SimpleGeoJSON extends GeoJSON
3116+
case class Feature(
3117+
properties: Map[String, String] = Map.empty,
3118+
geometry: Geometry,
3119+
bbox: Option[(Double, Double, Double, Double)] = None
3120+
) extends SimpleGeoJSON
3121+
case class FeatureCollection(features: Chunk[SimpleGeoJSON], bbox: Option[(Double, Double, Double, Double)] = None)
3122+
extends GeoJSON
3123+
3124+
object GeoJSON {
3125+
implicit lazy val schema: Schema[GeoJSON] = DeriveSchema.gen
3126+
}
3127+
}
30973128
}

0 commit comments

Comments
 (0)