Skip to content

Commit 83285a2

Browse files
committed
Refactor TreeAcumulator to simplify use
Remove the need to handle path dependent tasty.Reflection
1 parent 4299f03 commit 83285a2

File tree

12 files changed

+148
-147
lines changed

12 files changed

+148
-147
lines changed

library/src/scala/tasty/Reflection.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ abstract class Reflection
1818
with StandardDefinitions
1919
with SymbolOps
2020
with TreeOps
21+
with TreeUtils
2122
with TypeOrBoundsTreeOps
2223
with TypeOrBoundsOps
2324

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package scala.tasty
2+
package reflect
3+
4+
/** Tasty reflect case definition */
5+
trait TreeUtils
6+
extends ReflectionCore
7+
with CaseDefOps
8+
with PatternOps
9+
with SymbolOps
10+
with TreeOps
11+
with TypeOrBoundsTreeOps {
12+
13+
abstract class TreeAccumulator[X] {
14+
15+
// Ties the knot of the traversal: call `foldOver(x, tree))` to dive in the `tree` node.
16+
def foldTree(x: X, tree: Tree)(implicit ctx: Context): X
17+
def foldTypeTree(x: X, tree: TypeOrBoundsTree)(implicit ctx: Context): X
18+
def foldCaseDef(x: X, tree: CaseDef)(implicit ctx: Context): X
19+
def foldPattern(x: X, tree: Pattern)(implicit ctx: Context): X
20+
21+
def foldTrees(x: X, trees: Iterable[Tree])(implicit ctx: Context): X = (x /: trees)(foldTree)
22+
def foldTypeTrees(x: X, trees: Iterable[TypeOrBoundsTree])(implicit ctx: Context): X = (x /: trees)(foldTypeTree)
23+
def foldCaseDefs(x: X, trees: Iterable[CaseDef])(implicit ctx: Context): X = (x /: trees)(foldCaseDef)
24+
def foldPatterns(x: X, trees: Iterable[Pattern])(implicit ctx: Context): X = (x /: trees)(foldPattern)
25+
private def foldParents(x: X, trees: Iterable[TermOrTypeTree])(implicit ctx: Context): X = (x /: trees)(foldOverTermOrTypeTree)
26+
27+
def foldOverTree(x: X, tree: Tree)(implicit ctx: Context): X = {
28+
def localCtx(definition: Definition): Context = definition.symbol.localContext
29+
tree match {
30+
case Term.Ident(_) =>
31+
x
32+
case Term.Select(qualifier, _, _) =>
33+
foldTree(x, qualifier)
34+
case Term.This(qual) =>
35+
x
36+
case Term.Super(qual, _) =>
37+
foldTree(x, qual)
38+
case Term.Apply(fun, args) =>
39+
foldTrees(foldTree(x, fun), args)
40+
case Term.TypeApply(fun, args) =>
41+
foldTypeTrees(foldTree(x, fun), args)
42+
case Term.Literal(const) =>
43+
x
44+
case Term.New(tpt) =>
45+
foldTypeTree(x, tpt)
46+
case Term.Typed(expr, tpt) =>
47+
foldTypeTree(foldTree(x, expr), tpt)
48+
case Term.NamedArg(_, arg) =>
49+
foldTree(x, arg)
50+
case Term.Assign(lhs, rhs) =>
51+
foldTree(foldTree(x, lhs), rhs)
52+
case Term.Block(stats, expr) =>
53+
foldTree(foldTrees(x, stats), expr)
54+
case Term.If(cond, thenp, elsep) =>
55+
foldTree(foldTree(foldTree(x, cond), thenp), elsep)
56+
case Term.Lambda(meth, tpt) =>
57+
val a = foldTree(x, meth)
58+
tpt.fold(a)(b => foldTypeTree(a, b))
59+
case Term.Match(selector, cases) =>
60+
foldCaseDefs(foldTree(x, selector), cases)
61+
case Term.Return(expr) =>
62+
foldTree(x, expr)
63+
case Term.Try(block, handler, finalizer) =>
64+
foldTrees(foldCaseDefs(foldTree(x, block), handler), finalizer)
65+
case Term.Repeated(elems) =>
66+
foldTrees(x, elems)
67+
case Term.Inlined(call, bindings, expansion) =>
68+
foldTree(foldTrees(x, bindings), expansion)
69+
case IsDefinition(vdef @ ValDef(_, tpt, rhs)) =>
70+
implicit val ctx = localCtx(vdef)
71+
foldTrees(foldTypeTree(x, tpt), rhs)
72+
case IsDefinition(ddef @ DefDef(_, tparams, vparamss, tpt, rhs)) =>
73+
implicit val ctx = localCtx(ddef)
74+
foldTrees(foldTypeTree((foldTrees(x, tparams) /: vparamss)(foldTrees), tpt), rhs)
75+
case IsDefinition(tdef @ TypeDef(_, rhs)) =>
76+
implicit val ctx = localCtx(tdef)
77+
foldTypeTree(x, rhs)
78+
case IsDefinition(cdef @ ClassDef(_, constr, parents, self, body)) =>
79+
implicit val ctx = localCtx(cdef)
80+
foldTrees(foldTrees(foldParents(foldTree(x, constr), parents), self), body)
81+
case Import(expr, selectors) =>
82+
foldTree(x, expr)
83+
case IsPackageClause(clause @ PackageClause(pid, stats)) =>
84+
foldTrees(foldTree(x, pid), stats)(clause.symbol.localContext)
85+
}
86+
}
87+
88+
def foldOverTypeTree(x: X, tree: TypeOrBoundsTree)(implicit ctx: Context): X = tree match {
89+
case TypeTree.Synthetic() => x
90+
case TypeTree.Ident(_) => x
91+
case TypeTree.Select(qualifier, _) => foldTree(x, qualifier)
92+
case TypeTree.Project(qualifier, _) => foldTypeTree(x, qualifier)
93+
case TypeTree.Singleton(ref) => foldTree(x, ref)
94+
case TypeTree.And(left, right) => foldTypeTree(foldTypeTree(x, left), right)
95+
case TypeTree.Or(left, right) => foldTypeTree(foldTypeTree(x, left), right)
96+
case TypeTree.Refined(tpt, refinements) => foldTrees(foldTypeTree(x, tpt), refinements)
97+
case TypeTree.Applied(tpt, args) => foldTypeTrees(foldTypeTree(x, tpt), args)
98+
case TypeTree.ByName(result) => foldTypeTree(x, result)
99+
case TypeTree.Annotated(arg, annot) => foldTree(foldTypeTree(x, arg), annot)
100+
case TypeBoundsTree(lo, hi) => foldTypeTree(foldTypeTree(x, lo), hi)
101+
}
102+
103+
def foldOverCaseDef(x: X, tree: CaseDef)(implicit ctx: Context): X = tree match {
104+
case CaseDef(pat, guard, body) => foldTree(foldTrees(foldPattern(x, pat), guard), body)
105+
}
106+
107+
def foldOverPattern(x: X, tree: Pattern)(implicit ctx: Context): X = tree match {
108+
case Pattern.Value(v) => foldTree(x, v)
109+
case Pattern.Bind(_, body) => foldPattern(x, body)
110+
case Pattern.Unapply(fun, implicits, patterns) => foldPatterns(foldTrees(foldTree(x, fun), implicits), patterns)
111+
case Pattern.Alternative(patterns) => foldPatterns(x, patterns)
112+
case Pattern.TypeTest(tpt) => foldTypeTree(x, tpt)
113+
}
114+
115+
private def foldOverTermOrTypeTree(x: X, tree: TermOrTypeTree)(implicit ctx: Context): X = tree match {
116+
case IsTerm(termOrTypeTree) => foldOverTree(x, termOrTypeTree)
117+
case IsTypeTree(termOrTypeTree) => foldOverTypeTree(x, termOrTypeTree)
118+
}
119+
120+
}
121+
122+
abstract class TreeTraverser extends TreeAccumulator[Unit] {
123+
124+
def traverseTree(tree: Tree)(implicit ctx: Context): Unit = traverseTreeChildren(tree)
125+
def traverseTypeTree(tree: TypeOrBoundsTree)(implicit ctx: Context): Unit = traverseTypeTreeChildren(tree)
126+
def traverseCaseDef(tree: CaseDef)(implicit ctx: Context): Unit = traverseCaseDefChildren(tree)
127+
def traversePattern(tree: Pattern)(implicit ctx: Context): Unit = traversePatternChildren(tree)
128+
129+
def foldTree(x: Unit, tree: Tree)(implicit ctx: Context): Unit = traverseTree(tree)
130+
def foldTypeTree(x: Unit, tree: TypeOrBoundsTree)(implicit ctx: Context) = traverseTypeTree(tree)
131+
def foldCaseDef(x: Unit, tree: CaseDef)(implicit ctx: Context) = traverseCaseDef(tree)
132+
def foldPattern(x: Unit, tree: Pattern)(implicit ctx: Context) = traversePattern(tree)
133+
134+
protected def traverseTreeChildren(tree: Tree)(implicit ctx: Context): Unit = foldOverTree((), tree)
135+
protected def traverseTypeTreeChildren(tree: TypeOrBoundsTree)(implicit ctx: Context): Unit = foldOverTypeTree((), tree)
136+
protected def traverseCaseDefChildren(tree: CaseDef)(implicit ctx: Context): Unit = foldOverCaseDef((), tree)
137+
protected def traversePatternChildren(tree: Pattern)(implicit ctx: Context): Unit = foldOverPattern((), tree)
138+
139+
}
140+
141+
}

