Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new utilities to partial.Result, improve existing Scaladocs a bit #446

Merged
merged 6 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Information about Scala macros can be found on:
* [EPFL papers](https://infoscience.epfl.ch/search?ln=en&as=1&m1=p&p1=macros&f1=keyword&op1=a&m2=p&p2=scala&f2=&op2=a&m3=a&p3=&f3=&dt=&d1d=&d1m=&d1y=&d2d=&d2m=&d2y=&rm=&action_search=Search&sf=title&so=a&rg=10&c=Infoscience&of=hb)

Very basic introduction can be found in [design doc](DESIGN.md) and in the
[Under the hood](https://chimney.readthedocs.io/en/stable/under-the-hood/) section of the documentation.
[Under the hood](https://chimney.readthedocs.io/under-the-hood/) section of the documentation.
From then on we suggest looking at tests, and using`.enableMacrosLogging` to see how some branches are triggered.
If still at doubt, you can ask us on GH discussions.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ If you are looking to up-to-date artifacts versions ready to copy-paste into you
## Contribution

A way to get started is described in [CONTRIBUTING.md](CONTRIBUTING.md) and the general overview of the architecture
is given in [DESIGN.md](DESIGN.md) and in [Under the hood](https://chimney.readthedocs.io/en/stable/under-the-hood/)
is given in [DESIGN.md](DESIGN.md) and in [Under the hood](https://chimney.readthedocs.io/under-the-hood/)
section of the documentation.

## Thanks
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.scalaland.chimney.partial

package object syntax {

/** Provides operations lifting [[scala.Option]] to [[io.scalaland.chimney.partial.Result]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#partialresult-utilities]] for more details
*
* @tparam A successful value type
* @param option value to convert
*
* @since 0.8.5
*/
implicit class PartialResultOptionOps[A](private val option: Option[A]) extends AnyVal {

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[io.scalaland.chimney.partial.Error]] on [[scala.None]].
*
* @param onEmpty thunk creating error on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orErrorAsResult(onEmpty: => Error): Result[A] = Result.fromOptionOrError(option, onEmpty)

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[java.lang.String]] on [[scala.None]].
*
* @param onEmpty thunk creating error message on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orStringAsResult(onEmpty: => String): Result[A] = Result.fromOptionOrString(option, onEmpty)

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[java.lang.Throwable]] on [[scala.None]].
*
* @param onEmpty thunk creating exception on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orThrowableAsResult(onEmpty: => Throwable): Result[A] = Result.fromOptionOrThrowable(option, onEmpty)
}

/** Provides operations lifting `F[A]` to [[io.scalaland.chimney.partial.Result]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#partialresult-utilities]] for more details
* @tparam F wrapper type
* @tparam A successful value type
* @param fa value to convert
*
* @since 0.8.5
*/
implicit class PartialResultAsResultOps[F[_], A](private val fa: F[A]) extends AnyVal {

/** Converts `F[A]` to [[io.scalaland.chimney.partial.Result]].
*
* @return result with error values handled
*
* @since 0.8.5
*/
def asResult(implicit F: AsResult[F]): Result[A] = F.asResult(fa)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.scalaland.chimney.partial.syntax

import io.scalaland.chimney.partial.{AsResult, Error, Result}

/** Provides operations lifting [[scala.Option]] to [[io.scalaland.chimney.partial.Result]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#partialresult-utilities]] for more details
*
* @tparam A successful value type
* @param option value to convert
*
* @since 0.8.5
*/
extension [A](option: Option[A])

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[io.scalaland.chimney.partial.Error]] on [[scala.None]].
*
* @param onEmpty thunk creating error on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orErrorAsResult(onEmpty: => Error): Result[A] = Result.fromOptionOrError(option, onEmpty)

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[java.lang.String]] on [[scala.None]].
*
* @param onEmpty thunk creating error message on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orStringAsResult(onEmpty: => String): Result[A] = Result.fromOptionOrString(option, onEmpty)

/** Converts [[scala.Some]] to [[io.scalaland.chimney.partial.Result.Value]] and uses user-provided
* [[java.lang.Throwable]] on [[scala.None]].
*
* @param onEmpty thunk creating exception on [[scala.None]]
* @return result with [[scala.None]] handled
*
* @since 0.8.5
*/
def orThrowableAsResult(onEmpty: => Throwable): Result[A] = Result.fromOptionOrThrowable(option, onEmpty)

/** Provides operations lifting `F[A]` to [[io.scalaland.chimney.partial.Result]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#partialresult-utilities]] for more details
*
* @tparam F wrapper type
* @tparam A successful value type
* @param fa value to convert
*
* @since 0.8.5
*/
extension [F[_], A](fa: F[A])
/** Converts `F[A]` to [[io.scalaland.chimney.partial.Result]].
*
* @return result with error values handled
*
* @since 0.8.5
*/
def asResult(using F: AsResult[F]): Result[A] = F.asResult(fa)
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package io.scalaland.chimney
import io.scalaland.chimney.dsl.{PartialTransformerDefinition, TransformerDefinitionCommons}
import io.scalaland.chimney.internal.runtime.{TransformerCfg, TransformerFlags}

/** Type class expressing partial transformation between
* source type `From` and target type `To`, with the ability
/** Type class expressing partial transformation between source type `From` and target type `To`, with the ability
* of reporting path-annotated transformation error(s).
*
* @see [[https://chimney.readthedocs.io/supported-transformations/]]
* @see [[https://chimney.readthedocs.io/supported-transformations/#total-transformers-vs-partialtransformers]]
*
* @tparam From type of input value
* @tparam To type of output value
*
Expand All @@ -17,8 +19,9 @@ trait PartialTransformer[From, To] extends PartialTransformer.AutoDerived[From,
/** Run transformation using provided value as a source.
*
* @param src source value
* @param failFast should fail as early as the first set of errors appear
* @return result of transformation
* @param failFast whether the transformerion should return as early as the first set of errors appear (`true`),
* or should it attempt to convert what it can and then aggregate all errors (`false`)
* @return [[io.scalaland.chimney.partial.Result]] of the transformation
*
* @since 0.7.0
*/
Expand All @@ -27,7 +30,7 @@ trait PartialTransformer[From, To] extends PartialTransformer.AutoDerived[From,
/** Run transformation using provided value as a source in error accumulation mode.
*
* @param src source value
* @return result of transformation
* @return [[io.scalaland.chimney.partial.Result]] of the transformation
*
* @since 0.7.0
*/
Expand All @@ -37,14 +40,21 @@ trait PartialTransformer[From, To] extends PartialTransformer.AutoDerived[From,
/** Run transformation using provided value as a source in short-circuit (fail fast) mode.
*
* @param src source value
* @return result of transformation
* @return [[io.scalaland.chimney.partial.Result]] of the transformation
*
* @since 0.7.0
*/
final def transformFailFast(src: From): partial.Result[To] =
transform(src, failFast = true)
}

/** Companion of [[io.scalaland.chimney.PartialTransformer]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/]]
* @see [[https://chimney.readthedocs.io/supported-transformations/#total-transformers-vs-partialtransformers]]
*
* @since 0.7.0
*/
object PartialTransformer extends PartialTransformerCompanionPlatform {

/** Construct ad-hoc instance of partial transformer from transforming function returning partial result.
Expand Down Expand Up @@ -93,8 +103,8 @@ object PartialTransformer extends PartialTransformerCompanionPlatform {
def liftTotal[From, To](t: Transformer[From, To]): PartialTransformer[From, To] =
fromFunction[From, To](t.transform)

/** Creates an empty [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] that
* you can customize to derive [[io.scalaland.chimney.PartialTransformer]].
/** Creates an empty [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] that you can customize to derive
* [[io.scalaland.chimney.PartialTransformer]].
*
* @see [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] for available settings
*
Expand All @@ -107,9 +117,23 @@ object PartialTransformer extends PartialTransformerCompanionPlatform {
def define[From, To]: PartialTransformerDefinition[From, To, TransformerCfg.Empty, TransformerFlags.Default] =
new PartialTransformerDefinition(TransformerDefinitionCommons.emptyRuntimeDataStore)

/** Type class used when you want o allow using automatically derived transformations.
*
* When we want to only allow semiautomatically derived/manually defined instances you should use
* [[io.scalaland.chimney.PartialTransformer]].
*
* @see [[https://chimney.readthedocs.io/cookbook/#automatic-semiautomatic-and-inlined-derivation]] for more details
*
* @tparam From type of input value
* @tparam To type of output value
*
* @since 0.8.0
*/
trait AutoDerived[From, To] {
def transform(src: From, failFast: Boolean): partial.Result[To]
}

/** @since 0.8.0 */
object AutoDerived extends PartialTransformerAutoDerivedCompanionPlatform {

implicit def liftTotal[From, To](implicit total: Transformer[From, To]): AutoDerived[From, To] =
Expand Down
27 changes: 24 additions & 3 deletions chimney/src/main/scala/io/scalaland/chimney/Patcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import io.scalaland.chimney.dsl.PatcherDefinition
import io.scalaland.chimney.internal.runtime.{PatcherCfg, PatcherFlags}

/** Type class definition that wraps patching behavior.
*
* @see [[https://chimney.readthedocs.io/supported-patching/]]
*
* @tparam A type of object to apply patch to
* @tparam Patch type of patch object
Expand All @@ -23,11 +25,16 @@ trait Patcher[A, Patch] extends Patcher.AutoDerived[A, Patch] {
def patch(obj: A, patch: Patch): A
}

/** @since 0.1.3 */
/** Companion of [[io.scalaland.chimney.Patcher]].
*
* @see [[https://chimney.readthedocs.io/supported-patching/]]
*
* @since 0.1.3
*/
object Patcher extends PatcherCompanionPlatform {

/** Creates an empty [[io.scalaland.chimney.dsl.PatcherDefinition]] that
* you can customize to derive [[io.scalaland.chimney.Patcher]].
/** Creates an empty [[io.scalaland.chimney.dsl.PatcherDefinition]] that you can customize to derive
* [[io.scalaland.chimney.Patcher]].
*
* @see [[io.scalaland.chimney.dsl.PatcherDefinition]] for available settings
*
Expand All @@ -40,8 +47,22 @@ object Patcher extends PatcherCompanionPlatform {
def define[A, Patch]: PatcherDefinition[A, Patch, PatcherCfg.Empty, PatcherFlags.Default] =
new PatcherDefinition

/** Type class used when you want o allow using automatically derived patchings.
*
* When we want to only allow semiautomatically derived/manually defined instances you should use
* [[io.scalaland.chimney.Patcher]].
*
* @see [[https://chimney.readthedocs.io/cookbook/#automatic-semiautomatic-and-inlined-derivation]] for more details
*
* @tparam A type of object to apply patch to
* @tparam Patch type of patch object
*
* @since 0.8.0
*/
trait AutoDerived[A, Patch] {
def patch(obj: A, patch: Patch): A
}

/** @since 0.8.0 */
object AutoDerived extends PatcherAutoDerivedCompanionPlatform
}
35 changes: 29 additions & 6 deletions chimney/src/main/scala/io/scalaland/chimney/Transformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package io.scalaland.chimney
import io.scalaland.chimney.dsl.{PartialTransformerDefinition, TransformerDefinition, TransformerDefinitionCommons}
import io.scalaland.chimney.internal.runtime.{TransformerCfg, TransformerFlags}

/** Type class expressing total transformation between
* source type `From` and target type `To`.
/** Type class expressing total transformation between source type `From` and target type `To`.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/]]
* @see [[https://chimney.readthedocs.io/supported-transformations/#total-transformers-vs-partialtransformers]]
*
* @tparam From type of input value
* @tparam To type of output value
Expand All @@ -23,10 +25,17 @@ trait Transformer[From, To] extends Transformer.AutoDerived[From, To] {
def transform(src: From): To
}

/** Companion of [[io.scalaland.chimney.Transformer]].
*
* @see [[https://chimney.readthedocs.io/supported-transformations/]]
* @see [[https://chimney.readthedocs.io/supported-transformations/#total-transformers-vs-partialtransformers]]
*
* @since 0.2.0
*/
object Transformer extends TransformerCompanionPlatform {

/** Creates an empty [[io.scalaland.chimney.dsl.TransformerDefinition]] that
* you can customize to derive [[io.scalaland.chimney.Transformer]].
/** Creates an empty [[io.scalaland.chimney.dsl.TransformerDefinition]] that you can customize to derive
* [[io.scalaland.chimney.Transformer]].
*
* @see [[io.scalaland.chimney.dsl.TransformerDefinition]] for available settings
*
Expand All @@ -39,8 +48,8 @@ object Transformer extends TransformerCompanionPlatform {
def define[From, To]: TransformerDefinition[From, To, TransformerCfg.Empty, TransformerFlags.Default] =
new TransformerDefinition(TransformerDefinitionCommons.emptyRuntimeDataStore)

/** Creates an empty [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] that
* you can customize to derive [[io.scalaland.chimney.PartialTransformer]].
/** Creates an empty [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] that you can customize to derive
* [[io.scalaland.chimney.PartialTransformer]].
*
* @see [[io.scalaland.chimney.dsl.PartialTransformerDefinition]] for available settings
*
Expand All @@ -53,8 +62,22 @@ object Transformer extends TransformerCompanionPlatform {
def definePartial[From, To]: PartialTransformerDefinition[From, To, TransformerCfg.Empty, TransformerFlags.Default] =
new PartialTransformerDefinition(TransformerDefinitionCommons.emptyRuntimeDataStore)

/** Type class used when you want o allow using automatically derived transformations.
*
* When we want to only allow semiautomatically derived/manually defined instances you should use
* [[io.scalaland.chimney.Transformer]].
*
* @see [[https://chimney.readthedocs.io/cookbook/#automatic-semiautomatic-and-inlined-derivation]] for more details
*
* @tparam From type of input value
* @tparam To type of output value
*
* @since 0.8.0
*/
trait AutoDerived[From, To] {
def transform(src: From): To
}

/** @since 0.8.0 */
object AutoDerived extends TransformerAutoDerivedCompanionPlatform
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package io.scalaland.chimney.dsl

/** Whether derivation should prefer total or partial transformers if both are provided for some field transformation.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#resolving-priority-of-implicit-total-vs-partial-transformers]] for more details
*
* @since 0.7.0
*/
sealed abstract class ImplicitTransformerPreference

/** Tell the derivation to prefer total transformers.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#resolving-priority-of-implicit-total-vs-partial-transformers]] for more details
*
* @since 0.7.0
*/
case object PreferTotalTransformer extends ImplicitTransformerPreference

/** Tell the derivation to prefer partial transformers.
*
* @see [[https://chimney.readthedocs.io/supported-transformations/#resolving-priority-of-implicit-total-vs-partial-transformers]] for more details
*
* @since 0.7.0
*/
Expand Down
Loading
Loading