diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index d4cb1d8d1..dd98eac8f 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -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 @@ -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 @@ -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 diff --git a/zio-schema-avro/src/test/scala/zio/schema/codec/AvroSchemaCodecSpec.scala b/zio-schema-avro/src/test/scala/zio/schema/codec/AvroSchemaCodecSpec.scala index 8260f256d..58c483bf3 100644 --- a/zio-schema-avro/src/test/scala/zio/schema/codec/AvroSchemaCodecSpec.scala +++ b/zio-schema-avro/src/test/scala/zio/schema/codec/AvroSchemaCodecSpec.scala @@ -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] diff --git a/zio-schema-derivation/shared/src/main/scala-2/zio/schema/DeriveSchema.scala b/zio-schema-derivation/shared/src/main/scala-2/zio/schema/DeriveSchema.scala index 2f2420cde..6a9262e65 100644 --- a/zio-schema-derivation/shared/src/main/scala-2/zio/schema/DeriveSchema.scala +++ b/zio-schema-derivation/shared/src/main/scala-2/zio/schema/DeriveSchema.scala @@ -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)) diff --git a/zio-schema-derivation/shared/src/test/scala/zio/schema/DeriveSchemaSpec.scala b/zio-schema-derivation/shared/src/test/scala/zio/schema/DeriveSchemaSpec.scala index 7927478c9..04cae53f6 100644 --- a/zio-schema-derivation/shared/src/test/scala/zio/schema/DeriveSchemaSpec.scala +++ b/zio-schema-derivation/shared/src/test/scala/zio/schema/DeriveSchemaSpec.scala @@ -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") { @@ -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" ) { @@ -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)) + } + }