Skip to content

Commit

Permalink
Merge pull request #96 from OndrejSpanel/pr-modify-tuple
Browse files Browse the repository at this point in the history
Tuple modification fails with Scala 3
  • Loading branch information
adamw authored Aug 31, 2022
2 parents 50592c5 + 98da9f7 commit a546896
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ object QuicklensMacros {
def unsupportedShapeInfo(tree: Tree) =
s"Unsupported path element. Path must have shape: _.field1.field2.each.field3.(...), got: ${tree.show}"

def noSuchMember(term: Term, name: String) =
s"${term.tpe} has no member named $name"

def methodSupported(method: String) =
Seq("at", "each", "eachWhere", "eachRight", "eachLeft", "atOrElse", "index", "when").contains(method)

Expand Down Expand Up @@ -84,10 +87,10 @@ object QuicklensMacros {
else
children.map {
case (sym, trees) if sym equiv symbol =>
sym -> { trees.init ++ { trees.last match
sym -> (trees.init ++ { trees.last match
case PathTree.Empty => Seq(PathTree.Empty, tail.toPathTree)
case node => Seq(node <> tail)
}}
})
case c => c
}
}
Expand All @@ -100,7 +103,6 @@ object QuicklensMacros {
def toPathTree: PathTree = symbols match
case Nil => PathTree.Empty
case (symbol :: tail) => PathTree.Node(Seq(symbol -> Seq(tail.toPathTree)))


enum PathSymbol:
case Field(name: String)
Expand Down Expand Up @@ -139,13 +141,17 @@ object QuicklensMacros {
}

def termMethodByNameUnsafe(term: Term, name: String): Symbol = {
term.tpe.typeSymbol.memberMethod(name).head
term.tpe.typeSymbol
.memberMethod(name)
.headOption
.getOrElse(report.errorAndAbort(noSuchMember(term, name)))
}

def termAccessorMethodByNameUnsafe(term: Term, name: String): (Symbol, Int) = {
val caseFields = term.tpe.typeSymbol.caseFields
val idx = caseFields.map(_.name).indexOf(name)
(caseFields.find(_.name == name).get, idx + 1)
val caseParamNames = term.tpe.typeSymbol.primaryConstructor.paramSymss.flatten.filter(_.isTerm).map(_.name)
val idx = caseParamNames.indexOf(name)
term.tpe.typeSymbol.caseFields.find(_.name == name).getOrElse(report.errorAndAbort(noSuchMember(term, name)))
-> (idx + 1)
}

def caseClassCopy(
Expand All @@ -166,7 +172,7 @@ object QuicklensMacros {
idx -> namedArg
}.toMap

val fieldsIdxs = 1.to(obj.tpe.typeSymbol.caseFields.length)
val fieldsIdxs = 1.to(obj.tpe.typeSymbol.primaryConstructor.paramSymss.flatten.filter(_.isTerm).length)
val args = fieldsIdxs.map { i =>
argsMap.getOrElse(
i,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.softwaremill.quicklens

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class TupleModifyTest extends AnyFlatSpec with Matchers {
it should "modify case classes using setTo" in {
case class Pair(a: Int, b: Int)
val p = Pair(0, 1)
val modified = p.modify(_.b).setTo(2)
modified shouldBe Pair(0, 2)
}
it should "modify tuples using setTo" in {
val tuple = (0, 1)
val modified = tuple.modify(_._2).setTo(2)
modified shouldBe ((0, 2))
}
it should "modify tuples using using" in {
val tuple4 = (0, 1, 2, 3)
val modified = tuple4.modify(_._3).using(_ + 1)
modified shouldBe ((0, 1, 3, 3))
}

it should "modify tuples using multiple modify" in {
val tuple4 = (0, 1, 2, 3)
val modified = tuple4.modify(_._3).using(_ + 1).modify(_._4).using(_ + 1)
modified shouldBe ((0, 1, 3, 4))
}
}

0 comments on commit a546896

Please sign in to comment.