![JAR search and dependency download from the Maven repository](/logo.png)
io.scalaland.chimney.internal.compiletime.DerivationEngine.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of chimney-engine_2.13 Show documentation
Show all versions of chimney-engine_2.13 Show documentation
Chimney derivation engine exposed for reuse in other libraries
The newest version!
package io.scalaland.chimney.internal.compiletime
/** Chimney derivation engine as API.
*
* Intended usage:
*
* 1. Implement your own derivation rules in a mixins based on implementation-agnostic API:
*
* {{{
* trait MyOwnImplicitRuleModule { this: DerivationEngine =>
*
* protected object MyOwnImplicitRule extends Rule("MyOwnImplicit") {
*
* def expand[From, To](implicit ctx: TransformationContext[From, To]): DerivationResult[Rule.ExpansionRule[To] =
* ...
* }
* }
* }}}
*
* (Do the same when you need more types and utility methods shared between 2 different macro implementations.)
*
* 2. Mix-in with the implementation for Scala 2/Scala 3 macros:
*
* {{{
* // Scala 2
* trait MyMacrosImpl
* extends DerivationEngineImpl
* with StandardRules
* with MyOwnImplicitRuleModule {
*
* final override protected val rulesAvailableForPlatform: List[Rule] = List(
* MyOwnImplicitRule,
* TransformSubtypesRule,
* TransformToSingletonRule,
* TransformOptionToOptionRule,
* TransformPartialOptionToNonOptionRule,
* TransformToOptionRule,
* TransformValueClassToValueClassRule,
* TransformValueClassToTypeRule,
* TransformTypeToValueClassRule,
* TransformEitherToEitherRule,
* TransformMapToMapRule,
* TransformIterableToIterableRule,
* TransformProductToProductRule,
* TransformSealedHierarchyToSealedHierarchyRule
* )
* }
* }}}
*
* {{{
* // Scala 3
* abstract class MyMacrosImpl(q: scala.quoted.Quotes)
* extends DerivationEngineImpl(q)
* with StandardRules
* with MyOwnImplicitRuleModule {
*
* final override protected val rulesAvailableForPlatform: List[Rule] = List(
* MyOwnImplicitRule,
* TransformSubtypesRule,
* TransformToSingletonRule,
* TransformOptionToOptionRule,
* TransformPartialOptionToNonOptionRule,
* TransformToOptionRule,
* TransformValueClassToValueClassRule,
* TransformValueClassToTypeRule,
* TransformTypeToValueClassRule,
* TransformEitherToEitherRule,
* TransformMapToMapRule,
* TransformIterableToIterableRule,
* TransformProductToProductRule,
* TransformSealedHierarchyToSealedHierarchyRule
* )
* }}}
*
* (You can provide platform-specific implementations of your types/utilities the same way).
*
* 3. Use `deriveFinalTransformationResultExpr` in your macros:
*
* {{{
* // Scala 2
* import c.universe._
*
* def deriveMyTypeClass[
* From: c.WeakTypeTag,
* To: c.WeakTypeTag
* ]: c.Expr[MyTypeClass[From, To]] = {
*
* def deriveBody(src: c.Expr[From]): c.Expr[To] = {
* val cfg = TransformerConfiguration() // customize, read config with DSL etc
* val context = TransformationContext.ForTotal.create(src, cfg)
*
* deriveFinalTransformationResultExpr(context).toEither.fold(
* derivationErrors => reportError(derivationErrors.toString), // customize
* identity
* )
* }
*
* val inputName = freshTermName(...)
* c.Expr[MyTypeClass[From, To](
* q"""
* new MyTypeClass[${Type[From]}, ${Type[To]}] {
* def encode($inputName: ${Type[From]}): ${Type[To]} = ${deriveBody(c.Expr[From](q"$inputName"))}
* }
* """
* )
* )
* }
* }}}
*
* {{{
* // Scala 3
* import q.*, q.reflect.*
*
* def deriveMyTypeClass[
* From: Type,
* To: Type
* ]: Expr[MyTypeClass[From, To]] = {
*
* def deriveBody(src: Expr[From]): Expr[To] = {
* val cfg = TransformerConfiguration() // customize, read config with DSL etc
* val context = TransformationContext.ForTotal.create(src, cfg)
*
* deriveFinalTransformationResultExpr(context).toEither.fold(
* derivationErrors => reportError(derivationErrors.toString), // customize
* identity
* )
* }
*
* '{
* new MyTypeClass[From, To] {
* def convert(src: From): To = ${deriveBody('toExpr)}
* }
* }
* )
* }
* }}}
*/
trait DerivationEngine
extends derivation.transformer.Derivation
with derivation.transformer.Configurations
with derivation.transformer.Contexts
with derivation.transformer.ImplicitSummoning
with derivation.transformer.ResultOps
with datatypes.IterableOrArrays
with datatypes.ProductTypes
with datatypes.SealedHierarchies
with datatypes.SingletonTypes
with datatypes.ValueClasses
with derivation.transformer.integrations.OptionalValues
with derivation.transformer.integrations.PartiallyBuildIterables
with derivation.transformer.integrations.TotallyBuildIterables
with derivation.transformer.integrations.TotallyOrPartiallyBuildIterables
with derivation.transformer.rules.TransformationRules {
type DerivationResult[+A] = io.scalaland.chimney.internal.compiletime.DerivationResult[A]
val DerivationResult = io.scalaland.chimney.internal.compiletime.DerivationResult
/** Adapts TransformationExpr[To] to expected type of transformation */
def deriveFinalTransformationResultExpr[From, To](implicit
ctx: TransformationContext[From, To]
): DerivationResult[Expr[ctx.Target]] =
DerivationResult.log(s"Start derivation with context: $ctx") >>
deriveTransformationResultExpr[From, To]
.map { transformationExpr =>
ctx.fold(_ => transformationExpr.ensureTotal.asInstanceOf[Expr[ctx.Target]])(_ =>
transformationExpr.ensurePartial.asInstanceOf[Expr[ctx.Target]]
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy