Skip to content

Commit 54342a6

Browse files
committed
Introduce SourceImportTree and SourceNamedTree
1 parent c55413b commit 54342a6

File tree

5 files changed

+79
-50
lines changed

5 files changed

+79
-50
lines changed

compiler/src/dotty/tools/dotc/interactive/Interactive.scala

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ object Interactive {
251251
* source code.
252252
*/
253253
def namedTrees(trees: List[SourceTree], include: Include.Set, sym: Symbol)
254-
(implicit ctx: Context): List[SourceTree] =
254+
(implicit ctx: Context): List[SourceNamedTree] =
255255
if (!sym.exists)
256256
Nil
257257
else
@@ -262,38 +262,40 @@ object Interactive {
262262
* @param includeReferences If true, include references and not just definitions
263263
*/
264264
def namedTrees(trees: List[SourceTree], includeReferences: Boolean, nameSubstring: String)
265-
(implicit ctx: Context): List[SourceTree] =
265+
(implicit ctx: Context): List[SourceNamedTree] =
266266
namedTrees(trees, includeReferences, _.show.toString.contains(nameSubstring))
267267

268268
/** Find named trees with a non-empty position satisfying `treePredicate` in `trees`.
269269
*
270270
* @param includeReferences If true, include references and not just definitions
271271
*/
272272
def namedTrees(trees: List[SourceTree], includeReferences: Boolean, treePredicate: NameTree => Boolean)
273-
(implicit ctx: Context): List[SourceTree] = safely {
274-
val buf = new mutable.ListBuffer[SourceTree]
275-
276-
trees foreach { case SourceTree(_, topTree, source) =>
277-
new untpd.TreeTraverser {
278-
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
279-
tree match {
280-
case utree: untpd.NameTree if tree.hasType =>
281-
val tree = utree.asInstanceOf[tpd.NameTree]
282-
if (tree.symbol.exists
283-
&& !tree.symbol.is(Synthetic)
284-
&& tree.pos.exists
285-
&& !tree.pos.isZeroExtent
286-
&& (includeReferences || isDefinition(tree))
287-
&& treePredicate(tree))
288-
buf += SourceTree(Nil, tree, source)
289-
traverseChildren(tree)
290-
case tree: untpd.Inlined =>
291-
traverse(tree.call)
292-
case _ =>
293-
traverseChildren(tree)
273+
(implicit ctx: Context): List[SourceNamedTree] = safely {
274+
val buf = new mutable.ListBuffer[SourceNamedTree]
275+
276+
trees foreach {
277+
case SourceNamedTree(topTree, source) =>
278+
new untpd.TreeTraverser {
279+
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
280+
tree match {
281+
case utree: untpd.NameTree if tree.hasType =>
282+
val tree = utree.asInstanceOf[tpd.NameTree]
283+
if (tree.symbol.exists
284+
&& !tree.symbol.is(Synthetic)
285+
&& tree.pos.exists
286+
&& !tree.pos.isZeroExtent
287+
&& (includeReferences || isDefinition(tree))
288+
&& treePredicate(tree))
289+
buf += SourceNamedTree(tree, source)
290+
traverseChildren(tree)
291+
case tree: untpd.Inlined =>
292+
traverse(tree.call)
293+
case _ =>
294+
traverseChildren(tree)
295+
}
294296
}
295-
}
296-
}.traverse(topTree)
297+
}.traverse(topTree)
298+
case _: SourceImportTree => ()
297299
}
298300

299301
buf.toList
@@ -304,9 +306,9 @@ object Interactive {
304306
* the tree closest enclosing `pos` and ends with an element of `trees`.
305307
*/
306308
def pathTo(trees: List[SourceTree], pos: SourcePosition)(implicit ctx: Context): List[Tree] = {
307-
val allTrees = trees.flatMap(t => t.tree :: t.topLevelImports)
308-
allTrees.find(t => t.pos.contains(pos.pos)) match {
309-
case Some(tree) => pathTo(tree, pos.pos)
309+
trees.find(t => t.pos.contains(pos)) match {
310+
case Some(tree) =>
311+
pathTo(tree.tree, pos.pos)
310312
case None => Nil
311313
}
312314
}

compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
6767
(fromSource ++ fromClassPath).distinct
6868
}
6969

70-
private def tree(className: TypeName, id: String)(implicit ctx: Context): Option[SourceTree] = {
70+
private def tree(className: TypeName, id: String)(implicit ctx: Context): List[SourceTree] = {
7171
val clsd = ctx.base.staticRef(className)
7272
clsd match {
7373
case clsd: ClassDenotation =>
7474
clsd.ensureCompleted()
7575
SourceTree.fromSymbol(clsd.symbol.asClass, id)
7676
case _ =>
77-
None
77+
Nil
7878
}
7979
}
8080

@@ -169,18 +169,19 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
169169
names.toList
170170
}
171171

172-
private def topLevelClassTrees(topTree: Tree, source: SourceFile): List[SourceTree] = {
172+
private def topLevelTrees(topTree: Tree, source: SourceFile): List[SourceTree] = {
173173
val trees = new mutable.ListBuffer[SourceTree]
174174

175-
def addTrees(topLevelImports: List[Import], tree: Tree): Unit = tree match {
175+
def addTrees(tree: Tree): Unit = tree match {
176176
case PackageDef(_, stats) =>
177-
val imports = stats.collect { case imp: Import => imp }
178-
stats.foreach(addTrees(imports, _))
177+
stats.foreach(addTrees)
178+
case imp: Import =>
179+
trees += SourceImportTree(imp, source)
179180
case tree: TypeDef =>
180-
trees += SourceTree(topLevelImports, tree, source)
181+
trees += SourceNamedTree(tree, source)
181182
case _ =>
182183
}
183-
addTrees(Nil, topTree)
184+
addTrees(topTree)
184185

185186
trees.toList
186187
}
@@ -244,7 +245,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
244245
val unit = ctx.run.units.head
245246
val t = unit.tpdTree
246247
cleanup(t)
247-
myOpenedTrees(uri) = topLevelClassTrees(t, source)
248+
myOpenedTrees(uri) = topLevelTrees(t, source)
248249
myCompilationUnits(uri) = unit
249250

250251
reporter.removeBufferedMessages

compiler/src/dotty/tools/dotc/interactive/SourceTree.scala

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,24 @@ import core._, core.Decorators.{sourcePos => _, _}
99
import Contexts._, NameOps._, Symbols._
1010
import util._, util.Positions._
1111

12-
/** A typechecked named `tree` coming from `source` */
13-
case class SourceTree(topLevelImports: List[tpd.Import], tree: tpd.NameTree, source: SourceFile) {
12+
/** A `tree` coming from `source` */
13+
sealed trait SourceTree {
14+
15+
/** The underlying tree. */
16+
def tree: tpd.Tree
17+
18+
/** The source from which `tree` comes. */
19+
def source: SourceFile
20+
1421
/** The position of `tree` */
15-
def pos(implicit ctx: Context): SourcePosition = source.atPos(tree.pos)
22+
final def pos(implicit ctx: Context): SourcePosition = source.atPos(tree.pos)
23+
}
24+
25+
/** An import coming from `source` */
26+
case class SourceImportTree(tree: tpd.Import, source: SourceFile) extends SourceTree
27+
28+
/** A typechecked `tree` coming from `source` */
29+
case class SourceNamedTree(tree: tpd.NameTree, source: SourceFile) extends SourceTree {
1630

1731
/** The position of the name in `tree` */
1832
def namePos(implicit ctx: Context): SourcePosition = {
@@ -39,22 +53,34 @@ case class SourceTree(topLevelImports: List[tpd.Import], tree: tpd.NameTree, sou
3953
}
4054

4155
object SourceTree {
42-
def fromSymbol(sym: ClassSymbol, id: String = "")(implicit ctx: Context): Option[SourceTree] = {
56+
def fromSymbol(sym: ClassSymbol, id: String = "")(implicit ctx: Context): List[SourceTree] = {
4357
if (sym == defn.SourceFileAnnot || // FIXME: No SourceFile annotation on SourceFile itself
4458
sym.sourceFile == null) // FIXME: We cannot deal with external projects yet
45-
None
59+
Nil
4660
else {
4761
import ast.Trees._
48-
def sourceTreeOfClass(tree: tpd.Tree): Option[SourceTree] = tree match {
62+
63+
def sourceTreeOfClass(tree: tpd.Tree): Option[SourceNamedTree] = tree match {
4964
case PackageDef(_, stats) =>
50-
val imports = stats.collect { case imp: tpd.Import => imp }
51-
stats.flatMap(sourceTreeOfClass(_).map(_.copy(topLevelImports = imports))).headOption
65+
stats.flatMap(sourceTreeOfClass).headOption
5266
case tree: tpd.TypeDef if tree.symbol == sym =>
5367
val sourceFile = new SourceFile(sym.sourceFile, Codec.UTF8)
54-
Some(SourceTree(Nil, tree, sourceFile))
55-
case _ => None
68+
Some(SourceNamedTree(tree, sourceFile))
69+
case _ =>
70+
None
71+
}
72+
73+
def sourceImports(tree: tpd.Tree, sourceFile: SourceFile): List[SourceImportTree] = tree match {
74+
case PackageDef(_, stats) => stats.flatMap(sourceImports(_, sourceFile))
75+
case imp: tpd.Import => SourceImportTree(imp, sourceFile) :: Nil
76+
case _ => Nil
77+
}
78+
79+
val tree = sym.treeContaining(id)
80+
sourceTreeOfClass(tree) match {
81+
case Some(namedTree) => namedTree :: sourceImports(tree, namedTree.source)
82+
case None => Nil
5683
}
57-
sourceTreeOfClass(sym.treeContaining(id))
5884
}
5985
}
6086
}

compiler/src/dotty/tools/repl/ReplDriver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import dotc.reporting.MessageRendering
99
import dotc.reporting.diagnostic.MessageContainer
1010
import dotc.ast.untpd
1111
import dotc.ast.tpd
12-
import dotc.interactive.{ SourceTree, Interactive }
12+
import dotc.interactive.{ SourceNamedTree, Interactive }
1313
import dotc.core.Contexts.Context
1414
import dotc.{ CompilationUnit, Run }
1515
import dotc.core.Mode

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ class DottyLanguageServer extends LanguageServer
279279
(driver.allTreesContaining(sym.name.sourceModuleName.toString),
280280
Include.overriding | Include.overridden)
281281
else
282-
(SourceTree.fromSymbol(sym.topLevelClass.asClass).toList,
282+
(SourceTree.fromSymbol(sym.topLevelClass.asClass),
283283
Include.overriding)
284284
Interactive.namedTrees(trees, include, sym)
285285
}

0 commit comments

Comments
 (0)