Skip to content

Commit

Permalink
Extract SourceMatching out of Matching for more safety
Browse files Browse the repository at this point in the history
  • Loading branch information
MateuszKubuszok committed Apr 12, 2024
1 parent 5d924ca commit 41b5e0b
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ private[compiletime] trait ChimneyTypesPlatform extends ChimneyTypes { this: Chi
val fixedInit = fixJavaEnums(init)
import fixedSubtype.Underlying as FixedSubtype, fixedInit.Underlying as FixedInit
Path.Matching[FixedInit, FixedSubtype].as_?<[runtime.Path]
case Path.SourceMatching(init, subtype) =>
val fixedSubtype = fixJavaEnum(subtype)
val fixedInit = fixJavaEnums(init)
import fixedSubtype.Underlying as FixedSubtype, fixedInit.Underlying as FixedInit
Path.SourceMatching[FixedInit, FixedSubtype].as_?<[runtime.Path]
case Path.EveryItem(init) =>
val fixedInit = fixJavaEnums(init)
import fixedInit.Underlying as FixedInit
Expand Down Expand Up @@ -359,6 +364,13 @@ private[compiletime] trait ChimneyTypesPlatform extends ChimneyTypes { this: Chi
if (A.isCtor[runtime.Path.Matching[?, ?]]) Some(A.param_<[runtime.Path](0) -> A.param(1))
else scala.None
}
object SourceMatching extends SourceMatchingModule {
def apply[Init <: runtime.Path: Type, Subtype: Type]: Type[runtime.Path.SourceMatching[Init, Subtype]] =
weakTypeTag[runtime.Path.SourceMatching[Init, Subtype]]
def unapply[A](A: Type[A]): Option[(?<[runtime.Path], ??)] =
if (A.isCtor[runtime.Path.SourceMatching[?, ?]]) Some(A.param_<[runtime.Path](0) -> A.param(1))
else scala.None
}
object EveryItem extends EveryItemModule {
def apply[Init <: runtime.Path: Type]: Type[runtime.Path.EveryItem[Init]] =
weakTypeTag[runtime.Path.EveryItem[Init]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class PartialTransformerDefinitionMacros(val c: whitebox.Context) extends utils.
.asInstanceOfExpr[PartialTransformerDefinition[
From,
To,
CaseComputed[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand All @@ -108,7 +108,7 @@ class PartialTransformerDefinitionMacros(val c: whitebox.Context) extends utils.
.asInstanceOfExpr[PartialTransformerDefinition[
From,
To,
CaseComputedPartial[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputedPartial[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class PartialTransformerIntoMacros(val c: whitebox.Context) extends utils.DslMac
.asInstanceOfExpr[PartialTransformerInto[
From,
To,
CaseComputed[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand All @@ -109,7 +109,7 @@ class PartialTransformerIntoMacros(val c: whitebox.Context) extends utils.DslMac
.asInstanceOfExpr[PartialTransformerInto[
From,
To,
CaseComputedPartial[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputedPartial[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class TransformerDefinitionMacros(val c: whitebox.Context) extends utils.DslMacr
.asInstanceOfExpr[TransformerDefinition[
From,
To,
CaseComputed[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class TransformerIntoMacros(val c: whitebox.Context) extends utils.DslMacroUtils
.asInstanceOfExpr[TransformerInto[
From,
To,
CaseComputed[Path.Matching[Path.Root, FixedSubtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, FixedSubtype], Overrides],
Flags
]]
}.applyJavaEnumFixFromClosureSignature[Subtype](f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,14 @@ private[compiletime] trait ChimneyTypesPlatform extends ChimneyTypes { this: Chi
Some((Type[init].as_?<[runtime.Path], Type[subtype].as_??))
case _ => scala.None
}
object SourceMatching extends SourceMatchingModule {
def apply[Init <: runtime.Path: Type, Subtype: Type]: Type[runtime.Path.SourceMatching[Init, Subtype]] =
quoted.Type.of[runtime.Path.SourceMatching[Init, Subtype]]
def unapply[A](tpe: Type[A]): Option[(?<[runtime.Path], ??)] = tpe match
case '[runtime.Path.SourceMatching[init, subtype]] =>
Some((Type[init].as_?<[runtime.Path], Type[subtype].as_??))
case _ => scala.None
}
object EveryItem extends EveryItemModule {
def apply[Init <: runtime.Path: Type]: Type[runtime.Path.EveryItem[Init]] =
quoted.Type.of[runtime.Path.EveryItem[Init]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ object PartialTransformerDefinitionMacros {
.asInstanceOf[PartialTransformerDefinition[
From,
To,
CaseComputed[Path.Matching[Path.Root, Subtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}
Expand All @@ -176,7 +176,7 @@ object PartialTransformerDefinitionMacros {
.asInstanceOf[PartialTransformerDefinition[
From,
To,
CaseComputedPartial[Path.Matching[Path.Root, Subtype], Overrides],
CaseComputedPartial[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ object PartialTransformerIntoMacros {
.asInstanceOf[PartialTransformerInto[
From,
To,
CaseComputed[Path.Matching[Path.Root, Subtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}
Expand All @@ -166,7 +166,7 @@ object PartialTransformerIntoMacros {
.asInstanceOf[PartialTransformerInto[
From,
To,
CaseComputedPartial[Path.Matching[Path.Root, Subtype], Overrides],
CaseComputedPartial[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ object TransformerDefinitionMacros {
.asInstanceOf[TransformerDefinition[
From,
To,
CaseComputed[Path.Matching[Path.Root, Subtype], Overrides],
CaseComputed[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ object TransformerIntoMacros {
'{
WithRuntimeDataStore
.update($ti, $f)
.asInstanceOf[TransformerInto[From, To, CaseComputed[Path.Matching[Path.Root, Subtype], Overrides], Flags]]
.asInstanceOf[TransformerInto[
From,
To,
CaseComputed[Path.SourceMatching[Path.Root, Subtype], Overrides],
Flags
]]
}

def withConstructorImpl[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ private[compiletime] trait ChimneyTypes { this: ChimneyDefinitions =>
Any,
runtime.Path.Matching
] { this: Matching.type => }
val SourceMatching: SourceMatchingModule
trait SourceMatchingModule
extends Type.Ctor2UpperBounded[
runtime.Path,
Any,
runtime.Path.SourceMatching
] { this: SourceMatching.type => }
val EveryItem: EveryItemModule
trait EveryItemModule
extends Type.Ctor1UpperBounded[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ private[compiletime] trait Configurations { this: Derivation =>
import Path.*, Path.Segment.*
def select(name: String): Path = new Path(segments :+ Select(name))
def matching[Tpe: Type]: Path = new Path(segments :+ Matching(Type[Tpe].as_??))
def sourceMatching[Tpe: Type]: Path = new Path(segments :+ SourceMatching(Type[Tpe].as_??))
def everyItem: Path = new Path(segments :+ EveryItem)
def everyMapKey: Path = new Path(segments :+ EveryMapKey)
def everyMapValue: Path = new Path(segments :+ EveryMapValue)
Expand Down Expand Up @@ -124,6 +125,11 @@ private[compiletime] trait Configurations { this: Derivation =>
path.segments.headOption.collect { case Segment.Matching(tpe) => tpe -> new Path(path.segments.tail) }
}

object AtSourceSubtype {
def unapply(path: Path): Option[(??, Path)] =
path.segments.headOption.collect { case Segment.SourceMatching(tpe) => tpe -> new Path(path.segments.tail) }
}

object AtItem {
def unapply(path: Path): Option[Path] =
path.segments.headOption.collect { case Segment.EveryItem => new Path(path.segments.tail) }
Expand Down Expand Up @@ -152,6 +158,14 @@ private[compiletime] trait Configurations { this: Derivation =>

override def toString: String = s".matching[${Type.prettyPrint(tpe.Underlying)}]"
}
final case class SourceMatching(tpe: ??) extends Segment {
override def equals(obj: Any): Boolean = obj match {
case Matching(tpe2) => tpe.Underlying =:= tpe2.Underlying
case _ => false
}

override def toString: String = s" if src.isInstanceOf[${Type.prettyPrint(tpe.Underlying)}]"
}
case object EveryItem extends Segment {
override def toString: String = ".everyItem"
}
Expand Down Expand Up @@ -207,10 +221,11 @@ private[compiletime] trait Configurations { this: Derivation =>
) {

private lazy val runtimeOverridesForCurrent = runtimeOverrides.filter {
case (Path.AtField(_, Path.Root), _: TransformerOverride.ForField) => true
case (Path.AtSubtype(_, Path.Root), _: TransformerOverride.ForSubtype) => true
case (Path.Root, _: TransformerOverride.ForConstructor) => true
case _ => false
case (Path.AtField(_, Path.Root), _: TransformerOverride.ForField) => true
case (Path.AtSubtype(_, Path.Root), _: TransformerOverride.ForSubtype) => true
case (Path.AtSourceSubtype(_, Path.Root), _: TransformerOverride.ForSubtype) => true
case (Path.Root, _: TransformerOverride.ForConstructor) => true
case _ => false
}

def allowFromToImplicitSummoning: TransformerConfiguration =
Expand Down Expand Up @@ -241,11 +256,15 @@ private[compiletime] trait Configurations { this: Derivation =>
name -> runtimeFieldOverride
}
)
def filterCurrentOverridesForSubtype(typeFilter: ?? => Boolean): Map[??, TransformerOverride.ForSubtype] =
def filterCurrentOverridesForSubtype(
sourceTypeFilter: ?? => Boolean,
@scala.annotation.unused targetTypeFilter: ?? => Boolean
): Map[Option[??], TransformerOverride.ForSubtype] =
ListMap.from(
runtimeOverridesForCurrent.collect {
case (Path.AtSubtype(tpe, _), runtimeCoproductOverride: TransformerOverride.ForSubtype) if typeFilter(tpe) =>
tpe -> runtimeCoproductOverride
case (Path.AtSourceSubtype(tpe, _), runtimeCoproductOverride: TransformerOverride.ForSubtype)
if sourceTypeFilter(tpe) =>
Some(tpe) -> runtimeCoproductOverride
}
)
def currentOverrideForConstructor: Option[TransformerOverride.ForConstructor] =
Expand Down Expand Up @@ -457,6 +476,9 @@ private[compiletime] trait Configurations { this: Derivation =>
case ChimneyType.Path.Matching(init, subtype) =>
import init.Underlying as PathType2, subtype.Underlying as Subtype
extractPath[PathType2].matching[Subtype]
case ChimneyType.Path.SourceMatching(init, sourceSubtype) =>
import init.Underlying as PathType2, sourceSubtype.Underlying as SourceSubtype
extractPath[PathType2].sourceMatching[SourceSubtype]
case ChimneyType.Path.EveryItem(init) =>
import init.Underlying as PathType2
extractPath[PathType2].everyItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,15 @@ private[compiletime] trait TransformSealedHierarchyToSealedHierarchyRuleModule {
private def mapOverriddenElements[From, To](implicit
ctx: TransformationContext[From, To]
): List[Existential[ExprPromise[*, TransformationExpr[To]]]] = ctx.config
.filterCurrentOverridesForSubtype { someFrom =>
import someFrom.Underlying as SomeFrom
Type[SomeFrom] <:< Type[From]
}
.filterCurrentOverridesForSubtype(
someFrom => {
import someFrom.Underlying as SomeFrom
Type[SomeFrom] <:< Type[From]
},
_ => false
)
.toList
.collect { case (someFrom, runtimeCoproductOverride) =>
.collect { case (Some(someFrom), runtimeCoproductOverride) =>
import someFrom.Underlying as SomeFrom
someFrom.mapK[ExprPromise[*, TransformationExpr[To]]] { _ => _ =>
ExprPromise
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
package io.scalaland.chimney.internal.runtime

/** Represents the path passed into `withField*` methods. */
sealed abstract class Path
object Path {

/** Represents _ (anonymous argument) path. */
final class Root extends Path

/** Represents $init.$fieldName path. */
final class Select[Init <: Path, FieldName <: String] extends Path

/** Represents $init.matching[$Subtype] path BUT ALSO is used for `matchingSome`, `matchingLeft` and `matchingRight`.
*
* Currently there is some special casing - `.matchingSome`, `.matchingLeft` and `.matchingRight` not only matches
* the subtype but also extracts the inner value AND running `_.option.matching[Some[A]].value` would NOT work.
*/
final class Matching[Init <: Path, Subtype] extends Path

/** Used only for withSealedSubtypeMatching to denote that type is matched on the source side!!! */
final class SourceMatching[Init <: Path, SourceSubtype] extends Path

/** Represents $init.everyItem path. */
final class EveryItem[Init <: Path] extends Path

/** Represents $init.everyMapKey path. */
final class EveryMapKey[Init <: Path] extends Path

/** Represents $init.everyMapValue path. */
final class EveryMapValue[Init <: Path] extends Path
}

0 comments on commit 41b5e0b

Please sign in to comment.