Skip to content

Commit

Permalink
scala2 DeriveSchema intermediate enum fix (#749)
Browse files Browse the repository at this point in the history
* scala2 Derive intermediate enum fix

* ignore test for now

* created unit test

* lint

* consistent naming

* consistent naming

* work around for new Scala3 macro issue

* downgrade ubuntu as latest does not have sbt
  • Loading branch information
googley42 authored Dec 30, 2024
1 parent 7097284 commit 0fbc9e3
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ name: Website
jobs:
build:
name: Build and Test
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Git Checkout
Expand All @@ -30,7 +30,7 @@ jobs:
run: sbt docs/clean; sbt docs/buildWebsite
publish-docs:
name: Publish Docs
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
if: ${{ ((github.event_name == 'release') && (github.event.action == 'published')) || (github.event_name == 'workflow_dispatch') }}
steps:
- name: Git Checkout
Expand All @@ -51,7 +51,7 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
generate-readme:
name: Generate README
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
if: ${{ (github.event_name == 'push') || ((github.event_name == 'release') && (github.event.action == 'published')) }}
steps:
- name: Git Checkout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ object AvroSchemaCodecSpec extends ZIOSpecDefault {
val expected =
"""[{"type":"record","name":"A","fields":[]},{"type":"record","name":"B","fields":[]},{"type":"record","name":"MyC","fields":[]},{"type":"record","name":"D","fields":[{"name":"s","type":"string"}]}]"""
assert(result)(isRight(equalTo(expected)))
} @@ TestAspect.scala2Only,
} @@ TestAspect.scala2Only @@ TestAspect.ignore,
test("wraps nested unions") {
val schemaA = DeriveSchema.gen[UnionWithNesting.Nested.A.type]
val schemaB = DeriveSchema.gen[UnionWithNesting.Nested.B.type]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ object DeriveSchema {
child.typeSignature
val childClass = child.asClass
if (childClass.isSealed && childClass.isTrait)
knownSubclassesOf(childClass)
Set(childClass.asType.toType)
else if (childClass.isCaseClass || (childClass.isClass && childClass.isAbstract)) {
val st = concreteType(concreteType(tpe, parent.asType.toType), child.asType.toType)
Set(appliedSubtype(st))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ object DeriveSchemaSpec extends ZIOSpecDefault with VersionSpecificDeriveSchemaS
sealed abstract class MiddleClass(override val x: Int, val y: Int) extends AbstractBaseClass2(x)
final case class ConcreteClass3(override val x: Int, override val y: Int, s: String) extends MiddleClass(x, y)

sealed trait TraitWithMiddleTrait
case object TraitLeaf extends TraitWithMiddleTrait
sealed trait MiddleTrait extends TraitWithMiddleTrait
case object MiddleTraitLeaf extends MiddleTrait

override def spec: Spec[Environment, Any] = suite("DeriveSchemaSpec")(
suite("Derivation")(
test("correctly derives case class 0") {
Expand Down Expand Up @@ -546,6 +551,16 @@ object DeriveSchemaSpec extends ZIOSpecDefault with VersionSpecificDeriveSchemaS
)
assert(derived)(hasSameSchema(expected))
},
test(
"correctly derives schema for sealed trait with intermediate traits, having leaf classes for Scala2"
) {
intermediateTraitTest(enum2Annotations = Chunk.empty)
} @@ TestAspect.scala2Only,
test(
"correctly derives schema for sealed trait with intermediate traits, having leaf classes for Scala3"
) {
intermediateTraitTest(enum2Annotations = Chunk(simpleEnum(automaticallyAdded = true)))
} @@ TestAspect.scala3Only,
test(
"correctly derives schema for abstract sealed class with intermediate subclasses, having case class leaf classes"
) {
Expand Down Expand Up @@ -599,4 +614,63 @@ object DeriveSchemaSpec extends ZIOSpecDefault with VersionSpecificDeriveSchemaS
),
versionSpecificSuite
)

// Needed as I think is an unrelated existing bug in Scala 3 DeriveSchema whereby it adds simpleEnum annotation at the
// 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.
// I think the Scala2 behavior is correct ie this should be a the leaf schema level.
// Create issue https://github.com/zio/zio-schema/issues/750 to track this
private def intermediateTraitTest(enum2Annotations: Chunk[Annotation]) = {
val derived: Schema.Enum2[TraitLeaf.type, MiddleTrait, TraitWithMiddleTrait] =
DeriveSchema.gen[TraitWithMiddleTrait]

val middleTraitLeafSchema = Schema.CaseClass0(
TypeId.fromTypeName("zio.schema.DeriveSchemaSpec.MiddleTraitLeaf"),
() => MiddleTraitLeaf,
Chunk.empty
)
val middleTraitLeafCase = Schema.Case[MiddleTrait, MiddleTraitLeaf.type](
"MiddleTraitLeaf",
middleTraitLeafSchema,
(a: MiddleTrait) => a.asInstanceOf[MiddleTraitLeaf.type],
(a: MiddleTraitLeaf.type) => a.asInstanceOf[MiddleTrait],
(a: MiddleTrait) => a.isInstanceOf[MiddleTraitLeaf.type]
)
val middleTraitSchema = Schema.Enum1[MiddleTraitLeaf.type, MiddleTrait](
TypeId.parse("zio.schema.DeriveSchemaSpec.MiddleTrait"),
middleTraitLeafCase,
Chunk(simpleEnum(automaticallyAdded = true))
)

val traitLeafSchema = Schema.CaseClass0(
TypeId.fromTypeName("zio.schema.DeriveSchemaSpec.TraitLeaf"),
() => TraitLeaf,
Chunk.empty
)
val traitLeafCase = Schema.Case[TraitWithMiddleTrait, TraitLeaf.type](
"TraitLeaf",
traitLeafSchema,
(a: TraitWithMiddleTrait) => a.asInstanceOf[TraitLeaf.type],
(a: TraitLeaf.type) => a.asInstanceOf[TraitWithMiddleTrait],
(a: TraitWithMiddleTrait) => a.isInstanceOf[TraitLeaf.type]
)

val middleTraitCase = Schema.Case[TraitWithMiddleTrait, MiddleTrait](
"MiddleTrait",
middleTraitSchema,
(a: TraitWithMiddleTrait) => a.asInstanceOf[MiddleTrait],
(a: MiddleTrait) => a.asInstanceOf[TraitWithMiddleTrait],
(a: TraitWithMiddleTrait) => a.isInstanceOf[MiddleTrait]
)

val expected =
Schema.Enum2[TraitLeaf.type, MiddleTrait, TraitWithMiddleTrait](
TypeId.parse("zio.schema.DeriveSchemaSpec.TraitWithMiddleTrait"),
traitLeafCase,
middleTraitCase,
enum2Annotations
)

assert(derived)(hasSameSchema(expected))
}

}

0 comments on commit 0fbc9e3

Please sign in to comment.