Skip to content

Commit

Permalink
When accessing current values of fields, try the field symbol first
Browse files Browse the repository at this point in the history
before the method symbol
  • Loading branch information
KacperFKorban committed Sep 17, 2024
1 parent b0ef525 commit 25d8c0e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,13 @@ object QuicklensMacros {
def symbolAccessorByNameOrError(sym: Symbol, name: String): Symbol = {
val mem = sym.fieldMember(name)
if mem != Symbol.noSymbol then mem
else report.errorAndAbort(noSuchMember(sym.name, name))
else symbolMethodByNameOrError(sym, name)
}

def symbolMethodByNameOrError(sym: Symbol, name: String): Symbol = {
sym.methodMember(name) match
case List(m) => m
case Nil => symbolAccessorByNameOrError(sym, name)
case Nil => report.errorAndAbort(noSuchMember(sym.name, name))
case _ => report.errorAndAbort(multipleMatchingMethods(sym.name, name))
}

Expand Down Expand Up @@ -202,9 +202,10 @@ object QuicklensMacros {
obj: Term,
fields: Seq[(PathSymbol.Field, Seq[PathTree])]
): Term = {
val objSymbol = obj.tpe.widenAll.matchingTypeSymbol
val objTpe = obj.tpe.widenAll
val objSymbol = objTpe.matchingTypeSymbol
if isSum(objSymbol) then {
obj.tpe.widenAll match {
objTpe match {
case AndType(_, _) =>
report.errorAndAbort(
s"Implementation limitation: Cannot modify sealed hierarchies mixed with & types. Try providing a more specific type."
Expand Down Expand Up @@ -235,15 +236,15 @@ object QuicklensMacros {
} else if isProduct(objSymbol) || isProductLike(objSymbol) then {
val copy = symbolMethodByNameOrError(objSymbol, "copy")
val argsMap: Map[String, Term] = fields.map { (field, trees) =>
val fieldMethod = symbolMethodByNameOrError(objSymbol, field.name)
val fieldMethod = symbolAccessorByNameOrError(objSymbol, field.name)
val resTerm: Term = trees.foldLeft[Term](Select(obj, fieldMethod)) { (term, tree) =>
mapToCopy(owner, mod, term, tree)
}
val namedArg = NamedArg(field.name, resTerm)
field.name -> namedArg
}.toMap

val typeParams = obj.tpe.widenAll match {
val typeParams = objTpe match {
case AppliedType(_, typeParams) => Some(typeParams)
case _ => None
}
Expand Down Expand Up @@ -272,7 +273,7 @@ object QuicklensMacros {
case _ => Apply(Select(obj, copy), args)
}
} else
report.errorAndAbort(s"Unsupported source object: must be a case class or sealed trait, but got: $objSymbol")
report.errorAndAbort(s"Unsupported source object: must be a case class or sealed trait, but got: $objSymbol of type ${objTpe.show} (${obj.show})")
}

def applyFunctionDelegate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,18 @@ class ExplicitCopyTest extends AnyFlatSpec with Matchers {
modified.show shouldEqual expected.show
}

it should "modify a class that has a method with the same name as a field" in {
final case class PathItem()
final case class Paths(
pathItems: Map[String, PathItem] = Map.empty
)
final case class Docs(
paths: Paths = Paths()
) {
def paths(paths: Paths): Docs = copy(paths = paths)
}
val docs = Docs()
docs.modify(_.paths.pathItems).using(m => m + ("a" -> PathItem()))
}

}

0 comments on commit 25d8c0e

Please sign in to comment.