Skip to content

Commit 8a9770b

Browse files
Merge pull request #4968 from dotty-staging/load-tree-for-symbol
TASTy reflect use complete definition trees
2 parents 2b73f9d + 0289c31 commit 8a9770b

File tree

23 files changed

+137
-50
lines changed

23 files changed

+137
-50
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/FromSymbol.scala

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import dotty.tools.dotc.core.Types._
1010
object FromSymbol {
1111

1212
def definitionFromSym(sym: Symbol)(implicit ctx: Context): tpd.Tree = {
13+
assert(sym.exists)
1314
if (sym.is(Package)) packageDefFromSym(sym)
1415
else if (sym.isClass) classDef(sym.asClass)
1516
else if (sym.isType) typeDefFromSym(sym.asType)
@@ -19,21 +20,32 @@ object FromSymbol {
1920

2021
def packageDefFromSym(sym: Symbol)(implicit ctx: Context): PackageDefinition = PackageDefinitionImpl(sym)
2122

22-
def classDef(cls: ClassSymbol)(implicit ctx: Context): tpd.TypeDef = {
23-
val constrSym = cls.unforcedDecls.find(_.isPrimaryConstructor).orElse(
24-
// Dummy constructor for classes such as `<refinement>`
25-
ctx.newSymbol(cls, nme.CONSTRUCTOR, EmptyFlags, NoType)
26-
)
27-
val constr = tpd.DefDef(constrSym.asTerm)
28-
val parents = cls.classParents.map(tpd.TypeTree(_))
29-
val body = cls.unforcedDecls.filter(!_.isPrimaryConstructor).map(s => definitionFromSym(s))
30-
tpd.ClassDefWithParents(cls, constr, parents, body)
23+
def classDef(cls: ClassSymbol)(implicit ctx: Context): tpd.TypeDef = cls.defTree match {
24+
case tree: tpd.TypeDef => tree
25+
case tpd.EmptyTree =>
26+
val constrSym = cls.unforcedDecls.find(_.isPrimaryConstructor).orElse(
27+
// Dummy constructor for classes such as `<refinement>`
28+
ctx.newSymbol(cls, nme.CONSTRUCTOR, EmptyFlags, NoType)
29+
)
30+
val constr = tpd.DefDef(constrSym.asTerm)
31+
val parents = cls.classParents.map(tpd.TypeTree(_))
32+
val body = cls.unforcedDecls.filter(!_.isPrimaryConstructor).map(s => definitionFromSym(s))
33+
tpd.ClassDefWithParents(cls, constr, parents, body)
3134
}
3235

33-
def typeDefFromSym(sym: TypeSymbol)(implicit ctx: Context): tpd.TypeDef = tpd.TypeDef(sym)
36+
def typeDefFromSym(sym: TypeSymbol)(implicit ctx: Context): tpd.TypeDef = sym.defTree match {
37+
case tree: tpd.TypeDef => tree
38+
case tpd.EmptyTree => tpd.TypeDef(sym)
39+
}
3440

35-
def defDefFromSym(sym: TermSymbol)(implicit ctx: Context): tpd.DefDef = tpd.DefDef(sym)
41+
def defDefFromSym(sym: TermSymbol)(implicit ctx: Context): tpd.DefDef = sym.defTree match {
42+
case tree: tpd.DefDef => tree
43+
case tpd.EmptyTree => tpd.DefDef(sym)
44+
}
3645

37-
def valDefFromSym(sym: TermSymbol)(implicit ctx: Context): tpd.ValDef = tpd.ValDef(sym)
46+
def valDefFromSym(sym: TermSymbol)(implicit ctx: Context): tpd.ValDef = sym.defTree match {
47+
case tree: tpd.ValDef => tree
48+
case tpd.EmptyTree => tpd.ValDef(sym)
49+
}
3850

3951
}

compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with TastyCoreImpl with He
316316
}
317317

318318
object Inlined extends InlinedExtractor {
319-
def unapply(x: Term)(implicit ctx: Context): Option[(Option[Term], List[Statement], Term)] = x match {
319+
def unapply(x: Term)(implicit ctx: Context): Option[(Option[Parent], List[Statement], Term)] = x match {
320320
case x: tpd.Inlined =>
321321
Some((optional(x.call), x.bindings, x.expansion))
322322
case _ => None

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ class CompilationTests extends ParallelTesting {
169169

170170
@Test def runAll: Unit = {
171171
implicit val testGroup: TestGroup = TestGroup("runAll")
172+
compileFilesInDir("tests/run-custom-args/Yretain-trees", defaultOptions and "-Yretain-trees") +
172173
compileFilesInDir("tests/run", defaultOptions)
173174
}.checkRuns()
174175

library/src/scala/tasty/reflect/TreeOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ trait TreeOps extends TastyCore {
286286

287287
val Inlined: InlinedExtractor
288288
abstract class InlinedExtractor {
289-
def unapply(tree: Tree)(implicit ctx: Context): Option[(Option[Term], List[Definition], Term)]
289+
def unapply(tree: Tree)(implicit ctx: Context): Option[(Option[Parent], List[Definition], Term)]
290290
}
291291

292292
val SelectOuter: SelectOuterExtractor

library/src/scala/tasty/util/ShowExtractors.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
6969
case Term.Repeated(elems) =>
7070
this += "Term.Repeated(" ++= elems += ")"
7171
case Term.Inlined(call, bindings, expansion) =>
72-
this += "Term.Inlined(" += call += ", " ++= bindings += ", " += expansion += ")"
72+
this += "Term.Inlined("
73+
visitOption(call, visitParent)
74+
this += ", " ++= bindings += ", " += expansion += ")"
7375
case ValDef(name, tpt, rhs) =>
7476
this += "ValDef(\"" += name += "\", " += tpt += ", " += rhs += ")"
7577
case DefDef(name, typeParams, paramss, returnTpt, rhs) =>
@@ -78,10 +80,7 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
7880
this += "TypeDef(\"" += name += "\", " += rhs += ")"
7981
case ClassDef(name, constr, parents, self, body) =>
8082
this += "ClassDef(\"" += name += "\", " += constr += ", "
81-
visitList[Parent](parents, {
82-
case IsTerm(parent) => this += parent
83-
case IsTypeTree(parent) => this += parent
84-
})
83+
visitList[Parent](parents, visitParent)
8584
this += ", " += self += ", " ++= body += ")"
8685
case PackageDef(name, owner) =>
8786
this += "PackageDef(\"" += name += "\", " += owner += ")"
@@ -142,6 +141,11 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
142141
this += "Pattern.TypeTest(" += tpt += ")"
143142
}
144143

144+
def visitParent(x: Parent): Buffer = x match {
145+
case IsTerm(parent) => this += parent
146+
case IsTypeTree(parent) => this += parent
147+
}
148+
145149
def visitConstant(x: Constant): Buffer = x match {
146150
case Constant.Unit() => this += "Constant.Unit()"
147151
case Constant.Null() => this += "Constant.Null()"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DefDef("foo", Nil, Nil, TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(2))))))
2+
ValDef("bar", TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(3))))))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DefDef("foo", Nil, Nil, TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(2))))))
2+
ValDef("bar", TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(3))))))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
foo
2+
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.TypeIdent("Array"), List(TypeTree.TypeIdent("String"))), None))), TypeTree.TypeIdent("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(TypeTree.TypeIdent("Macros$")), Nil, Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Synthetic())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Synthetic())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.TypeIdent("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~", Some(Signature(Nil, java.lang.Object)))))))
3+
4+
bar
5+
DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic()))))
6+
7+
bar2
8+
DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic()))))
9+
10+
foo2
11+
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.TypeIdent("Array"), List(TypeTree.TypeIdent("String"))), None))), TypeTree.TypeIdent("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(TypeTree.TypeIdent("Macros$")), Nil, Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Synthetic())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Synthetic())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.TypeIdent("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~", Some(Signature(Nil, java.lang.Object)))))))
12+
13+
baz
14+
ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic()))))
15+
16+
baz2
17+
ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic()))))
18+
19+
<init>
20+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.TypeIdent("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))
21+
22+
b
23+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.TypeIdent("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))
24+
25+
b2
26+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.TypeIdent("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))
27+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DefDef("foo", Nil, Nil, TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(2))))))
2+
ValDef("bar", TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(3))))))
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import scala.quoted._
2+
3+
import scala.tasty._
4+
5+
object Foo {
6+
7+
inline def inspectBody(i: => Int): String =
8+
~inspectBodyImpl('(i))
9+
10+
def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = {
11+
import tasty._
12+
13+
def definitionString(tree: Tree): Expr[String] = tree.symbol.tree match {
14+
case Some(definition) => definition.show.toExpr
15+
case None => '("NO DEFINTION")
16+
}
17+
18+
x.toTasty match {
19+
case Term.Inlined(None, Nil, arg) => definitionString(arg)
20+
case arg => definitionString(arg) // TODO should all by name parameters be in an inline node
21+
}
22+
}
23+
24+
def foo: Int = 1 + 2
25+
val bar: Int = 2 + 3
26+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
println(Foo.inspectBody(Foo.foo))
5+
println(Foo.inspectBody(Foo.bar))
6+
}
7+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DefDef("foo", Nil, Nil, TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(2))))))
2+
ValDef("bar", TypeTree.TypeIdent("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+", Some(Signature(List(scala.Int), scala.Int))), List(Term.Literal(Constant.Int(3))))))
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import scala.quoted._
2+
3+
import scala.tasty._
4+
5+
object Foo {
6+
7+
inline def inspectBody(i: => Int): String =
8+
~inspectBodyImpl('(i))
9+
10+
def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = {
11+
import tasty._
12+
13+
def definitionString(tree: Tree): Expr[String] = tree.symbol.tree match {
14+
case Some(definition) => definition.show.toExpr
15+
case None => '("NO DEFINTION")
16+
}
17+
18+
x.toTasty match {
19+
case Term.Inlined(None, Nil, arg) => definitionString(arg)
20+
case arg => definitionString(arg) // TODO should all by name parameters be in an inline node
21+
}
22+
}
23+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
println(Foo.inspectBody(foo))
5+
println(Foo.inspectBody(bar))
6+
}
7+
8+
def foo: Int = 1 + 2
9+
val bar: Int = 2 + 3
10+
}

tests/run/tasty-definitions-2.check

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

tests/run/tasty-definitions-3.check

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

tests/run/tasty-extractors-owners.check

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

0 commit comments

Comments
 (0)