Skip to content

Commit

Permalink
Provide documentation for custom constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
MateuszKubuszok committed Dec 18, 2023
1 parent 90bd4ed commit 6197111
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,39 @@ final class PartialTransformerDefinition[From, To, Cfg <: TransformerCfg, Flags
): PartialTransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
macro PartialTransformerDefinitionMacros.withCoproductInstancePartialImpl[From, To, Cfg, Flags, Inst]

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]]
*
* @since 0.8.4
*/
def withConstructor[Ctor](
f: Ctor
)(implicit ev: IsFunction.Of[Ctor, To]): PartialTransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
macro PartialTransformerDefinitionMacros.withConstructorImpl[From, To, Cfg, Flags]

// TODO: docs
/** Use `f` instead of the primary constructor to parse into `partial.Result[To]` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `partial.Result[To]`
* @param f method name or lambda which constructs `partial.Result[To]`
* @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]]
*
* @since 0.8.4
*/
def withConstructorPartial[Ctor](
f: Ctor
)(implicit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,39 @@ final class PartialTransformerInto[From, To, Cfg <: TransformerCfg, Flags <: Tra
): PartialTransformerInto[From, To, ? <: TransformerCfg, Flags] =
macro PartialTransformerIntoMacros.withCoproductInstancePartialImpl[From, To, Cfg, Flags, Inst]

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.PartialTransformerInto]]
*
* @since 0.8.4
*/
def withConstructor[Ctor](
f: Ctor
)(implicit ev: IsFunction.Of[Ctor, To]): PartialTransformerInto[From, To, ? <: TransformerCfg, Flags] =
macro PartialTransformerIntoMacros.withConstructorImpl[From, To, Cfg, Flags]