library/src/scala/tasty/util/TreeAccumulator.scala

Lines changed: 0 additions & 113 deletions
This file was deleted.

library/src/scala/tasty/util/TreeTraverser.scala

Lines changed: 0 additions & 23 deletions
This file was deleted.

semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SemanticdbConsumer extends TastyConsumer {
88

99
final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
1010
import reflect._
11-
object Traverser extends TreeTraverser[reflect.type](reflect) {
11+
object Traverser extends TreeTraverser {
1212

1313
override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = tree match {
1414
case IsDefinition(tree) =>

tests/run-custom-args/Yretain-trees/tasty-extractors-owners/quoted_1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import scala.quoted._
22

33
import scala.tasty._
4-
import scala.tasty.util.TreeTraverser
54

65
object Macros {
76

@@ -22,7 +21,7 @@ object Macros {
2221
}
2322
}
2423

25-
val output = new TreeTraverser(reflect) {
24+
val output = new TreeTraverser {
2625
override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = {
2726
tree match {
2827
case IsDefinition(tree @ DefDef(name, _, _, _, _)) =>

tests/run-separate-compilation/tasty-custom-show/quoted_1.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import scala.quoted._
22

33
import scala.tasty.Reflection
4-
import scala.tasty.util.{TreeTraverser, Printer}
4+
import scala.tasty.util.Printer
55

66
object Macros {
77

@@ -13,7 +13,7 @@ object Macros {
1313

1414
val buff = new StringBuilder
1515

16-
val output = new TreeTraverser(reflect) {
16+
val output = new TreeTraverser {
1717
override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = {
1818
// Use custom Show[_] here
1919
val printer = new DummyShow(reflect)

tests/run-separate-compilation/tasty-definitions-1/quoted_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import scala.quoted._
22

33
import scala.tasty._
4-
import scala.tasty.util.TreeTraverser
54

65
object Macros {
76

tests/run-separate-compilation/tasty-eval/quoted_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import scala.quoted._
22

33
import scala.tasty._
4-
import scala.tasty.util.TreeTraverser
54

65
object Macros {
76

tests/run-separate-compilation/tasty-extractors-3/quoted_1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import scala.quoted._
22

33
import scala.tasty.Reflection
4-
import scala.tasty.util.TreeTraverser
54

65
object Macros {
76

@@ -12,7 +11,7 @@ object Macros {
1211
import reflect._
1312

1413
val buff = new StringBuilder
15-
val traverser = new TreeTraverser(reflect) {
14+
val traverser = new TreeTraverser {
1615
override def traverseTypeTree(tree: TypeOrBoundsTree)(implicit ctx: Context): Unit = {
1716
buff.append(tree.tpe.show)
1817
buff.append("\n\n")

tests/run-separate-compilation/tasty-extractors-types/quoted_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import scala.quoted._
22

33
import scala.tasty._
4-
import scala.tasty.util.TreeTraverser
54

65
object Macros {
76

tests/run-with-compiler/tasty-consumer/Test.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class DBConsumer extends TastyConsumer {
1212

1313
final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
1414
import reflect._
15-
object Traverser extends TreeTraverser[reflect.type](reflect) {
15+
object Traverser extends TreeTraverser {
1616

1717
override def traverseTree(tree: Tree)(implicit ctx: Context): Unit = tree match {
1818
case IsDefinition(tree) =>

0 commit comments

Comments
 (0)