From 357bb1af7987a1c54b0536d3dc89f12fcd84b172 Mon Sep 17 00:00:00 2001 From: Mateusz Kubuszok Date: Thu, 11 Apr 2024 10:28:04 +0200 Subject: [PATCH 1/3] Create withSealedSubtypeHandled and withEnumCaseHandled as new names for withCoproductInstance, deprecate the last one (same for partials) --- .../chimney/benchmarks/Coproduct.scala | 4 +- .../scalaland/chimney/ProtobufOneOfSpec.scala | 6 +- .../dsl/PartialTransformerDefinition.scala | 50 ++++++++++-- .../chimney/dsl/PartialTransformerInto.scala | 50 ++++++++++-- .../chimney/dsl/TransformerDefinition.scala | 25 +++++- .../chimney/dsl/TransformerInto.scala | 26 ++++-- .../PartialTransformerDefinitionMacros.scala | 4 +- .../dsl/PartialTransformerIntoMacros.scala | 4 +- .../dsl/TransformerDefinitionMacros.scala | 2 +- .../dsl/TransformerIntoMacros.scala | 2 +- .../internal/runtime/RefinedJavaEnum.scala | 6 +- .../dsl/PartialTransformerDefinition.scala | 57 ++++++++++--- .../chimney/dsl/PartialTransformerInto.scala | 57 ++++++++++--- .../chimney/dsl/PatcherDefinition.scala | 4 +- .../scalaland/chimney/dsl/PatcherUsing.scala | 5 +- .../chimney/dsl/TransformerDefinition.scala | 30 +++++-- .../chimney/dsl/TransformerInto.scala | 33 +++++++- .../PartialTransformerDefinitionMacros.scala | 71 ++++++++-------- .../dsl/PartialTransformerIntoMacros.scala | 80 ++++++++----------- .../dsl/PatcherDefinitionMacros.scala | 20 ----- .../dsl/TransformerDefinitionMacros.scala | 50 +++++------- .../dsl/TransformerIntoMacros.scala | 44 ++++------ .../chimney/PartialTransformerEnumSpec.scala | 32 ++++---- .../chimney/TotalTransformerEnumSpec.scala | 16 ++-- .../chimney/fixtures/NumbersEnums.scala | 8 +- .../io/scalaland/chimney/IssuesSpec.scala | 40 +++++----- ...artialTransformerSealedHierarchySpec.scala | 32 ++++---- .../TotalTransformerSealedHierarchySpec.scala | 16 ++-- .../scalaland/chimney/fixtures/Numbers.scala | 8 +- .../PartialTransformerJavaEnumSpec.scala | 20 ++--- .../TotalTransformerJavaEnumSpec.scala | 10 +-- docs/docs/cookbook.md | 6 +- docs/docs/supported-transformations.md | 44 +++++----- 33 files changed, 525 insertions(+), 337 deletions(-) delete mode 100644 chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PatcherDefinitionMacros.scala diff --git a/benchmarks/src/main/scala/io/scalaland/chimney/benchmarks/Coproduct.scala b/benchmarks/src/main/scala/io/scalaland/chimney/benchmarks/Coproduct.scala index 483400f05..baa388250 100644 --- a/benchmarks/src/main/scala/io/scalaland/chimney/benchmarks/Coproduct.scala +++ b/benchmarks/src/main/scala/io/scalaland/chimney/benchmarks/Coproduct.scala @@ -11,7 +11,7 @@ class Coproduct extends CommonBenchmarkSettings { private val color2ChannelT = Transformer.derive[Color, Channel] private val channel2ColorT = Transformer .define[Channel, Color] - .withCoproductInstance { (_: Channel.Alpha.type) => + .withSealedSubtypeHandled { (_: Channel.Alpha.type) => Color.Blue } .buildTransformer @@ -31,7 +31,7 @@ class Coproduct extends CommonBenchmarkSettings { color .transformInto[Channel] .into[Color] - .withCoproductInstance { (_: Channel.Alpha.type) => + .withSealedSubtypeHandled { (_: Channel.Alpha.type) => Color.Blue } .transform diff --git a/chimney-protobufs/src/test/scala/io/scalaland/chimney/ProtobufOneOfSpec.scala b/chimney-protobufs/src/test/scala/io/scalaland/chimney/ProtobufOneOfSpec.scala index 5a81be88e..d90ab1fab 100644 --- a/chimney-protobufs/src/test/scala/io/scalaland/chimney/ProtobufOneOfSpec.scala +++ b/chimney-protobufs/src/test/scala/io/scalaland/chimney/ProtobufOneOfSpec.scala @@ -21,7 +21,7 @@ class ProtobufOneOfSpec extends ChimneySpec { pbType.value .intoPartial[addressbook.AddressBookType] - .withCoproductInstancePartial[pb.addressbook.AddressBookType.Value.Empty.type](_ => partial.Result.fromEmpty) + .withSealedSubtypeHandledPartial[pb.addressbook.AddressBookType.Value.Empty.type](_ => partial.Result.fromEmpty) .transform .asOption ==> Some(domainType) locally { @@ -40,8 +40,8 @@ class ProtobufOneOfSpec extends ChimneySpec { pbStatus .intoPartial[order.CustomerStatus] - .withCoproductInstancePartial[pb.order.CustomerStatus.Empty.type](_ => partial.Result.fromEmpty) - .withCoproductInstance[pb.order.CustomerStatus.NonEmpty](_.transformInto[order.CustomerStatus]) + .withSealedSubtypeHandledPartial[pb.order.CustomerStatus.Empty.type](_ => partial.Result.fromEmpty) + .withSealedSubtypeHandled[pb.order.CustomerStatus.NonEmpty](_.transformInto[order.CustomerStatus]) .transform .asOption ==> Some(domainStatus) } diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala index 853206e12..139b953f4 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala @@ -123,7 +123,7 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = macro PartialTransformerDefinitionMacros.withFieldRenamedImpl[From, To, Overrides, Flags] - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -132,18 +132,37 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] + * + * @since 1.0.0 + */ + def withSealedSubtypeHandled[Subtype]( + f: Subtype => To + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandled[Subtype]( + f: Subtype => To + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.7.0 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") def withCoproductInstance[Subtype]( f: Subtype => To ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - macro PartialTransformerDefinitionMacros.withCoproductInstanceImpl[From, To, Overrides, Flags, Subtype] + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] - /** Use `f` to calculate the (missing) coproduct instance partial result when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype's partial.Result when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -152,16 +171,35 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] * * @since 0.7.0 */ + def withSealedSubtypeHandledPartial[Subtype]( + f: Subtype => partial.Result[To] + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandledPartial]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandledPartial[Subtype]( + f: Subtype => partial.Result[To] + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandledPartial]]. + * + * @since 0.7.0 + */ + @deprecated("Use .withSealedSubtypeHandledPartial or .withEnumCaseHandledPartial for more clarity", "1.0.0") def withCoproductInstancePartial[Subtype]( f: Subtype => partial.Result[To] ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - macro PartialTransformerDefinitionMacros.withCoproductInstancePartialImpl[From, To, Overrides, Flags, Subtype] + macro PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] /** Use `f` instead of the primary constructor to construct the `To` value. * diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala index 25d66aec6..107452533 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala @@ -126,7 +126,7 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = macro PartialTransformerIntoMacros.withFieldRenamedImpl[From, To, Overrides, Flags] - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -135,18 +135,37 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerInto]] + * + * @since 1.0.0 + */ + def withSealedSubtypeHandled[Subtype]( + f: Subtype => To + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandled[Subtype]( + f: Subtype => To + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.7.0 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") def withCoproductInstance[Subtype]( f: Subtype => To ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = - macro PartialTransformerIntoMacros.withCoproductInstanceImpl[From, To, Overrides, Flags, Subtype] + macro PartialTransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] - /** Use `f` to calculate the (missing) coproduct instance partial result when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype's partial.Result when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -155,16 +174,35 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerInto]] + * + * @since 1.0.0 + */ + def withSealedSubtypeHandledPartial[Subtype]( + f: Subtype => partial.Result[To] + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandledPartial]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandledPartial[Subtype]( + f: Subtype => partial.Result[To] + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandledPartial]]. * * @since 0.7.0 */ + @deprecated("Use .withSealedSubtypeHandledPartial or .withEnumCaseHandledPartial for more clarity", "1.0.0") def withCoproductInstancePartial[Subtype]( f: Subtype => partial.Result[To] ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = - macro PartialTransformerIntoMacros.withCoproductInstancePartialImpl[From, To, Overrides, Flags, Subtype] + macro PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl[From, To, Overrides, Flags, Subtype] /** Use `f` instead of the primary constructor to construct the `To` value. * diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala index e221e81e0..149e493d3 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala @@ -94,7 +94,7 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = macro TransformerDefinitionMacros.withFieldRenamedImpl[From, To, Overrides, Flags] - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -103,16 +103,35 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.TransformerDefinition]] + * + * @since 1.0.0 + */ + def withSealedSubtypeHandled[Subtype]( + f: Subtype => To + ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro TransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandled[Subtype]( + f: Subtype => To + ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + macro TransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.4.0 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") def withCoproductInstance[Subtype]( f: Subtype => To ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - macro TransformerDefinitionMacros.withCoproductInstanceImpl[From, To, Overrides, Flags, Subtype] + macro TransformerDefinitionMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] /** Use `f` instead of the primary constructor to construct the `To` value. * diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala index 07c985589..1394961a3 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala @@ -99,13 +99,29 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance@param f function to calculate values of components that cannot be mapped automatically + * @tparam Subtype type of sealed/enum instance + * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.TransformerInto]] + * + * @since 1.0.0 + */ + def withSealedSubtypeHandled[Subtype](f: Subtype => To): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro TransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + def withEnumCaseHandled[Subtype](f: Subtype => To): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = + macro TransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.1.2 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") def withCoproductInstance[Subtype](f: Subtype => To): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = - macro TransformerIntoMacros.withCoproductInstanceImpl[From, To, Overrides, Flags, Subtype] + macro TransformerIntoMacros.withSealedSubtypeHandledImpl[From, To, Overrides, Flags, Subtype] /** Use `f` instead of the primary constructor to construct the `To` value. * @@ -121,9 +137,9 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < * * @since 0.8.4 */ - def withConstructor[Ctor]( - f: Ctor - )(implicit ev: IsFunction.Of[Ctor, To]): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = + def withConstructor[Ctor](f: Ctor)(implicit + ev: IsFunction.Of[Ctor, To] + ): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = macro TransformerIntoMacros.withConstructorImpl[From, To, Overrides, Flags] /** Apply configured transformation in-place. diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala index 2a9b3776b..66314fcf0 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala @@ -79,7 +79,7 @@ class PartialTransformerDefinitionMacros(val c: whitebox.Context) extends utils. }.applyFromSelectors(selectorFrom, selectorTo) ) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, @@ -96,7 +96,7 @@ class PartialTransformerDefinitionMacros(val c: whitebox.Context) extends utils. ]] }.applyJavaEnumFixFromClosureSignature[Subtype](f) - def withCoproductInstancePartialImpl[ + def withSealedSubtypeHandledPartialImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala index fd8a5ea8f..347f049b8 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala @@ -80,7 +80,7 @@ class PartialTransformerIntoMacros(val c: whitebox.Context) extends utils.DslMac }.applyFromSelectors(selectorFrom, selectorTo) ) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, @@ -97,7 +97,7 @@ class PartialTransformerIntoMacros(val c: whitebox.Context) extends utils.DslMac ]] }.applyJavaEnumFixFromClosureSignature[Subtype](f) - def withCoproductInstancePartialImpl[ + def withSealedSubtypeHandledPartialImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala index 6416ad951..ba7bc8fb4 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala @@ -52,7 +52,7 @@ class TransformerDefinitionMacros(val c: whitebox.Context) extends utils.DslMacr }.applyFromSelectors(selectorFrom, selectorTo) ) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala index 76fe6e13a..ee595d249 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala @@ -52,7 +52,7 @@ class TransformerIntoMacros(val c: whitebox.Context) extends utils.DslMacroUtils }.applyFromSelectors(selectorFrom, selectorTo) ) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: WeakTypeTag, To: WeakTypeTag, Overrides <: TransformerOverrides: WeakTypeTag, diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/runtime/RefinedJavaEnum.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/runtime/RefinedJavaEnum.scala index c6eea6f18..c82087aab 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/runtime/RefinedJavaEnum.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/runtime/RefinedJavaEnum.scala @@ -2,11 +2,11 @@ package io.scalaland.chimney.internal.runtime /** Apparently, `com.mypackage.JavaEnum.Value.type` is not a thing on Scala 2. This means that: * - * withCoproductInstance[com.mypackage.JavaEnum.Value.type] { value => ... } + * withSealedSubtypeHandled[com.mypackage.JavaEnum.Value.type] { value => ... } * * is ALWAYS treated as: * - * withCoproductInstance[com.mypackage.JavaEnum] { value => ... } + * withSealedSubtypeHandled[com.mypackage.JavaEnum] { value => ... } * * matching on ALL values of `com.mypackage.JavaEnum`. Probably not what you want. * @@ -14,7 +14,7 @@ package io.scalaland.chimney.internal.runtime * in pattern-matching), it will be upcasted to `JavaEnum`. We are only able to read it by reading a whole function's * tree: * - * withCoproductInstance { (value: com.mypackage.JavaEnum.Value.type) => ... } + * withSealedSubtypeHandled { (value: com.mypackage.JavaEnum.Value.type) => ... } * * and we are only able to store it for DSL by encoding the name read from the tree with a dedicated type from below. * diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala index 84d0cff60..0472a6825 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala @@ -1,5 +1,6 @@ package io.scalaland.chimney.dsl +import io.scalaland.chimney.internal.compiletime.derivation.transformer.TransformerMacros import io.scalaland.chimney.{partial, PartialTransformer} import io.scalaland.chimney.internal.compiletime.dsl.* import io.scalaland.chimney.internal.runtime.{IsFunction, TransformerFlags, TransformerOverrides, WithRuntimeDataStore} @@ -122,9 +123,9 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr inline selectorFrom: From => T, inline selectorTo: To => U ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - ${ PartialTransformerDefinitionMacros.withFieldRenamed('this, 'selectorFrom, 'selectorTo) } + ${ PartialTransformerDefinitionMacros.withFieldRenamedImpl('this, 'selectorFrom, 'selectorTo) } - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation expects that coproducts * to have matching names of its components, and for every component in `To` field's type there is matching component @@ -132,18 +133,37 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] * - * @since 0.7.0 + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandled[Subtype]( + inline f: Subtype => To + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandled[Subtype]( + inline f: Subtype => To + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandled]]. + * + * @since 0.1.2 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") transparent inline def withCoproductInstance[Subtype]( inline f: Subtype => To ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - ${ PartialTransformerDefinitionMacros.withCoproductInstance('this, 'f) } + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } - /** Use `f` to calculate the (missing) coproduct instance partial result when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype's partial.Result when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation * expects that coproducts to have matching names of its components, and for every component @@ -152,16 +172,35 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] + * + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandledPartial[Subtype]( + inline f: Subtype => partial.Result[To] + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandledPartial]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandledPartial[Subtype]( + inline f: Subtype => partial.Result[To] + ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandledPartial]]. * * @since 0.7.0 */ + @deprecated("Use .withSealedSubtypeHandledPartial or .withEnumCaseHandledPartial for more clarity", "1.0.0") transparent inline def withCoproductInstancePartial[Subtype]( inline f: Subtype => partial.Result[To] ): PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - ${ PartialTransformerDefinitionMacros.withCoproductInstancePartial('this, 'f) } + ${ PartialTransformerDefinitionMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } /** Use `f` instead of the primary constructor to construct the `To` value. * @@ -215,7 +254,7 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr inline def buildTransformer[ImplicitScopeFlags <: TransformerFlags](using tc: TransformerConfiguration[ImplicitScopeFlags] ): PartialTransformer[From, To] = - ${ PartialTransformerDefinitionMacros.buildTransformer[From, To, Overrides, Flags, ImplicitScopeFlags]('this) } + ${ TransformerMacros.derivePartialTransformerWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags]('this) } private[chimney] def addOverride(overrideData: Any): this.type = new PartialTransformerDefinition(overrideData +: runtimeData).asInstanceOf[this.type] diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala index be1868440..27b217b39 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala @@ -1,5 +1,6 @@ package io.scalaland.chimney.dsl +import io.scalaland.chimney.internal.compiletime.derivation.transformer.TransformerMacros import io.scalaland.chimney.internal.compiletime.dsl import io.scalaland.chimney.partial import io.scalaland.chimney.internal.compiletime.dsl.PartialTransformerIntoMacros @@ -126,7 +127,7 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = ${ PartialTransformerIntoMacros.withFieldRenamedImpl('this, 'selectorFrom, 'selectorTo) } - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation expects that coproducts * to have matching names of its components, and for every component in `To` field's type there is matching component @@ -134,18 +135,37 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerInto]] * - * @since 0.7.0 + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandled[Subtype]( + inline f: Subtype => To + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandled[Subtype]( + inline f: Subtype => To + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandled]]. + * + * @since 0.1.2 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") transparent inline def withCoproductInstance[Subtype]( inline f: Subtype => To ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = - ${ PartialTransformerIntoMacros.withCoproductInstanceImpl('this, 'f) } + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } - /** Use `f` to calculate the (missing) coproduct instance partial result when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype's partial.Result when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation expects that coproducts * to have matching names of its components, and for every component in `To` field's type there is matching component @@ -153,16 +173,35 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.PartialTransformerInto]] + * + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandledPartial[Subtype]( + inline f: Subtype => partial.Result[To] + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandledPartial]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandledPartial[Subtype]( + inline f: Subtype => partial.Result[To] + ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandledPartial]]. * * @since 0.7.0 */ + @deprecated("Use .withSealedSubtypeHandledPartial or .withEnumCaseHandledPartial for more clarity", "1.0.0") transparent inline def withCoproductInstancePartial[Subtype]( inline f: Subtype => partial.Result[To] ): PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags] = - ${ PartialTransformerIntoMacros.withCoproductInstancePartialImpl('this, 'f) } + ${ PartialTransformerIntoMacros.withSealedSubtypeHandledPartialImpl('this, 'f) } /** Use `f` instead of the primary constructor to construct the `To` value. * @@ -215,7 +254,7 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, tc: TransformerConfiguration[ImplicitScopeFlags] ): partial.Result[To] = ${ - PartialTransformerIntoMacros.transform[From, To, Overrides, Flags, ImplicitScopeFlags]( + TransformerMacros.derivePartialTransformerResultWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags]( 'source, 'td, failFast = false @@ -235,7 +274,7 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, tc: TransformerConfiguration[ImplicitScopeFlags] ): partial.Result[To] = ${ - PartialTransformerIntoMacros.transform[From, To, Overrides, Flags, ImplicitScopeFlags]( + TransformerMacros.derivePartialTransformerResultWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags]( 'source, 'td, failFast = true diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherDefinition.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherDefinition.scala index 1faaa1b60..ff277cf95 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherDefinition.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherDefinition.scala @@ -2,7 +2,7 @@ package io.scalaland.chimney.dsl import io.scalaland.chimney.Patcher import io.scalaland.chimney.internal.* -import io.scalaland.chimney.internal.compiletime.dsl.* +import io.scalaland.chimney.internal.compiletime.derivation.patcher.PatcherMacros import io.scalaland.chimney.internal.runtime.{PatcherFlags, PatcherOverrides} /** Allows customization of [[io.scalaland.chimney.Patcher]] derivation. @@ -29,5 +29,5 @@ final class PatcherDefinition[A, Patch, Overrides <: PatcherOverrides, Flags <: inline def buildPatcher[ImplicitScopeFlags <: PatcherFlags](using tc: PatcherConfiguration[ImplicitScopeFlags] ): Patcher[A, Patch] = - ${ PatcherDefinitionMacros.buildPatcher[A, Patch, Overrides, Flags, ImplicitScopeFlags] } + ${ PatcherMacros.derivePatcherWithConfig[A, Patch, Overrides, Flags, ImplicitScopeFlags] } } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherUsing.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherUsing.scala index a7e385bc0..436a805eb 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherUsing.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PatcherUsing.scala @@ -28,7 +28,6 @@ final class PatcherUsing[A, Patch, Overrides <: PatcherOverrides, Flags <: Patch */ inline def patch[ImplicitScopeFlags <: PatcherFlags](using tc: PatcherConfiguration[ImplicitScopeFlags] - ): A = ${ - PatcherMacros.derivePatcherResultWithConfig[A, Patch, Overrides, Flags, ImplicitScopeFlags]('obj, 'objPatch) - } + ): A = + ${ PatcherMacros.derivePatcherResultWithConfig[A, Patch, Overrides, Flags, ImplicitScopeFlags]('obj, 'objPatch) } } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala index c9c1e2880..d3906c7ed 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala @@ -2,6 +2,7 @@ package io.scalaland.chimney.dsl import io.scalaland.chimney.Transformer import io.scalaland.chimney.internal.* +import io.scalaland.chimney.internal.compiletime.derivation.transformer.TransformerMacros import io.scalaland.chimney.internal.compiletime.dsl.* import io.scalaland.chimney.internal.runtime.{IsFunction, TransformerFlags, TransformerOverrides, WithRuntimeDataStore} @@ -94,9 +95,9 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F inline selectorFrom: From => T, inline selectorTo: To => U ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - ${ TransformerDefinitionMacros.withFieldRenamed('this, 'selectorFrom, 'selectorTo) } + ${ TransformerDefinitionMacros.withFieldRenamedImpl('this, 'selectorFrom, 'selectorTo) } - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another. + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation expects that coproducts * to have matching names of its components, and for every component in `To` field's type there is matching component @@ -104,16 +105,35 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance + * @tparam Subtype type of sealed/enum instance * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.TransformerDefinition]] + * + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandled[Subtype]( + inline f: Subtype => To + ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ TransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandled[Subtype]( + inline f: Subtype => To + ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = + ${ TransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.4.0 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") transparent inline def withCoproductInstance[Subtype]( inline f: Subtype => To ): TransformerDefinition[From, To, ? <: TransformerOverrides, Flags] = - ${ TransformerDefinitionMacros.withCoproductInstance('this, 'f) } + ${ TransformerDefinitionMacros.withSealedSubtypeHandledImpl('this, 'f) } /** Use `f` instead of the primary constructor to construct the `To` value. * @@ -146,7 +166,7 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F inline def buildTransformer[ImplicitScopeFlags <: TransformerFlags](using tc: TransformerConfiguration[ImplicitScopeFlags] ): Transformer[From, To] = - ${ TransformerDefinitionMacros.buildTransformer[From, To, Overrides, Flags, ImplicitScopeFlags]('this) } + ${ TransformerMacros.deriveTotalTransformerWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags]('this) } private[chimney] def addOverride(overrideData: Any): this.type = new TransformerDefinition(overrideData +: runtimeData).asInstanceOf[this.type] diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala index 0cea3df38..62c1c6616 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala @@ -88,7 +88,7 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < ): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = ${ TransformerIntoMacros.withFieldRenamedImpl('this, 'selectorFrom, 'selectorTo) } - /** Use `f` to calculate the (missing) coproduct instance when mapping one coproduct into another + /** Use `f` to calculate the unmatched subtype when mapping one sealed/enum into another. * * By default if mapping one coproduct in `From` into another coproduct in `To` derivation expects that coproducts * will have matching names of its components, and for every component in `To` field's type there is matching @@ -96,15 +96,35 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * - * @tparam Subtypetype of coproduct instance@param f function to calculate values of components that cannot be mapped automatically + * @tparam Subtype type of sealed/enum instance + * @param f function to calculate values of components that cannot be mapped automatically * @return [[io.scalaland.chimney.dsl.TransformerInto]] + * + * @since 1.0.0 + */ + transparent inline def withSealedSubtypeHandled[Subtype]( + inline f: Subtype => To + ): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ TransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Alias to [[withSealedSubtypeHandled]]. + * + * @since 1.0.0 + */ + transparent inline def withEnumCaseHandled[Subtype]( + inline f: Subtype => To + ): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = + ${ TransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } + + /** Renamed to [[withSealedSubtypeHandled]]. * * @since 0.1.2 */ + @deprecated("Use .withSealedSubtypeHandled or .withEnumCaseHandled for more clarity", "1.0.0") transparent inline def withCoproductInstance[Subtype]( inline f: Subtype => To ): TransformerInto[From, To, ? <: TransformerOverrides, Flags] = - ${ TransformerIntoMacros.withCoproductInstanceImpl('this, 'f) } + ${ TransformerIntoMacros.withSealedSubtypeHandledImpl('this, 'f) } /** Use `f` instead of the primary constructor to construct the `To` value. * @@ -137,7 +157,12 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < inline def transform[ImplicitScopeFlags <: TransformerFlags](using tc: TransformerConfiguration[ImplicitScopeFlags] ): To = - ${ TransformerIntoMacros.transform[From, To, Overrides, Flags, ImplicitScopeFlags]('source, 'td) } + ${ + TransformerMacros.deriveTotalTransformerResultWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags]( + 'source, + 'td + ) + } private[chimney] def addOverride(overrideData: Any): this.type = new TransformerInto(source, td.addOverride(overrideData)).asInstanceOf[this.type] diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala index dddbdf0ce..8c3516705 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerDefinitionMacros.scala @@ -21,12 +21,12 @@ object PartialTransformerDefinitionMacros { def withFieldConstImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[U] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -36,19 +36,19 @@ object PartialTransformerDefinitionMacros { '{ WithRuntimeDataStore .update($td, $value) - .asInstanceOf[PartialTransformerDefinition[From, To, Const[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerDefinition[From, To, Const[toPath, Overrides], Flags]] } }(selector) def withFieldConstPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[partial.Result[U]] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -61,7 +61,7 @@ object PartialTransformerDefinitionMacros { .asInstanceOf[PartialTransformerDefinition[ From, To, - ConstPartial[toPath, Tail], + ConstPartial[toPath, Overrides], Flags ]] } @@ -70,12 +70,12 @@ object PartialTransformerDefinitionMacros { def withFieldComputedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => U] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -85,19 +85,19 @@ object PartialTransformerDefinitionMacros { '{ WithRuntimeDataStore .update($td, $f) - .asInstanceOf[PartialTransformerDefinition[From, To, Computed[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerDefinition[From, To, Computed[toPath, Overrides], Flags]] } }(selector) def withFieldComputedPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => partial.Result[U]] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -110,21 +110,21 @@ object PartialTransformerDefinitionMacros { .asInstanceOf[PartialTransformerDefinition[ From, To, - ComputedPartial[toPath, Tail], + ComputedPartial[toPath, Overrides], Flags ]] } }(selector) - def withFieldRenamed[ + def withFieldRenamedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], selectorFrom: Expr[From => T], selectorTo: Expr[To => U] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -134,19 +134,19 @@ object PartialTransformerDefinitionMacros { (_: Type[toPath]) ?=> '{ $td.asInstanceOf[ - PartialTransformerDefinition[From, To, RenamedFrom[fromPath, toPath, Tail], Flags] + PartialTransformerDefinition[From, To, RenamedFrom[fromPath, toPath, Overrides], Flags] ] } }(selectorFrom, selectorTo) - def withCoproductInstance[ + def withSealedSubtypeHandledImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], f: Expr[Subtype => To] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = '{ @@ -155,19 +155,19 @@ object PartialTransformerDefinitionMacros { .asInstanceOf[PartialTransformerDefinition[ From, To, - CaseComputed[Path.Matching[Path.Root, Subtype], Tail], + CaseComputed[Path.Matching[Path.Root, Subtype], Overrides], Flags ]] } - def withCoproductInstancePartial[ + def withSealedSubtypeHandledPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], f: Expr[Subtype => partial.Result[To]] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = '{ @@ -176,7 +176,7 @@ object PartialTransformerDefinitionMacros { .asInstanceOf[PartialTransformerDefinition[ From, To, - CaseComputedPartial[Path.Matching[Path.Root, Subtype], Tail], + CaseComputedPartial[Path.Matching[Path.Root, Subtype], Overrides], Flags ]] } @@ -184,11 +184,11 @@ object PartialTransformerDefinitionMacros { def withConstructorImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + ti: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -197,18 +197,18 @@ object PartialTransformerDefinitionMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerDefinition[From, To, Constructor[args, Path.Root, Tail], Flags]] + .asInstanceOf[PartialTransformerDefinition[From, To, Constructor[args, Path.Root, Overrides], Flags]] } }(f) def withConstructorPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], + ti: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[PartialTransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -217,18 +217,23 @@ object PartialTransformerDefinitionMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerDefinition[From, To, ConstructorPartial[args, Path.Root, Tail], Flags]] + .asInstanceOf[PartialTransformerDefinition[ + From, + To, + ConstructorPartial[args, Path.Root, Overrides], + Flags + ]] } }(f) def buildTransformer[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, ImplicitScopeFlags <: TransformerFlags: Type ]( - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]] + td: Expr[PartialTransformerDefinition[From, To, Overrides, Flags]] )(using Quotes): Expr[PartialTransformer[From, To]] = - TransformerMacros.derivePartialTransformerWithConfig[From, To, Tail, Flags, ImplicitScopeFlags](td) + TransformerMacros.derivePartialTransformerWithConfig[From, To, Overrides, Flags, ImplicitScopeFlags](td) } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala index 2afce655f..5958e58b2 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PartialTransformerIntoMacros.scala @@ -21,12 +21,12 @@ object PartialTransformerIntoMacros { def withFieldConstImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[U] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -36,19 +36,19 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $value) - .asInstanceOf[PartialTransformerInto[From, To, Const[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, Const[toPath, Overrides], Flags]] } }(selector) def withFieldConstPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[partial.Result[U]] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -58,19 +58,19 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $value) - .asInstanceOf[PartialTransformerInto[From, To, ConstPartial[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, ConstPartial[toPath, Overrides], Flags]] } }(selector) def withFieldComputedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => U] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -80,19 +80,19 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerInto[From, To, Computed[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, Computed[toPath, Overrides], Flags]] } }(selector) def withFieldComputedPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => partial.Result[U]] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -102,19 +102,19 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerInto[From, To, ComputedPartial[toPath, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, ComputedPartial[toPath, Overrides], Flags]] } }(selector) def withFieldRenamedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], selectorFrom: Expr[From => T], selectorTo: Expr[To => U] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -124,35 +124,40 @@ object PartialTransformerIntoMacros { (_: Type[toPath]) ?=> '{ $ti.asInstanceOf[ - PartialTransformerInto[From, To, RenamedFrom[fromPath, toPath, Tail], Flags] + PartialTransformerInto[From, To, RenamedFrom[fromPath, toPath, Overrides], Flags] ] } }(selectorFrom, selectorTo) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], f: Expr[Subtype => To] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerInto[From, To, CaseComputed[Path.Matching[Path.Root, Subtype], Tail], Flags]] + .asInstanceOf[PartialTransformerInto[ + From, + To, + CaseComputed[Path.Matching[Path.Root, Subtype], Overrides], + Flags + ]] } - def withCoproductInstancePartialImpl[ + def withSealedSubtypeHandledPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], f: Expr[Subtype => partial.Result[To]] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = '{ @@ -161,7 +166,7 @@ object PartialTransformerIntoMacros { .asInstanceOf[PartialTransformerInto[ From, To, - CaseComputedPartial[Path.Matching[Path.Root, Subtype], Tail], + CaseComputedPartial[Path.Matching[Path.Root, Subtype], Overrides], Flags ]] } @@ -169,11 +174,11 @@ object PartialTransformerIntoMacros { def withConstructorImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -182,18 +187,18 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerInto[From, To, Constructor[args, Path.Root, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, Constructor[args, Path.Root, Overrides], Flags]] } }(f) def withConstructorPartialImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[PartialTransformerInto[From, To, Tail, Flags]], + ti: Expr[PartialTransformerInto[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[PartialTransformerInto[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -202,24 +207,7 @@ object PartialTransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[PartialTransformerInto[From, To, ConstructorPartial[args, Path.Root, Tail], Flags]] + .asInstanceOf[PartialTransformerInto[From, To, ConstructorPartial[args, Path.Root, Overrides], Flags]] } }(f) - - def transform[ - From: Type, - To: Type, - Tail <: TransformerOverrides: Type, - Flags <: TransformerFlags: Type, - ImplicitScopeFlags <: TransformerFlags: Type - ]( - source: Expr[From], - td: Expr[PartialTransformerDefinition[From, To, Tail, Flags]], - failFast: Boolean - )(using Quotes): Expr[partial.Result[To]] = - TransformerMacros.derivePartialTransformerResultWithConfig[From, To, Tail, Flags, ImplicitScopeFlags]( - source, - td, - failFast - ) } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PatcherDefinitionMacros.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PatcherDefinitionMacros.scala deleted file mode 100644 index f3d68eaf3..000000000 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/PatcherDefinitionMacros.scala +++ /dev/null @@ -1,20 +0,0 @@ -package io.scalaland.chimney.internal.compiletime.dsl - -import io.scalaland.chimney.Patcher -import io.scalaland.chimney.dsl.* -import io.scalaland.chimney.internal.compiletime.derivation.patcher.PatcherMacros -import io.scalaland.chimney.internal.runtime.{PatcherFlags, PatcherOverrides} - -import scala.quoted.* - -object PatcherDefinitionMacros { - - def buildPatcher[ - A: Type, - Patch: Type, - Tail <: PatcherOverrides: Type, - Flags <: PatcherFlags: Type, - ImplicitScopeFlags <: PatcherFlags: Type - ](using Quotes): Expr[Patcher[A, Patch]] = - PatcherMacros.derivePatcherWithConfig[A, Patch, Tail, Flags, ImplicitScopeFlags] -} diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala index 1b182ea7c..965ce8884 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerDefinitionMacros.scala @@ -20,12 +20,12 @@ object TransformerDefinitionMacros { def withFieldConstImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[TransformerDefinition[From, To, Tail, Flags]], + td: Expr[TransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[U] )(using Quotes): Expr[TransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -35,19 +35,19 @@ object TransformerDefinitionMacros { '{ WithRuntimeDataStore .update($td, $value) - .asInstanceOf[TransformerDefinition[From, To, Const[toPath, Tail], Flags]] + .asInstanceOf[TransformerDefinition[From, To, Const[toPath, Overrides], Flags]] } }(selector) def withFieldComputedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[TransformerDefinition[From, To, Tail, Flags]], + td: Expr[TransformerDefinition[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => U] )(using Quotes): Expr[TransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -57,19 +57,19 @@ object TransformerDefinitionMacros { '{ WithRuntimeDataStore .update($td, $f) - .asInstanceOf[TransformerDefinition[From, To, Computed[toPath, Tail], Flags]] + .asInstanceOf[TransformerDefinition[From, To, Computed[toPath, Overrides], Flags]] } }(selector) - def withFieldRenamed[ + def withFieldRenamedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - td: Expr[TransformerDefinition[From, To, Tail, Flags]], + td: Expr[TransformerDefinition[From, To, Overrides, Flags]], selectorFrom: Expr[From => T], selectorTo: Expr[To => U] )(using Quotes): Expr[TransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = @@ -81,36 +81,41 @@ object TransformerDefinitionMacros { $td.asInstanceOf[TransformerDefinition[ From, To, - RenamedFrom[fromPath, toPath, Tail], + RenamedFrom[fromPath, toPath, Overrides], Flags ]] } }(selectorFrom, selectorTo) - def withCoproductInstance[ + def withSealedSubtypeHandledImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - td: Expr[TransformerDefinition[From, To, Tail, Flags]], + td: Expr[TransformerDefinition[From, To, Overrides, Flags]], f: Expr[Subtype => To] )(using Quotes): Expr[TransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = '{ WithRuntimeDataStore .update($td, $f) - .asInstanceOf[TransformerDefinition[From, To, CaseComputed[Path.Matching[Path.Root, Subtype], Tail], Flags]] + .asInstanceOf[TransformerDefinition[ + From, + To, + CaseComputed[Path.Matching[Path.Root, Subtype], Overrides], + Flags + ]] } def withConstructorImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[TransformerDefinition[From, To, Tail, Flags]], + ti: Expr[TransformerDefinition[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[TransformerDefinition[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -119,18 +124,7 @@ object TransformerDefinitionMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[TransformerDefinition[From, To, Constructor[args, Path.Root, Tail], Flags]] + .asInstanceOf[TransformerDefinition[From, To, Constructor[args, Path.Root, Overrides], Flags]] } }(f) - - def buildTransformer[ - From: Type, - To: Type, - Tail <: TransformerOverrides: Type, - Flags <: TransformerFlags: Type, - ImplicitScopeFlags <: TransformerFlags: Type - ]( - td: Expr[TransformerDefinition[From, To, Tail, Flags]] - )(using Quotes): Expr[Transformer[From, To]] = - TransformerMacros.deriveTotalTransformerWithConfig[From, To, Tail, Flags, ImplicitScopeFlags](td) } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala index ad44b8a5d..538ce578f 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/TransformerIntoMacros.scala @@ -21,12 +21,12 @@ object TransformerIntoMacros { def withFieldConstImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[TransformerInto[From, To, Tail, Flags]], + ti: Expr[TransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], value: Expr[U] )(using Quotes): Expr[TransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -36,19 +36,19 @@ object TransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $value) - .asInstanceOf[TransformerInto[From, To, Const[toPath, Tail], Flags]] + .asInstanceOf[TransformerInto[From, To, Const[toPath, Overrides], Flags]] } }(selector) def withFieldComputedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[TransformerInto[From, To, Tail, Flags]], + ti: Expr[TransformerInto[From, To, Overrides, Flags]], selector: Expr[To => T], f: Expr[From => U] )(using Quotes): Expr[TransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -58,19 +58,19 @@ object TransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[TransformerInto[From, To, Computed[toPath, Tail], Flags]] + .asInstanceOf[TransformerInto[From, To, Computed[toPath, Overrides], Flags]] } }(selector) def withFieldRenamedImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, T: Type, U: Type ]( - ti: Expr[TransformerInto[From, To, Tail, Flags]], + ti: Expr[TransformerInto[From, To, Overrides, Flags]], selectorFrom: Expr[From => T], selectorTo: Expr[To => U] )(using Quotes): Expr[TransformerInto[From, To, ? <: TransformerOverrides, Flags]] = @@ -79,34 +79,34 @@ object TransformerIntoMacros { (_: Type[fromPath]) ?=> (_: Type[toPath]) ?=> '{ - $ti.asInstanceOf[TransformerInto[From, To, RenamedFrom[fromPath, toPath, Tail], Flags]] + $ti.asInstanceOf[TransformerInto[From, To, RenamedFrom[fromPath, toPath, Overrides], Flags]] } }(selectorFrom, selectorTo) - def withCoproductInstanceImpl[ + def withSealedSubtypeHandledImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Subtype: Type ]( - ti: Expr[TransformerInto[From, To, Tail, Flags]], + ti: Expr[TransformerInto[From, To, Overrides, Flags]], f: Expr[Subtype => To] )(using Quotes): Expr[TransformerInto[From, To, ? <: TransformerOverrides, Flags]] = '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[TransformerInto[From, To, CaseComputed[Path.Matching[Path.Root, Subtype], Tail], Flags]] + .asInstanceOf[TransformerInto[From, To, CaseComputed[Path.Matching[Path.Root, Subtype], Overrides], Flags]] } def withConstructorImpl[ From: Type, To: Type, - Tail <: TransformerOverrides: Type, + Overrides <: TransformerOverrides: Type, Flags <: TransformerFlags: Type, Ctor: Type ]( - ti: Expr[TransformerInto[From, To, Tail, Flags]], + ti: Expr[TransformerInto[From, To, Overrides, Flags]], f: Expr[Ctor] )(using Quotes): Expr[TransformerInto[From, To, ? <: TransformerOverrides, Flags]] = DslMacroUtils().applyConstructorType { @@ -115,19 +115,7 @@ object TransformerIntoMacros { '{ WithRuntimeDataStore .update($ti, $f) - .asInstanceOf[TransformerInto[From, To, Constructor[args, Path.Root, Tail], Flags]] + .asInstanceOf[TransformerInto[From, To, Constructor[args, Path.Root, Overrides], Flags]] } }(f) - - def transform[ - From: Type, - To: Type, - Tail <: TransformerOverrides: Type, - Flags <: TransformerFlags: Type, - ImplicitScopeFlags <: TransformerFlags: Type - ]( - source: Expr[From], - td: Expr[TransformerDefinition[From, To, Tail, Flags]] - )(using Quotes): Expr[To] = - TransformerMacros.deriveTotalTransformerResultWithConfig[From, To, Tail, Flags, ImplicitScopeFlags](source, td) } diff --git a/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala b/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala index e5f772d00..7464fd84c 100644 --- a/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala +++ b/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala @@ -178,7 +178,7 @@ class PartialTransformerEnumSpec extends ChimneySpec { Some(shapes3enums.Shape.Rectangle(shapes3enums.Point(2.0, 0.0), shapes3enums.Point(2.0, 2.0))) } - group("setting .withCoproductInstance(mapping)") { + group("setting .withSealedSubtypeHandled(mapping)") { test( """should be absent by default and not allow transforming "superset" of case class to "subset" of case objects""" @@ -200,25 +200,25 @@ class PartialTransformerEnumSpec extends ChimneySpec { (colors2enums.Color.Black: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Red) (colors2enums.Color.Red: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Red) (colors2enums.Color.Green: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Green) (colors2enums.Color.Blue: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Blue) } @@ -250,8 +250,8 @@ class PartialTransformerEnumSpec extends ChimneySpec { triangle .intoPartial[shapes2enums.Shape] - .withCoproductInstance(triangleToPolygon) - .withCoproductInstance(rectangleToPolygon) + .withSealedSubtypeHandled(triangleToPolygon) + .withSealedSubtypeHandled(rectangleToPolygon) .transform .asOption ==> Some( shapes2enums.Shape.Polygon(List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0))) @@ -262,7 +262,7 @@ class PartialTransformerEnumSpec extends ChimneySpec { rectangle .intoPartial[shapes2enums.Shape] - .withCoproductInstance[shapes1enums.Shape] { + .withSealedSubtypeHandled[shapes1enums.Shape] { case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) } @@ -335,7 +335,7 @@ class PartialTransformerEnumSpec extends ChimneySpec { ) } - group("setting .withCoproductInstancePartial[Subtype](mapping)") { + group("setting .withSealedSubtypeHandledPartial[Subtype](mapping)") { test( """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" @@ -345,25 +345,25 @@ class PartialTransformerEnumSpec extends ChimneySpec { (colors2enums.Color.Black: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> None (colors2enums.Color.Red: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Red) (colors2enums.Color.Green: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Green) (colors2enums.Color.Blue: colors2enums.Color) .intoPartial[colors1enums.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1enums.Color.Blue) } @@ -399,8 +399,8 @@ class PartialTransformerEnumSpec extends ChimneySpec { triangle .intoPartial[shapes2enums.Shape] - .withCoproductInstancePartial(triangleToPolygon) - .withCoproductInstancePartial(rectangleToPolygon) + .withSealedSubtypeHandledPartial(triangleToPolygon) + .withSealedSubtypeHandledPartial(rectangleToPolygon) .transform .asOption ==> Some( shapes2enums.Shape.Polygon(List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0))) @@ -411,7 +411,7 @@ class PartialTransformerEnumSpec extends ChimneySpec { rectangle .intoPartial[shapes2enums.Shape] - .withCoproductInstancePartial[shapes1enums.Shape] { + .withSealedSubtypeHandledPartial[shapes1enums.Shape] { case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) } diff --git a/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala b/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala index e94ce391f..dbaadb824 100644 --- a/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala +++ b/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala @@ -146,7 +146,7 @@ class TotalTransformerEnumSpec extends ChimneySpec { ) } - group("setting .withCoproductInstance[Subtype](mapping)") { + group("setting .withSealedSubtypeHandled[Subtype](mapping)") { test( """should be absent by default and not allow transforming "superset" of case class to "subset" of case objects""" @@ -167,22 +167,22 @@ class TotalTransformerEnumSpec extends ChimneySpec { (colors2enums.Color.Black: colors2enums.Color) .into[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1enums.Color.Red (colors2enums.Color.Red: colors2enums.Color) .into[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1enums.Color.Red (colors2enums.Color.Green: colors2enums.Color) .into[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1enums.Color.Green (colors2enums.Color.Blue: colors2enums.Color) .into[colors1enums.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1enums.Color.Blue } @@ -213,8 +213,8 @@ class TotalTransformerEnumSpec extends ChimneySpec { triangle .into[shapes2enums.Shape] - .withCoproductInstance(triangleToPolygon) - .withCoproductInstance(rectangleToPolygon) + .withSealedSubtypeHandled(triangleToPolygon) + .withSealedSubtypeHandled(rectangleToPolygon) .transform ==> shapes2enums.Shape.Polygon( List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0)) ) @@ -224,7 +224,7 @@ class TotalTransformerEnumSpec extends ChimneySpec { rectangle .into[shapes2enums.Shape] - .withCoproductInstance[shapes1enums.Shape] { + .withSealedSubtypeHandled[shapes1enums.Shape] { case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) } diff --git a/chimney/src/test/scala-3/io/scalaland/chimney/fixtures/NumbersEnums.scala b/chimney/src/test/scala-3/io/scalaland/chimney/fixtures/NumbersEnums.scala index d29afea90..673cdf3df 100644 --- a/chimney/src/test/scala-3/io/scalaland/chimney/fixtures/NumbersEnums.scala +++ b/chimney/src/test/scala-3/io/scalaland/chimney/fixtures/NumbersEnums.scala @@ -32,10 +32,10 @@ object ScalesEnumsPartialTransformer { ): PartialTransformer[shortEnums.NumScale[A, Nothing], longEnums.NumScale[B]] = Transformer .definePartial[shortEnums.NumScale[A, Nothing], longEnums.NumScale[B]] - .withCoproductInstancePartial { (billion: shortEnums.NumScale.Billion[A]) => + .withSealedSubtypeHandledPartial { (billion: shortEnums.NumScale.Billion[A]) => billion.transformIntoPartial[longEnums.NumScale.Milliard[B]] } - .withCoproductInstancePartial { (trillion: shortEnums.NumScale.Trillion[A]) => + .withSealedSubtypeHandledPartial { (trillion: shortEnums.NumScale.Trillion[A]) => trillion.transformIntoPartial[longEnums.NumScale.Billion[B]] } .buildTransformer @@ -45,10 +45,10 @@ object ScalesEnumsPartialTransformer { ): PartialTransformer[shortEnums.NumScale[A, Nothing], longEnums.NumScale[B]] = Transformer .definePartial[shortEnums.NumScale[A, Nothing], longEnums.NumScale[B]] - .withCoproductInstancePartial { (billion: shortEnums.NumScale.Billion[A]) => + .withSealedSubtypeHandledPartial { (billion: shortEnums.NumScale.Billion[A]) => billion.transformIntoPartial[longEnums.NumScale.Milliard[B]] } - .withCoproductInstancePartial { (trillion: shortEnums.NumScale.Trillion[A]) => + .withSealedSubtypeHandledPartial { (trillion: shortEnums.NumScale.Trillion[A]) => trillion.transformIntoPartial[longEnums.NumScale.Billion[B]] } .buildTransformer diff --git a/chimney/src/test/scala/io/scalaland/chimney/IssuesSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/IssuesSpec.scala index a7df613ad..3d6806428 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/IssuesSpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/IssuesSpec.scala @@ -297,7 +297,7 @@ class IssuesSpec extends ChimneySpec { val v1: Version1 = Instance1 val v2: Version2 = v1 .into[Version2] - .withCoproductInstance { (_: Instance1.type) => + .withSealedSubtypeHandled { (_: Instance1.type) => Instance2 } .transform @@ -314,7 +314,7 @@ class IssuesSpec extends ChimneySpec { val v1: Version1 = Instance1(10) val v2: Version2 = v1 .into[Version2] - .withCoproductInstance { (i: Instance1) => + .withSealedSubtypeHandled { (i: Instance1) => Instance2(i.p / 2, i.p / 2) } .transform @@ -332,36 +332,36 @@ class IssuesSpec extends ChimneySpec { case object Bar2 extends Foo2 case object Baz2 extends Foo2 - test("withCoproductInstancePartial twice") { + test("withSealedSubtypeHandledPartial twice") { implicit val fooFoo2PartialTransformer: PartialTransformer[Foo, Foo2] = PartialTransformer .define[Foo, Foo2] - .withCoproductInstancePartial((_: Bar.type) => partial.Result.fromValue(Bar2)) - .withCoproductInstancePartial((_: Baz.type) => partial.Result.fromValue(Baz2)) + .withSealedSubtypeHandledPartial((_: Bar.type) => partial.Result.fromValue(Bar2)) + .withSealedSubtypeHandledPartial((_: Baz.type) => partial.Result.fromValue(Baz2)) .buildTransformer (Bar: Foo).transformIntoPartial[Foo2].asOption ==> Some(Bar2) (Baz: Foo).transformIntoPartial[Foo2].asOption ==> Some(Baz2) } - test("withCoproductInstance followed by withCoproductInstancePartial") { + test("withSealedSubtypeHandled followed by withSealedSubtypeHandledPartial") { implicit val fooFoo2PartialTransformer: PartialTransformer[Foo, Foo2] = PartialTransformer .define[Foo, Foo2] - .withCoproductInstance((_: Bar.type) => Bar2) - .withCoproductInstancePartial((_: Baz.type) => partial.Result.fromValue(Baz2)) + .withSealedSubtypeHandled((_: Bar.type) => Bar2) + .withSealedSubtypeHandledPartial((_: Baz.type) => partial.Result.fromValue(Baz2)) .buildTransformer (Bar: Foo).transformIntoPartial[Foo2].asOption ==> Some(Bar2) (Baz: Foo).transformIntoPartial[Foo2].asOption ==> Some(Baz2) } - test("withCoproductInstancePartial followed by withCoproductInstance") { + test("withSealedSubtypeHandledPartial followed by withSealedSubtypeHandled") { implicit val fooFoo2PartialTransformer: PartialTransformer[Foo, Foo2] = PartialTransformer .define[Foo, Foo2] - .withCoproductInstancePartial((_: Bar.type) => partial.Result.fromValue(Bar2)) - .withCoproductInstance((_: Baz.type) => Baz2) + .withSealedSubtypeHandledPartial((_: Bar.type) => partial.Result.fromValue(Bar2)) + .withSealedSubtypeHandled((_: Baz.type) => Baz2) .buildTransformer (Bar: Foo).transformIntoPartial[Foo2].asOption ==> Some(Bar2) @@ -421,25 +421,25 @@ class IssuesSpec extends ChimneySpec { (colors2.Black: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Red) (colors2.Red: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Red) (colors2.Green: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Green) (colors2.Blue: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Blue) } @@ -492,7 +492,7 @@ class IssuesSpec extends ChimneySpec { implicit val oneOfPartialTransformer: PartialTransformer[proto.OneOf, OneOf] = PartialTransformer .define[proto.OneOf, OneOf] - .withCoproductInstancePartial[proto.Empty.type](_ => partial.Result.fromErrorString("proto.OneOf.Empty")) + .withSealedSubtypeHandledPartial[proto.Empty.type](_ => partial.Result.fromErrorString("proto.OneOf.Empty")) .buildTransformer (proto.Something(proto.SomethingMessage(42)): proto.OneOf) @@ -563,17 +563,17 @@ class IssuesSpec extends ChimneySpec { // make sure the other way around is fine with partial transformers (A.Foo: A) .intoPartial[B] - .withCoproductInstancePartial[A.Unrecognized](_ => partial.Result.fromEmpty) + .withSealedSubtypeHandledPartial[A.Unrecognized](_ => partial.Result.fromEmpty) .transform .asOption ==> Some(B.Foo) (A.Bar: A) .intoPartial[B] - .withCoproductInstancePartial[A.Unrecognized](_ => partial.Result.fromEmpty) + .withSealedSubtypeHandledPartial[A.Unrecognized](_ => partial.Result.fromEmpty) .transform .asOption ==> Some(B.Bar) (A.Unrecognized(100): A) .intoPartial[B] - .withCoproductInstancePartial[A.Unrecognized](_ => partial.Result.fromEmpty) + .withSealedSubtypeHandledPartial[A.Unrecognized](_ => partial.Result.fromEmpty) .transform .asOption ==> None } @@ -646,7 +646,7 @@ class IssuesSpec extends ChimneySpec { implicit val sourceToTarget: PartialTransformer[Source, Target] = PartialTransformer .define[Source, Target] - .withCoproductInstancePartial[Source.Empty.type](_ => partial.Result.fromErrorString("Error")) + .withSealedSubtypeHandledPartial[Source.Empty.type](_ => partial.Result.fromErrorString("Error")) .buildTransformer (Source.Value1(100): Source).transformIntoPartial[Target].asEither ==> Right(Target.Value1(100)) diff --git a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala index 01f96a72c..55f21bdd2 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala @@ -155,7 +155,7 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { ) } - group("setting .withCoproductInstance[Subtype](mapping)") { + group("setting .withSealedSubtypeHandled[Subtype](mapping)") { test( """should be absent by default and not allow transforming "superset" of case class to "subset" of case objects""" @@ -176,25 +176,25 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { (colors2.Black: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Red) (colors2.Red: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Red) (colors2.Green: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Green) (colors2.Blue: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform .asOption ==> Some(colors1.Blue) } @@ -226,8 +226,8 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { triangle .intoPartial[shapes2.Shape] - .withCoproductInstance(triangleToPolygon) - .withCoproductInstance(rectangleToPolygon) + .withSealedSubtypeHandled(triangleToPolygon) + .withSealedSubtypeHandled(rectangleToPolygon) .transform .asOption ==> Some(shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0)))) @@ -236,7 +236,7 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { rectangle .intoPartial[shapes2.Shape] - .withCoproductInstance[shapes1.Shape] { + .withSealedSubtypeHandled[shapes1.Shape] { case r: shapes1.Rectangle => rectangleToPolygon(r) case t: shapes1.Triangle => triangleToPolygon(t) } @@ -278,7 +278,7 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { ) } - group("setting .withCoproductInstancePartial[Subtype](mapping)") { + group("setting .withSealedSubtypeHandledPartial[Subtype](mapping)") { test( """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" @@ -288,25 +288,25 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { (colors2.Black: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> None (colors2.Red: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1.Red) (colors2.Green: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1.Green) (colors2.Blue: colors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial(blackIsRed) + .withSealedSubtypeHandledPartial(blackIsRed) .transform .asOption ==> Some(colors1.Blue) } @@ -342,8 +342,8 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { triangle .intoPartial[shapes2.Shape] - .withCoproductInstancePartial(triangleToPolygon) - .withCoproductInstancePartial(rectangleToPolygon) + .withSealedSubtypeHandledPartial(triangleToPolygon) + .withSealedSubtypeHandledPartial(rectangleToPolygon) .transform .asOption ==> Some(shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0)))) @@ -352,7 +352,7 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { rectangle .intoPartial[shapes2.Shape] - .withCoproductInstancePartial[shapes1.Shape] { + .withSealedSubtypeHandledPartial[shapes1.Shape] { case r: shapes1.Rectangle => rectangleToPolygon(r) case t: shapes1.Triangle => triangleToPolygon(t) } diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala index acd3beda2..1ff4c673d 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala @@ -118,7 +118,7 @@ class TotalTransformerSealedHierarchySpec extends ChimneySpec { ) } - group("setting .withCoproductInstance[Subtype](mapping)") { + group("setting .withSealedSubtypeHandled[Subtype](mapping)") { test( """should be absent by default and not allow transforming "superset" of case class to "subset" of case objects""" @@ -139,22 +139,22 @@ class TotalTransformerSealedHierarchySpec extends ChimneySpec { (colors2.Black: colors2.Color) .into[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1.Red (colors2.Red: colors2.Color) .into[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1.Red (colors2.Green: colors2.Color) .into[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1.Green (colors2.Blue: colors2.Color) .into[colors1.Color] - .withCoproductInstance(blackIsRed) + .withSealedSubtypeHandled(blackIsRed) .transform ==> colors1.Blue } @@ -185,8 +185,8 @@ class TotalTransformerSealedHierarchySpec extends ChimneySpec { triangle .into[shapes2.Shape] - .withCoproductInstance(triangleToPolygon) - .withCoproductInstance(rectangleToPolygon) + .withSealedSubtypeHandled(triangleToPolygon) + .withSealedSubtypeHandled(rectangleToPolygon) .transform ==> shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0))) val rectangle: shapes1.Shape = @@ -194,7 +194,7 @@ class TotalTransformerSealedHierarchySpec extends ChimneySpec { rectangle .into[shapes2.Shape] - .withCoproductInstance[shapes1.Shape] { + .withSealedSubtypeHandled[shapes1.Shape] { case r: shapes1.Rectangle => rectangleToPolygon(r) case t: shapes1.Triangle => triangleToPolygon(t) } diff --git a/chimney/src/test/scala/io/scalaland/chimney/fixtures/Numbers.scala b/chimney/src/test/scala/io/scalaland/chimney/fixtures/Numbers.scala index e308b5e98..0f76a264d 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/fixtures/Numbers.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/fixtures/Numbers.scala @@ -32,10 +32,10 @@ object ScalesPartialTransformer { ): PartialTransformer[short.NumScale[A, Nothing], long.NumScale[B]] = Transformer .definePartial[short.NumScale[A, Nothing], long.NumScale[B]] - .withCoproductInstancePartial { (billion: short.Billion[A]) => + .withSealedSubtypeHandledPartial { (billion: short.Billion[A]) => billion.transformIntoPartial[long.Milliard[B]] } - .withCoproductInstancePartial { (trillion: short.Trillion[A]) => + .withSealedSubtypeHandledPartial { (trillion: short.Trillion[A]) => trillion.transformIntoPartial[long.Billion[B]] } .buildTransformer @@ -45,10 +45,10 @@ object ScalesPartialTransformer { ): PartialTransformer[short.NumScale[A, Nothing], long.NumScale[B]] = Transformer .definePartial[short.NumScale[A, Nothing], long.NumScale[B]] - .withCoproductInstancePartial { (billion: short.Billion[A]) => + .withSealedSubtypeHandledPartial { (billion: short.Billion[A]) => billion.transformIntoPartial[long.Milliard[B]] } - .withCoproductInstancePartial { (trillion: short.Trillion[A]) => + .withSealedSubtypeHandledPartial { (trillion: short.Trillion[A]) => trillion.transformIntoPartial[long.Billion[B]] } .buildTransformer diff --git a/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala b/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala index 43ce66089..5c24d822d 100644 --- a/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala +++ b/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala @@ -74,7 +74,7 @@ class PartialTransformerJavaEnumSpec extends ChimneySpec { ) } - group("setting .withCoproductInstance[Subtype](mapping)") { + group("setting .withSealedSubtypeHandled[Subtype](mapping)") { test( """should be absent by default and not allow transforming Java Enum "superset" instances to sealed hierarchy "subset" of case objects""" @@ -95,31 +95,31 @@ class PartialTransformerJavaEnumSpec extends ChimneySpec { (jcolors2.Color.Black: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Red) (jcolors2.Color.Red: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Red) (jcolors2.Color.Green: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Green) (jcolors2.Color.Blue: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Blue) } } - group("setting .withCoproductInstancePartial[Subtype](mapping)") { + group("setting .withSealedSubtypeHandledPartial[Subtype](mapping)") { test( """transform from Java Enum "superset" instances to sealed hierarchy "subset" of case objects when user-provided mapping handled additional cases""" @@ -129,25 +129,25 @@ class PartialTransformerJavaEnumSpec extends ChimneySpec { (jcolors2.Color.Black: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> None (jcolors2.Color.Red: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Red) (jcolors2.Color.Green: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Green) (jcolors2.Color.Blue: jcolors2.Color) .intoPartial[colors1.Color] - .withCoproductInstancePartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform .asOption ==> Some(colors1.Blue) } diff --git a/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala b/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala index a0e266c92..fada32e42 100644 --- a/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala +++ b/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala @@ -74,7 +74,7 @@ class TotalTransformerJavaEnumSpec extends ChimneySpec { ) } - group("setting .withCoproductInstance[Subtype](mapping)") { + group("setting .withSealedSubtypeHandled[Subtype](mapping)") { test( """should be absent by default and not allow transforming Java Enum "superset" instances to sealed hierarchy "subset" of case objects""" @@ -95,22 +95,22 @@ class TotalTransformerJavaEnumSpec extends ChimneySpec { (jcolors2.Color.Black: jcolors2.Color) .into[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform ==> colors1.Red (jcolors2.Color.Red: jcolors2.Color) .into[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform ==> colors1.Red (jcolors2.Color.Green: jcolors2.Color) .into[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform ==> colors1.Green (jcolors2.Color.Blue: jcolors2.Color) .into[colors1.Color] - .withCoproductInstance((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .withSealedSubtypeHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) .transform ==> colors1.Blue } } diff --git a/docs/docs/cookbook.md b/docs/docs/cookbook.md index be3af2471..8f89c1b0b 100644 --- a/docs/docs/cookbook.md +++ b/docs/docs/cookbook.md @@ -784,7 +784,7 @@ Decoding (with `PartialTransformer`s) requires handling of `Empty.Value` type pbType.value .intoPartial[addressbook.AddressBookType] - .withCoproductInstancePartial[pb.addressbook.AddressBookType.Value.Empty.type]( + .withSealedSubtypeHandledPartial[pb.addressbook.AddressBookType.Value.Empty.type]( _ => partial.Result.fromEmpty ) .transform @@ -892,10 +892,10 @@ could be done with: pbStatus .intoPartial[order.CustomerStatus] - .withCoproductInstancePartial[pb.order.CustomerStatus.Empty.type]( + .withSealedSubtypeHandledPartial[pb.order.CustomerStatus.Empty.type]( _ => partial.Result.fromEmpty ) - .withCoproductInstance[pb.order.CustomerStatus.NonEmpty]( + .withSealedSubtypeHandled[pb.order.CustomerStatus.NonEmpty]( _.transformInto[order.CustomerStatus] ) .transform diff --git a/docs/docs/supported-transformations.md b/docs/docs/supported-transformations.md index 706931de9..2b8f128ec 100644 --- a/docs/docs/supported-transformations.md +++ b/docs/docs/supported-transformations.md @@ -1844,7 +1844,7 @@ Java's `enum` can also be converted this way to/from `sealed`/Scala 3's `enum`/a ### Handling a specific `sealed` subtype with a computed value Sometimes we are missing a corresponding subtype of the target type. Or we might want to override it with our -computation. This can be done using `.withCoproductInstance`: +computation. This can be done using `.withSealedSubtypeHandled`: !!! example @@ -1864,18 +1864,18 @@ computation. This can be done using `.withCoproductInstance`: case object Buzz extends Bar } - (Bar.Baz("value"): Bar).into[Foo].withCoproductInstance[Bar.Fizz.type] { + (Bar.Baz("value"): Bar).into[Foo].withSealedSubtypeHandled[Bar.Fizz.type] { fizz => Foo.Baz(fizz.toString) }.transform // Foo.Baz("value") - (Bar.Fizz: Bar).into[Foo].withCoproductInstance[Bar.Fizz.type] { + (Bar.Fizz: Bar).into[Foo].withSealedSubtypeHandled[Bar.Fizz.type] { fizz => Foo.Baz(fizz.toString) }.transform // Foo.Baz("Fizz") - (Bar.Buzz: Bar).into[Foo].withCoproductInstance[Bar.Fizz.type] { + (Bar.Buzz: Bar).into[Foo].withSealedSubtypeHandled[Bar.Fizz.type] { fizz => Foo.Baz(fizz.toString) }.transform // Foo.Buzz ``` -If the computation needs to allow failure, there is `.withCoproductInstancePartial`: +If the computation needs to allow failure, there is `.withSealedSubtypeHandledPartial`: !!! example @@ -1896,20 +1896,20 @@ If the computation needs to allow failure, there is `.withCoproductInstanceParti case object Buzz extends Bar } - (Bar.Baz("value"): Bar).intoPartial[Foo].withCoproductInstancePartial[Bar.Fizz.type] { + (Bar.Baz("value"): Bar).intoPartial[Foo].withSealedSubtypeHandledPartial[Bar.Fizz.type] { fizz => partial.Result.fromEmpty }.transform.asEither // Right(Foo.Baz("value")) - (Bar.Fizz: Bar).intoPartial[Foo].withCoproductInstancePartial[Bar.Fizz.type] { + (Bar.Fizz: Bar).intoPartial[Foo].withSealedSubtypeHandledPartial[Bar.Fizz.type] { fizz => partial.Result.fromEmpty }.transform.asEither // Left(...) - (Bar.Buzz: Bar).intoPartial[Foo].withCoproductInstancePartial[Bar.Fizz.type] { + (Bar.Buzz: Bar).intoPartial[Foo].withSealedSubtypeHandledPartial[Bar.Fizz.type] { fizz => partial.Result.fromEmpty }.transform.asEither // Right(Foo.Buzz) ``` !!! warning - Due to limitations of Scala 2, when you want to use `.withCoproductInstance` or `.withCoproductInstancePartial` with + Due to limitations of Scala 2, when you want to use `.withSealedSubtypeHandled` or `.withSealedSubtypeHandledPartial` with Java's `enum`s, the enum instance's exact type will always be upcasted/lost, turning the handler into "catch-all": ```java @@ -1933,10 +1933,10 @@ If the computation needs to allow failure, there is `.withCoproductInstanceParti def blackIsRed(black: ColorJ.Black.type): ColorS = ColorS.Red - ColorJ.Red.into[ColorS].withCoproductInstance[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red - ColorJ.Green.into[ColorS].withCoproductInstance[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red - ColorJ.Blue.into[ColorS].withCoproductInstance[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red - ColorJ.Black.into[ColorS].withCoproductInstance[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red + ColorJ.Red.into[ColorS].withSealedSubtypeHandled[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red + ColorJ.Green.into[ColorS].withSealedSubtypeHandled[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red + ColorJ.Blue.into[ColorS].withSealedSubtypeHandled[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red + ColorJ.Black.into[ColorS].withSealedSubtypeHandled[ColorJ.Black.type](blackIsRed(_)).transform // ColorS.Red ``` There is nothing we can do about the type, however, we can analyze the code and, if it preserves the exact Java enum @@ -1956,16 +1956,16 @@ If the computation needs to allow failure, there is `.withCoproductInstanceParti def blackIsRed(black: ColorJ.Black.type): ColorS = ColorS.Red - ColorJ.Red.into[ColorS].withCoproductInstance { (black: ColorJ.Black.type) => + ColorJ.Red.into[ColorS].withSealedSubtypeHandled { (black: ColorJ.Black.type) => blackIsRed(black) }.transform // ColorS.Red - ColorJ.Green.into[ColorS].withCoproductInstance { (black: ColorJ.Black.type) => + ColorJ.Green.into[ColorS].withSealedSubtypeHandled { (black: ColorJ.Black.type) => blackIsRed(black) }.transform // ColorS.Green - ColorJ.Blue.into[ColorS].withCoproductInstance { (black: ColorJ.Black.type) => + ColorJ.Blue.into[ColorS].withSealedSubtypeHandled { (black: ColorJ.Black.type) => blackIsRed(black) }.transform // ColorS.Blue - ColorJ.Black.into[ColorS].withCoproductInstance { (black: ColorJ.Black.type) => + ColorJ.Black.into[ColorS].withSealedSubtypeHandled { (black: ColorJ.Black.type) => blackIsRed(black) }.transform // ColorS.Black ``` @@ -1982,10 +1982,10 @@ If the computation needs to allow failure, there is `.withCoproductInstanceParti def blackIsRed(black: ColorJ.Black.type): ColorS = ColorS.Red - ColorJ.Red.into[ColorS].withCoproductInstance(blackIsRed).transform // ColorS.Red - ColorJ.Green.into[ColorS].withCoproductInstance(blackIsRed).transform // ColorS.Green - ColorJ.Blue.into[ColorS].withCoproductInstance(blackIsRed).transform // ColorS.Blue - ColorJ.Black.into[ColorS].withCoproductInstance(blackIsRed).transform // ColorS.Black + ColorJ.Red.into[ColorS].withSealedSubtypeHandled(blackIsRed).transform // ColorS.Red + ColorJ.Green.into[ColorS].withSealedSubtypeHandled(blackIsRed).transform // ColorS.Green + ColorJ.Blue.into[ColorS].withSealedSubtypeHandled(blackIsRed).transform // ColorS.Blue + ColorJ.Black.into[ColorS].withSealedSubtypeHandled(blackIsRed).transform // ColorS.Black ``` ### Customizing subtype name matching @@ -2070,7 +2070,7 @@ For details about `TransformedNamesComparison` look at [their dedicated section] } ``` - Such cases always have to be handled manually (`withCoproductInstance(...)`). + Such cases always have to be handled manually (`withSealedSubtypeHandled(...)`). If the flag was enabled in the implicit config it can be disabled with `.disableCustomSubtypeNameComparison`. From 7f96f03a138ccbaf958341c8e219d557a1d48973 Mon Sep 17 00:00:00 2001 From: Mateusz Kubuszok Date: Thu, 11 Apr 2024 18:47:01 +0200 Subject: [PATCH 2/3] Mention alias in scaladocs, use withEnumCaseHandled in tests to prove that it works --- .../dsl/PartialTransformerDefinition.scala | 10 + .../chimney/dsl/PartialTransformerInto.scala | 10 + .../chimney/dsl/TransformerDefinition.scala | 5 + .../chimney/dsl/TransformerInto.scala | 5 + .../dsl/PartialTransformerDefinition.scala | 10 + .../chimney/dsl/PartialTransformerInto.scala | 10 + .../chimney/dsl/TransformerDefinition.scala | 5 + .../chimney/dsl/TransformerInto.scala | 5 + .../chimney/PartialTransformerEnumSpec.scala | 174 ++++++++++++++++++ .../chimney/TotalTransformerEnumSpec.scala | 77 ++++++++ ...artialTransformerSealedHierarchySpec.scala | 170 +++++++++++++++++ .../TotalTransformerSealedHierarchySpec.scala | 75 ++++++++ .../PartialTransformerJavaEnumSpec.scala | 68 +++++++ .../TotalTransformerJavaEnumSpec.scala | 30 +++ 14 files changed, 654 insertions(+) diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala index 139b953f4..036ff850a 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala @@ -130,6 +130,11 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance @@ -169,6 +174,11 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandledPartial]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputedPartial(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala index 107452533..3c3fbb1da 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/PartialTransformerInto.scala @@ -133,6 +133,11 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance @@ -172,6 +177,11 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandledPartial]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputedPartial(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala index 149e493d3..9e56b7a45 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerDefinition.scala @@ -101,6 +101,11 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala index 1394961a3..acc3be27f 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/dsl/TransformerInto.scala @@ -97,6 +97,11 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < * in `To` field's type there is matching component in `From` type. If some component is missing * it will fail. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala index 0472a6825..37929024e 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerDefinition.scala @@ -131,6 +131,11 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * to have matching names of its components, and for every component in `To` field's type there is matching component * in `From` type. If some component is missing it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance @@ -170,6 +175,11 @@ final class PartialTransformerDefinition[From, To, Overrides <: TransformerOverr * in `To` field's type there is matching component in `From` type. If some component is missing * it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandledPartial]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputedPartial(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala index 27b217b39..0ec01d2f1 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/PartialTransformerInto.scala @@ -133,6 +133,11 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * to have matching names of its components, and for every component in `To` field's type there is matching component * in `From` type. If some component is missing it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance @@ -171,6 +176,11 @@ final class PartialTransformerInto[From, To, Overrides <: TransformerOverrides, * to have matching names of its components, and for every component in `To` field's type there is matching component * in `From` type. If some component is missing it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandledPartial]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputedPartial(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala index d3906c7ed..57e10a92b 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerDefinition.scala @@ -103,6 +103,11 @@ final class TransformerDefinition[From, To, Overrides <: TransformerOverrides, F * to have matching names of its components, and for every component in `To` field's type there is matching component * in `From` type. If some component is missing it fails compilation unless provided replacement with this operation. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala index 62c1c6616..8d8b177e6 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/dsl/TransformerInto.scala @@ -94,6 +94,11 @@ final class TransformerInto[From, To, Overrides <: TransformerOverrides, Flags < * will have matching names of its components, and for every component in `To` field's type there is matching * component in `From` type. If some component is missing it will fail. * + * For convenience/readability [[withEnumCaseHandled]] alias can be used (e.g. for Scala 3 enums or Java enums). + * + * It differs from `withFieldComputed(_.matching[Subtype], src => ...)`, since `withSealedSubtypeHandled` matches on + * `From` subtype, while `.matching[Subtype]` matches on `To` value's piece. + * * @see [[https://chimney.readthedocs.io/supported-transformations/#handling-a-specific-sealed-subtype-with-a-computed-value]] for more details * * @tparam Subtype type of sealed/enum instance diff --git a/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala b/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala index 7464fd84c..5b596a4f7 100644 --- a/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala +++ b/chimney/src/test/scala-3/io/scalaland/chimney/PartialTransformerEnumSpec.scala @@ -275,6 +275,91 @@ class PartialTransformerEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled(mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: colors2enums.Color.Black.type): colors1enums.Color = + colors1enums.Color.Red + + (colors2enums.Color.Black: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Red) + + (colors2enums.Color.Red: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Red) + + (colors2enums.Color.Green: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Green) + + (colors2enums.Color.Blue: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Blue) + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1enums.Shape.Triangle): shapes2enums.Shape = + shapes2enums.Shape.Polygon( + List( + t.p1.transformInto[shapes2enums.Point], + t.p2.transformInto[shapes2enums.Point], + t.p3.transformInto[shapes2enums.Point] + ) + ) + + def rectangleToPolygon(r: shapes1enums.Shape.Rectangle): shapes2enums.Shape = + shapes2enums.Shape.Polygon( + List( + r.p1.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p2.x, r.p1.y) + ) + ) + + val triangle: shapes1enums.Shape = + shapes1enums.Shape.Triangle(shapes1enums.Point(0, 0), shapes1enums.Point(2, 2), shapes1enums.Point(2, 0)) + + triangle + .intoPartial[shapes2enums.Shape] + .withEnumCaseHandled(triangleToPolygon) + .withEnumCaseHandled(rectangleToPolygon) + .transform + .asOption ==> Some( + shapes2enums.Shape.Polygon(List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0))) + ) + + val rectangle: shapes1enums.Shape = + shapes1enums.Shape.Rectangle(shapes1enums.Point(0, 0), shapes1enums.Point(6, 4)) + + rectangle + .intoPartial[shapes2enums.Shape] + .withEnumCaseHandled[shapes1enums.Shape] { + case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) + case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) + } + .transform + .asOption ==> Some( + shapes2enums.Shape.Polygon( + List(shapes2enums.Point(0, 0), shapes2enums.Point(0, 4), shapes2enums.Point(6, 4), shapes2enums.Point(6, 0)) + ) + ) + } + } + test( "transform sealed hierarchies of single value wrapping case classes to sealed hierarchy of flat case classes subtypes" ) { @@ -424,6 +509,95 @@ class PartialTransformerEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandledPartial[Subtype](mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(b: colors2enums.Color.Black.type): partial.Result[colors1enums.Color] = + partial.Result.fromEmpty + + (colors2enums.Color.Black: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> None + + (colors2enums.Color.Red: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Red) + + (colors2enums.Color.Green: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Green) + + (colors2enums.Color.Blue: colors2enums.Color) + .intoPartial[colors1enums.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1enums.Color.Blue) + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1enums.Shape.Triangle): partial.Result[shapes2enums.Shape] = + partial.Result.fromValue( + shapes2enums.Shape.Polygon( + List( + t.p1.transformInto[shapes2enums.Point], + t.p2.transformInto[shapes2enums.Point], + t.p3.transformInto[shapes2enums.Point] + ) + ) + ) + + def rectangleToPolygon(r: shapes1enums.Shape.Rectangle): partial.Result[shapes2enums.Shape] = + partial.Result.fromValue( + shapes2enums.Shape.Polygon( + List( + r.p1.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p2.x, r.p1.y) + ) + ) + ) + + val triangle: shapes1enums.Shape = + shapes1enums.Shape.Triangle(shapes1enums.Point(0, 0), shapes1enums.Point(2, 2), shapes1enums.Point(2, 0)) + + triangle + .intoPartial[shapes2enums.Shape] + .withEnumCaseHandledPartial(triangleToPolygon) + .withEnumCaseHandledPartial(rectangleToPolygon) + .transform + .asOption ==> Some( + shapes2enums.Shape.Polygon(List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0))) + ) + + val rectangle: shapes1enums.Shape = + shapes1enums.Shape.Rectangle(shapes1enums.Point(0, 0), shapes1enums.Point(6, 4)) + + rectangle + .intoPartial[shapes2enums.Shape] + .withEnumCaseHandledPartial[shapes1enums.Shape] { + case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) + case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) + } + .transform + .asOption ==> Some( + shapes2enums.Shape.Polygon( + List(shapes2enums.Point(0, 0), shapes2enums.Point(0, 4), shapes2enums.Point(6, 4), shapes2enums.Point(6, 0)) + ) + ) + } + } + group("flag .enableCustomSubtypeNameComparison") { import renames.* diff --git a/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala b/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala index dbaadb824..e291404b3 100644 --- a/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala +++ b/chimney/src/test/scala-3/io/scalaland/chimney/TotalTransformerEnumSpec.scala @@ -234,6 +234,83 @@ class TotalTransformerEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled[Subtype](mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: colors2enums.Color.Black.type): colors1enums.Color = + colors1enums.Color.Red + + (colors2enums.Color.Black: colors2enums.Color) + .into[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1enums.Color.Red + + (colors2enums.Color.Red: colors2enums.Color) + .into[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1enums.Color.Red + + (colors2enums.Color.Green: colors2enums.Color) + .into[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1enums.Color.Green + + (colors2enums.Color.Blue: colors2enums.Color) + .into[colors1enums.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1enums.Color.Blue + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1enums.Shape.Triangle): shapes2enums.Shape = + shapes2enums.Shape.Polygon( + List( + t.p1.transformInto[shapes2enums.Point], + t.p2.transformInto[shapes2enums.Point], + t.p3.transformInto[shapes2enums.Point] + ) + ) + + def rectangleToPolygon(r: shapes1enums.Shape.Rectangle): shapes2enums.Shape = + shapes2enums.Shape.Polygon( + List( + r.p1.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2enums.Point], + shapes2enums.Point(r.p2.x, r.p1.y) + ) + ) + + val triangle: shapes1enums.Shape = + shapes1enums.Shape.Triangle(shapes1enums.Point(0, 0), shapes1enums.Point(2, 2), shapes1enums.Point(2, 0)) + + triangle + .into[shapes2enums.Shape] + .withEnumCaseHandled(triangleToPolygon) + .withEnumCaseHandled(rectangleToPolygon) + .transform ==> shapes2enums.Shape.Polygon( + List(shapes2enums.Point(0, 0), shapes2enums.Point(2, 2), shapes2enums.Point(2, 0)) + ) + + val rectangle: shapes1enums.Shape = + shapes1enums.Shape.Rectangle(shapes1enums.Point(0, 0), shapes1enums.Point(6, 4)) + + rectangle + .into[shapes2enums.Shape] + .withEnumCaseHandled[shapes1enums.Shape] { + case r: shapes1enums.Shape.Rectangle => rectangleToPolygon(r) + case t: shapes1enums.Shape.Triangle => triangleToPolygon(t) + } + .transform ==> shapes2enums.Shape.Polygon( + List(shapes2enums.Point(0, 0), shapes2enums.Point(0, 4), shapes2enums.Point(6, 4), shapes2enums.Point(6, 0)) + ) + } + } + group("flag .enableCustomSubtypeNameComparison") { import renames.* diff --git a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala b/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala index 55f21bdd2..af0241ed9 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/PartialTransformerSealedHierarchySpec.scala @@ -249,6 +249,89 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled[Subtype](mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: colors2.Black.type): colors1.Color = + colors1.Red + + (colors2.Black: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1.Red) + + (colors2.Red: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1.Red) + + (colors2.Green: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1.Green) + + (colors2.Blue: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform + .asOption ==> Some(colors1.Blue) + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1.Triangle): shapes2.Shape = + shapes2.Polygon( + List( + t.p1.transformInto[shapes2.Point], + t.p2.transformInto[shapes2.Point], + t.p3.transformInto[shapes2.Point] + ) + ) + + def rectangleToPolygon(r: shapes1.Rectangle): shapes2.Shape = + shapes2.Polygon( + List( + r.p1.transformInto[shapes2.Point], + shapes2.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2.Point], + shapes2.Point(r.p2.x, r.p1.y) + ) + ) + + val triangle: shapes1.Shape = + shapes1.Triangle(shapes1.Point(0, 0), shapes1.Point(2, 2), shapes1.Point(2, 0)) + + triangle + .intoPartial[shapes2.Shape] + .withEnumCaseHandled(triangleToPolygon) + .withEnumCaseHandled(rectangleToPolygon) + .transform + .asOption ==> Some(shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0)))) + + val rectangle: shapes1.Shape = + shapes1.Rectangle(shapes1.Point(0, 0), shapes1.Point(6, 4)) + + rectangle + .intoPartial[shapes2.Shape] + .withEnumCaseHandled[shapes1.Shape] { + case r: shapes1.Rectangle => rectangleToPolygon(r) + case t: shapes1.Triangle => triangleToPolygon(t) + } + .transform + .asOption ==> Some( + shapes2.Polygon( + List(shapes2.Point(0, 0), shapes2.Point(0, 4), shapes2.Point(6, 4), shapes2.Point(6, 0)) + ) + ) + } + } + test( "transform sealed hierarchies of single value wrapping case classes to sealed hierarchy of flat case classes subtypes" ) { @@ -365,6 +448,93 @@ class PartialTransformerSealedHierarchySpec extends ChimneySpec { } } + group("setting .withEnumCaseHandledPartial[Subtype](mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(b: colors2.Black.type): partial.Result[colors1.Color] = + partial.Result.fromEmpty + + (colors2.Black: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> None + + (colors2.Red: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1.Red) + + (colors2.Green: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1.Green) + + (colors2.Blue: colors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial(blackIsRed) + .transform + .asOption ==> Some(colors1.Blue) + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1.Triangle): partial.Result[shapes2.Shape] = + partial.Result.fromValue( + shapes2.Polygon( + List( + t.p1.transformInto[shapes2.Point], + t.p2.transformInto[shapes2.Point], + t.p3.transformInto[shapes2.Point] + ) + ) + ) + + def rectangleToPolygon(r: shapes1.Rectangle): partial.Result[shapes2.Shape] = + partial.Result.fromValue( + shapes2.Polygon( + List( + r.p1.transformInto[shapes2.Point], + shapes2.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2.Point], + shapes2.Point(r.p2.x, r.p1.y) + ) + ) + ) + + val triangle: shapes1.Shape = + shapes1.Triangle(shapes1.Point(0, 0), shapes1.Point(2, 2), shapes1.Point(2, 0)) + + triangle + .intoPartial[shapes2.Shape] + .withEnumCaseHandledPartial(triangleToPolygon) + .withEnumCaseHandledPartial(rectangleToPolygon) + .transform + .asOption ==> Some(shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0)))) + + val rectangle: shapes1.Shape = + shapes1.Rectangle(shapes1.Point(0, 0), shapes1.Point(6, 4)) + + rectangle + .intoPartial[shapes2.Shape] + .withEnumCaseHandledPartial[shapes1.Shape] { + case r: shapes1.Rectangle => rectangleToPolygon(r) + case t: shapes1.Triangle => triangleToPolygon(t) + } + .transform + .asOption ==> Some( + shapes2.Polygon( + List(shapes2.Point(0, 0), shapes2.Point(0, 4), shapes2.Point(6, 4), shapes2.Point(6, 0)) + ) + ) + } + } + group("flag .enableCustomSubtypeNameComparison") { import fixtures.renames.Subtypes.* diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala index 1ff4c673d..b13ca39b5 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerSealedHierarchySpec.scala @@ -204,6 +204,81 @@ class TotalTransformerSealedHierarchySpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled[Subtype](mapping)") { + + test( + """transform sealed hierarchies from "superset" of case objects to "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: colors2.Black.type): colors1.Color = + colors1.Red + + (colors2.Black: colors2.Color) + .into[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1.Red + + (colors2.Red: colors2.Color) + .into[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1.Red + + (colors2.Green: colors2.Color) + .into[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1.Green + + (colors2.Blue: colors2.Color) + .into[colors1.Color] + .withEnumCaseHandled(blackIsRed) + .transform ==> colors1.Blue + } + + test( + """transform sealed hierarchies from "superset" of case classes to "subset" of case classes when user-provided mapping handled non-trivial cases""" + ) { + def triangleToPolygon(t: shapes1.Triangle): shapes2.Shape = + shapes2.Polygon( + List( + t.p1.transformInto[shapes2.Point], + t.p2.transformInto[shapes2.Point], + t.p3.transformInto[shapes2.Point] + ) + ) + + def rectangleToPolygon(r: shapes1.Rectangle): shapes2.Shape = + shapes2.Polygon( + List( + r.p1.transformInto[shapes2.Point], + shapes2.Point(r.p1.x, r.p2.y), + r.p2.transformInto[shapes2.Point], + shapes2.Point(r.p2.x, r.p1.y) + ) + ) + + val triangle: shapes1.Shape = + shapes1.Triangle(shapes1.Point(0, 0), shapes1.Point(2, 2), shapes1.Point(2, 0)) + + triangle + .into[shapes2.Shape] + .withEnumCaseHandled(triangleToPolygon) + .withEnumCaseHandled(rectangleToPolygon) + .transform ==> shapes2.Polygon(List(shapes2.Point(0, 0), shapes2.Point(2, 2), shapes2.Point(2, 0))) + + val rectangle: shapes1.Shape = + shapes1.Rectangle(shapes1.Point(0, 0), shapes1.Point(6, 4)) + + rectangle + .into[shapes2.Shape] + .withEnumCaseHandled[shapes1.Shape] { + case r: shapes1.Rectangle => rectangleToPolygon(r) + case t: shapes1.Triangle => triangleToPolygon(t) + } + .transform ==> shapes2.Polygon( + List(shapes2.Point(0, 0), shapes2.Point(0, 4), shapes2.Point(6, 4), shapes2.Point(6, 0)) + ) + } + } + group("flag .enableCustomSubtypeNameComparison") { import fixtures.renames.Subtypes.* diff --git a/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala b/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala index 5c24d822d..04f650738 100644 --- a/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala +++ b/chimney/src/test/scalajvm/io/scalaland/chimney/PartialTransformerJavaEnumSpec.scala @@ -119,6 +119,40 @@ class PartialTransformerJavaEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled[Subtype](mapping)") { + + test( + """transform from Java Enum "superset" instances to sealed hierarchy "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: jcolors2.Color.Black.type): colors1.Color = + colors1.Red + + (jcolors2.Color.Black: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Red) + + (jcolors2.Color.Red: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Red) + + (jcolors2.Color.Green: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Green) + + (jcolors2.Color.Blue: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Blue) + } + } + group("setting .withSealedSubtypeHandledPartial[Subtype](mapping)") { test( @@ -153,6 +187,40 @@ class PartialTransformerJavaEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandledPartial[Subtype](mapping)") { + + test( + """transform from Java Enum "superset" instances to sealed hierarchy "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(b: jcolors2.Color.Black.type): partial.Result[colors1.Color] = + partial.Result.fromEmpty + + (jcolors2.Color.Black: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> None + + (jcolors2.Color.Red: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Red) + + (jcolors2.Color.Green: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Green) + + (jcolors2.Color.Blue: jcolors2.Color) + .intoPartial[colors1.Color] + .withEnumCaseHandledPartial((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform + .asOption ==> Some(colors1.Blue) + } + } + group("flag .enableCustomSubtypeNameComparison") { import jrenames.* diff --git a/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala b/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala index fada32e42..8bbb31d8a 100644 --- a/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala +++ b/chimney/src/test/scalajvm/io/scalaland/chimney/TotalTransformerJavaEnumSpec.scala @@ -115,6 +115,36 @@ class TotalTransformerJavaEnumSpec extends ChimneySpec { } } + group("setting .withEnumCaseHandled[Subtype](mapping)") { + + test( + """transform from Java Enum "superset" instances to sealed hierarchy "subset" of case objects when user-provided mapping handled additional cases""" + ) { + def blackIsRed(@unused b: jcolors2.Color.Black.type): colors1.Color = + colors1.Red + + (jcolors2.Color.Black: jcolors2.Color) + .into[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform ==> colors1.Red + + (jcolors2.Color.Red: jcolors2.Color) + .into[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform ==> colors1.Red + + (jcolors2.Color.Green: jcolors2.Color) + .into[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform ==> colors1.Green + + (jcolors2.Color.Blue: jcolors2.Color) + .into[colors1.Color] + .withEnumCaseHandled((b: jcolors2.Color.Black.type) => blackIsRed(b)) + .transform ==> colors1.Blue + } + } + group("flag .enableCustomSubtypeNameComparison") { import jrenames.* From c07e3f3ca88ed00b7af618e125658d63c4e0837c Mon Sep 17 00:00:00 2001 From: Mateusz Kubuszok Date: Fri, 12 Apr 2024 12:27:00 +0200 Subject: [PATCH 3/3] Explain withEnumCaseHandled and withCoproductInstance in mkdocs, explain the difference between withSealedSubtypeHandled and withFieldComputed with matching path --- docs/docs/supported-transformations.md | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/docs/supported-transformations.md b/docs/docs/supported-transformations.md index 2b8f128ec..6e669a092 100644 --- a/docs/docs/supported-transformations.md +++ b/docs/docs/supported-transformations.md @@ -1907,6 +1907,66 @@ If the computation needs to allow failure, there is `.withSealedSubtypeHandledPa }.transform.asEither // Right(Foo.Buzz) ``` +!!! notice + + While `sealed` hierarchies, Scala 3 `enum`s and Java `enum`s fall into the same category of Algebraic Data Types, + manu users might consider them different things and e.g. not look for methods starting with `withSealedSubtype` + when dealing with `enum`s. For that reason we provide an aliases to both of these methods - `withEnumCaseHandled` + and `withEnumCaseHandledPartial`: + + ```scala + //> using scala {{ scala.3 }} + //> using dep io.scalaland::chimney::{{ chimney_version() }} + import io.scalaland.chimney.dsl._ + + enum Foo { + case Baz(a: String) + case Buzz + } + enum Bar { + case Baz(a: String) + case Fizz + case Buzz + } + + (Bar.Baz("value"): Bar).into[Foo].withEnumCaseHandled[Bar.Fizz.type] { + fizz => Foo.Baz(fizz.toString) + }.transform // Foo.Baz("value") + (Bar.Fizz: Bar).into[Foo].withEnumCaseHandled[Bar.Fizz.type] { + fizz => Foo.Baz(fizz.toString) + }.transform // Foo.Baz("Fizz") + (Bar.Buzz: Bar).into[Foo].withEnumCaseHandled[Bar.Fizz.type] { + fizz => Foo.Baz(fizz.toString) + }.transform // Foo.Buzz + + (Bar.Baz("value"): Bar).intoPartial[Foo].withEnumCaseHandledPartial[Bar.Fizz.type] { + fizz => partial.Result.fromEmpty + }.transform.asEither // Right(Foo.Baz("value")) + (Bar.Fizz: Bar).intoPartial[Foo].withEnumCaseHandledPartial[Bar.Fizz.type] { + fizz => partial.Result.fromEmpty + }.transform.asEither // Left(...) + (Bar.Buzz: Bar).intoPartial[Foo].withEnumCaseHandledPartial[Bar.Fizz.type] { + fizz => partial.Result.fromEmpty + }.transform.asEither // Right(Foo.Buzz) + ``` + + These methods are only aliases and there is no difference in behavior between `withSealedCaseHandled` and + `withEnumCaseHandled` - the difference in names exist only for the sake of readability and discoverability. + For similar reason the only name of this method - `withCoproductInstance` - was deprecated (although it was left as + an alias to let the old code work, while encourage users to use newer, more understanable names). + +!!! notice + + `withSealedSubtypeHandled[Subtype](...)` might look similar to `withFieldComputed(_.matching[Subtype], ...)` but + the difference becomes clear when we provide the types: + + * `foo.into[Bar].withSealedSubtypeHandled[Foo.Baz](subtype => ...).transform` matches the subtype on the **source** + value, while + * `foo.into[Bar].withFieldComputed(_.matching[Bar.Baz], foo => ...)` - provides an override on the **target** + type's value + + so these 2 pieces of code covers difference use cases. + !!! warning Due to limitations of Scala 2, when you want to use `.withSealedSubtypeHandled` or `.withSealedSubtypeHandledPartial` with