Skip to content

Commit

Permalink
Merge pull request #158 from KacperFKorban/fix-i157
Browse files Browse the repository at this point in the history
Move the second type argument to the modify/modifyAll method in Scala 3
  • Loading branch information
KacperFKorban authored May 3, 2023
2 parents 22295fe + f73d8b6 commit c744356
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ object QuicklensMacros {
case Empty
case Node(children: Seq[(PathSymbol, Seq[PathTree])])

def <>(symbols: Seq[PathSymbol]): PathTree = (this, symbols) match
def <>(symbols: Seq[PathSymbol]): PathTree = ((this, symbols): @unchecked) match
case (PathTree.Empty, _) =>
symbols.toPathTree
case (PathTree.Node(children), (symbol :: Nil)) =>
Expand Down Expand Up @@ -283,7 +283,9 @@ object QuicklensMacros {
)
val defdefStatements = DefDef(
defdefSymbol,
{ case List(List(x)) => Some(mapToCopy(defdefSymbol, mod, x.asExpr.asTerm, tree)) }
((_: @unchecked) match
case List(List(x)) => Some(mapToCopy(defdefSymbol, mod, x.asExpr.asTerm, tree))
)
)
val closure = Closure(Ref(defdefSymbol), None)
val block = Block(List(defdefStatements), closure)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ package object quicklens {

// #114: obj shouldn't be inline since we want to reference the parameter by-name, rather then embedding the whole
// expression whenever obj is used; this is especially important for chained .modify invocations
extension [S, A](obj: S)
extension [S](obj: S)
/** Create an object allowing modifying the given (deeply nested) field accessible in a `case class` hierarchy via
* `path` on the given `obj`.
*
* All modifications are side-effect free and create copies of the original objects.
*
* You can use `.each` to traverse options, lists, etc.
*/
inline def modify(inline path: S => A): PathModify[S, A] = ${ toPathModifyFromFocus('obj, 'path) }
inline def modify[A](inline path: S => A): PathModify[S, A] = ${ toPathModifyFromFocus('obj, 'path) }

/** Create an object allowing modifying the given (deeply nested) fields accessible in a `case class` hierarchy via
* `paths` on the given `obj`.
Expand All @@ -26,7 +26,7 @@ package object quicklens {
*
* You can use `.each` to traverse options, lists, etc.
*/
inline def modifyAll(inline path: S => A, inline paths: (S => A)*): PathModify[S, A] = ${
inline def modifyAll[A](inline path: S => A, inline paths: (S => A)*): PathModify[S, A] = ${
modifyAllImpl('obj, 'path, 'paths)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.softwaremill.quicklens.test

import com.softwaremill.quicklens.TestData.duplicate
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import com.softwaremill.quicklens._

object LiteralTypeTestData {
case class Test(f: "foo")
case class Test1[A](f: A)
}

class LiteralTypeTest extends AnyFlatSpec with Matchers {
import LiteralTypeTestData._

it should "modify a literal type field with an explicit parameter" in {
Test("foo").modify["foo"](_.f).setTo("foo") should be(Test("foo"))
}

it should "modify a literal type field as a type parameter with an explicit parameter" in {
Test1["foo"]("foo").modify["foo"](_.f).setTo("foo") should be(Test1("foo"))
}

it should "not compile for a wrong literal type" in {
assertDoesNotCompile("""
import com.softwaremill.quicklens.*
case class Test1[A](f: A)
Test1["foo"]("foo").modify["foo"](_.f).setTo("bar")
""")
}
}

0 comments on commit c744356

Please sign in to comment.