// TODO: docs
/** Use `f` instead of the primary constructor to parse into `partial.Result[To]` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `partial.Result[To]`
* @param f method name or lambda which constructs `partial.Result[To]`
* @return [[io.scalaland.chimney.dsl.PartialTransformerInto]]
*
* @since 0.8.4
*/
def withConstructorPartial[Ctor](
f: Ctor
)(implicit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,20 @@ final class TransformerDefinition[From, To, Cfg <: TransformerCfg, Flags <: Tran
def withCoproductInstance[Inst](f: Inst => To): TransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
macro TransformerDefinitionMacros.withCoproductInstanceImpl[From, To, Cfg, Flags, Inst]

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.TransformerDefinition]]
*
* @since 0.8.4
*/
def withConstructor[Ctor](
f: Ctor
)(implicit ev: IsFunction.Of[Ctor, To]): TransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,20 @@ final class TransformerInto[From, To, Cfg <: TransformerCfg, Flags <: Transforme
def withCoproductInstance[Inst](f: Inst => To): TransformerInto[From, To, ? <: TransformerCfg, Flags] =
macro TransformerIntoMacros.withCoproductInstanceImpl[From, To, Cfg, Flags, Inst]

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.TransformerInto]]
*
* @since 0.8.4
*/
def withConstructor[Ctor](
f: Ctor
)(implicit ev: IsFunction.Of[Ctor, To]): TransformerInto[From, To, ? <: TransformerCfg, Flags] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,39 @@ final class PartialTransformerDefinition[From, To, Cfg <: TransformerCfg, Flags
): PartialTransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
${ PartialTransformerDefinitionMacros.withCoproductInstancePartial('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]]
*
* @since 0.8.4
*/
transparent inline def withConstructor[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, To]): PartialTransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
${ PartialTransformerDefinitionMacros.withConstructorImpl('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to parse into `partial.Result[To]` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `partial.Result[To]`
* @param f method name or lambda which constructs `partial.Result[To]`
* @return [[io.scalaland.chimney.dsl.PartialTransformerDefinition]]
*
* @since 0.8.4
*/
transparent inline def withConstructorPartial[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, partial.Result[To]]): PartialTransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,39 @@ final class PartialTransformerInto[From, To, Cfg <: TransformerCfg, Flags <: Tra
): PartialTransformerInto[From, To, ? <: TransformerCfg, Flags] =
${ PartialTransformerIntoMacros.withCoproductInstancePartialImpl('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.PartialTransformerInto]]
*
* @since 0.8.4
*/
transparent inline def withConstructor[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, To]): PartialTransformerInto[From, To, ? <: TransformerCfg, Flags] =
${ PartialTransformerIntoMacros.withConstructorImpl('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to parse into `partial.Result[To]` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `partial.Result[To]`
* @param f method name or lambda which constructs `partial.Result[To]`
* @return [[io.scalaland.chimney.dsl.PartialTransformerInto]]
*
* @since 0.8.4
*/
transparent inline def withConstructorPartial[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, partial.Result[To]]): PartialTransformerInto[From, To, ? <: TransformerCfg, Flags] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,20 @@ final class TransformerDefinition[From, To, Cfg <: TransformerCfg, Flags <: Tran
): TransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
${ TransformerDefinitionMacros.withCoproductInstance('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.TransformerDefinition]]
*
* @since 0.8.4
*/
transparent inline def withConstructor[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, To]): TransformerDefinition[From, To, ? <: TransformerCfg, Flags] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,20 @@ final class TransformerInto[From, To, Cfg <: TransformerCfg, Flags <: Transforme
): TransformerInto[From, To, ? <: TransformerCfg, Flags] =
${ TransformerIntoMacros.withCoproductInstanceImpl('this, 'f) }

// TODO: docs
/** Use `f` instead of the primary constructor to construct the `To` value.
*
* Macro will read the names of Eta-expanded method's/lambda's parameters and try to match them with `From` getters.
*
* Values for each parameter can be provided the same way as if they were normal constructor's arguments.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#types-with-manually-provided-constructors]] for more details
*
* @tparam Ctor type of the Eta-expanded method/lambda which should return `To`
* @param f method name or lambda which constructs `To`
* @return [[io.scalaland.chimney.dsl.TransformerInto]]
*
* @since 0.8.4
*/
transparent inline def withConstructor[Ctor](
inline f: Ctor
)(using IsFunction.Of[Ctor, To]): TransformerInto[From, To, ? <: TransformerCfg, Flags] =
Expand Down
31 changes: 22 additions & 9 deletions docs/docs/supported-transformations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2014,11 +2014,16 @@ constructor for `PartialTransformer`:
def smartConstructor(value: String): partial.Result[Bar] =
partial.Result.fromEitherString(Bar.parse(value))

Foo("10").intoPartial[Bar].withConstructorPartial(smartConstructor).transform.asEither // Right(Bar(10))
Foo("10")
.intoPartial[Bar]
.withConstructorPartial(smartConstructor)
.transform.asEither // Right(Bar(10))

Foo("10").intoPartial[Bar].withConstructorPartial { (value: String) =>
partial.Result.fromEitherString(Bar.parse(value))
}.transform.asEither // Right(Bar(1000))
Foo("10")
.intoPartial[Bar]
.withConstructorPartial { (value: String) =>
partial.Result.fromEitherString(Bar.parse(value))
}.transform.asEither // Right(Bar(1000))
```

You can use this to automatically match the source's getters e.g. against Scala 3's `opaque type`'s constructor's
Expand All @@ -2027,8 +2032,8 @@ be difficult to be automatically recognized as such:

!!! example

Due to nature of `opaque type`s to work this example needs to have opaque types defined in a different file than
where they are being used:
Due to nature of `opaque type`s to work this example needs to have opaque types defined in a different `.scala`
file than where they are being used:

```scala
package models
Expand All @@ -2053,14 +2058,22 @@ be difficult to be automatically recognized as such:
import io.scalaland.chimney.{partial, PartialTransformer}
import models.{Foo, Bar}

given PartialTransformer[Foo, Bar] = PartialTransformer.define[Foo, Bar].withConstructorPa>
partial.Result.fromEitherString(Bar.parse(value))
}.buildTransformer
given PartialTransformer[Foo, Bar] = PartialTransformer.define[Foo, Bar]
.withConstructorPartial { (value: String) =>
partial.Result.fromEitherString(Bar.parse(value))
}.buildTransformer

@main def example: Unit =
println(Foo("10").transformIntoPartial[Bar].asEither)
```

!!! tip

`opaque type`s usually have only one constructor argument and usually it is easier to not transform them that way,
but rather call their constructor directly. If `opaque type`s are nested in the transformed structure, it might be
easier to define [a custom transformer](#custom-transformations), perhaps by using a dedicated new type/refined type
library and [providing an integration for all of its types](cookbook.md#libraries-with-smart-constructors).

## Custom transformations

For virtually every 2 types that you want, you can define your own `Transformer` or `PartialTransformer` as `implicit`.
Expand Down

0 comments on commit 6197111

Please sign in to comment.