From de9bfc3bd1993b8b8e716033c24509badbd2766b Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Wed, 10 May 2023 18:11:02 +0200 Subject: [PATCH] Fix when for parameterized types on Scala 2 It already works on Scala 3. Although in the general case it's eliminated by erasure, we would get a warning because it's implemented as a pattern match. --- .../softwaremill/quicklens/QuicklensMacros.scala | 4 ++-- .../softwaremill/quicklens/ModifyWhenTest.scala | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/quicklens/src/main/scala-2/com/softwaremill/quicklens/QuicklensMacros.scala b/quicklens/src/main/scala-2/com/softwaremill/quicklens/QuicklensMacros.scala index 248256f..983b783 100644 --- a/quicklens/src/main/scala-2/com/softwaremill/quicklens/QuicklensMacros.scala +++ b/quicklens/src/main/scala-2/com/softwaremill/quicklens/QuicklensMacros.scala @@ -119,7 +119,7 @@ object QuicklensMacros { sealed trait PathElement case class TermPathElement(term: c.TermName, access: PathAccess, xargs: c.Tree*) extends PathElement - case class SubtypePathElement(subtype: c.Symbol) extends PathElement + case class SubtypePathElement(subtype: c.Type) extends PathElement case class FunctorPathElement(functor: c.Tree, method: c.TermName, xargs: c.Tree*) extends PathElement /** Determine if the `.copy` method should be applied directly or through a match across all subclasses (for sealed @@ -168,7 +168,7 @@ object QuicklensMacros { val access = determinePathAccess(parent.tpe.typeSymbol) collectPathElements(parent, TermPathElement(child, access) :: acc) case q"$tpname[..$_]($parent).when[$tp]" if typeSupported(tpname) => - collectPathElements(parent, SubtypePathElement(tp.tpe.typeSymbol) :: acc) + collectPathElements(parent, SubtypePathElement(tp.tpe) :: acc) case q"$parent.$method(..$xargs)" if methodSupported(method) => collectPathElements(parent, TermPathElement(method, DirectPathAccess, xargs: _*) :: acc) case q"$tpname[..$_]($t)($f)" if typeSupported(tpname) => diff --git a/quicklens/src/test/scala/com/softwaremill/quicklens/ModifyWhenTest.scala b/quicklens/src/test/scala/com/softwaremill/quicklens/ModifyWhenTest.scala index caa0ffe..92110ef 100644 --- a/quicklens/src/test/scala/com/softwaremill/quicklens/ModifyWhenTest.scala +++ b/quicklens/src/test/scala/com/softwaremill/quicklens/ModifyWhenTest.scala @@ -17,6 +17,14 @@ object ModifyWhenTestData { val zoo = Zoo(List(dog, cat)) val olderZoo = Zoo(List(olderDog, olderCat)) + + trait MyOption[+A] + case class MySome[+A](value: A) extends MyOption[A] + case object MyNone extends MyOption[Nothing] + + val someDog: MyOption[Dog] = MySome(Dog(4)) + val someOlderDog: MyOption[Dog] = MySome(Dog(5)) + val noDog: MyOption[Dog] = MyNone } class ModifyWhenTest extends AnyFlatSpec with Matchers { @@ -42,4 +50,12 @@ class ModifyWhenTest extends AnyFlatSpec with Matchers { ) .using(_ + 1) shouldEqual olderZoo } + + it should "modify a field in a subtypes (parameterized)" in { + someDog.modify(_.when[MySome[Dog]].value.age).using(_ + 1) shouldEqual someOlderDog + } + + it should "ignore subtypes other than the selected one (parameterized)" in { + noDog.modify(_.when[MySome[Dog]].value.age).using(_ + 1) shouldEqual MyNone + } }