Skip to content

Commit

Permalink
Merge pull request #181 from softwaremill/fix-i159
Browse files Browse the repository at this point in the history
Extract focuses from nested `Inlined` trees when determining modification path in Scala 3 macro
  • Loading branch information
adamw authored Jul 17, 2023
2 parents fcf1f7c + 9169d90 commit 9bd5ed2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,19 +326,24 @@ object QuicklensMacros {
accumulateToCopy(owner, mod, objTerm, children)
}

val focusesTrees: Seq[Tree] = focuses.map(_.asTerm)
val paths: Seq[Seq[PathSymbol]] = focusesTrees.zip(focuses).map { (tree, focus) =>
tree match
/** Single inlined path */
case Inlined(_, _, Block(List(DefDef(_, _, _, Some(p))), _)) =>
toPath(p, focus)
/** One of paths from modifyAll */
case Block(List(DefDef(_, _, _, Some(p))), _) =>
toPath(p, focus)
case _ =>
report.errorAndAbort(unsupportedShapeInfo(tree))
def extractFocus(tree: Tree): Tree = tree match {
/** Single inlined path */
case Inlined(_, _, p) =>
extractFocus(p)
/** One of paths from modifyAll */
case Block(List(DefDef(_, _, _, Some(p))), _) =>
p
case _ =>
println(tree)
report.errorAndAbort(unsupportedShapeInfo(tree))
}

val focusesTrees: Seq[Tree] = focuses.map(_.asTerm)
val paths: Seq[Seq[PathSymbol]] =
focusesTrees.zip(focuses).map { (tree, focus) =>
toPath(extractFocus(tree), focus)
}

val pathTree: PathTree =
paths.foldLeft(PathTree.empty) { (tree, path) => tree <> path }

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

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

class CustomModifyProxyTest extends AnyFlatSpec with Matchers {

it should "correctly modify a class using a custom modify proxy method" in {
case class State(foo: Int)

inline def set[A](state: State, inline path: State => A, value: A): State = {
modify(state)(path).setTo(value)
}

val state = State(100)
val res = set(state, _.foo, 200)
val expected = State(200)
res.shouldBe(expected)
}

}

0 comments on commit 9bd5ed2

Please sign in to comment.