Skip to content

Commit 0182e4c

Browse files
committed
Introduce SourceImportTree and SourceNamedTree
1 parent ba646a6 commit 0182e4c

File tree

5 files changed

+80
-51
lines changed

5 files changed

+80
-51
lines changed

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

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ object Interactive {
282282
* source code.
283283
*/
284284
def namedTrees(trees: List[SourceTree], include: Include.Set, sym: Symbol)
285-
(implicit ctx: Context): List[SourceTree] =
285+
(implicit ctx: Context): List[SourceNamedTree] =
286286
if (!sym.exists)
287287
Nil
288288
else
@@ -293,38 +293,40 @@ object Interactive {
293293
* @param includeReferences If true, include references and not just definitions
294294
*/
295295
def namedTrees(trees: List[SourceTree], includeReferences: Boolean, nameSubstring: String)
296-
(implicit ctx: Context): List[SourceTree] =
296+
(implicit ctx: Context): List[SourceNamedTree] =
297297
namedTrees(trees, includeReferences, _.show.toString.contains(nameSubstring))
298298

299299
/** Find named trees with a non-empty position satisfying `treePredicate` in `trees`.
300300
*
301301
* @param includeReferences If true, include references and not just definitions
302302
*/
303303
def namedTrees(trees: List[SourceTree], includeReferences: Boolean, treePredicate: NameTree => Boolean)
304-
(implicit ctx: Context): List[SourceTree] = safely {
305-
val buf = new mutable.ListBuffer[SourceTree]
306-
307-
trees foreach { case SourceTree(_, topTree, source) =>
308-
new untpd.TreeTraverser {
309-
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
310-
tree match {
311-
case utree: untpd.NameTree if tree.hasType =>
312-
val tree = utree.asInstanceOf[tpd.NameTree]
313-
if (tree.symbol.exists
314-
&& !tree.symbol.is(Synthetic)
315-
&& tree.pos.exists
316-
&& !tree.pos.isZeroExtent
317-
&& (includeReferences || isDefinition(tree))
318-
&& treePredicate(tree))
319-
buf += SourceTree(Nil, tree, source)
320-
traverseChildren(tree)
321-
case tree: untpd.Inlined =>
322-
traverse(tree.call)
323-
case _ =>
324-
traverseChildren(tree)
304+
(implicit ctx: Context): List[SourceNamedTree] = safely {
305+
val buf = new mutable.ListBuffer[SourceNamedTree]
306+
307+
trees foreach {
308+
case SourceNamedTree(topTree, source) =>
309+
new untpd.TreeTraverser {
310+
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
311+
tree match {
312+
case utree: untpd.NameTree if tree.hasType =>
313+
val tree = utree.asInstanceOf[tpd.NameTree]
314+
if (tree.symbol.exists
315+
&& !tree.symbol.is(Synthetic)
316+
&& tree.pos.exists
317+
&& !tree.pos.isZeroExtent
318+
&& (includeReferences || isDefinition(tree))
319+
&& treePredicate(tree))
320+
buf += SourceNamedTree(tree, source)
321+
traverseChildren(tree)
322+
case tree: untpd.Inlined =>
323+
traverse(tree.call)
324+
case _ =>
325+
traverseChildren(tree)
326+
}
325327
}
326-
}
327-
}.traverse(topTree)
328+
}.traverse(topTree)
329+
case _: SourceImportTree => ()
328330
}
329331

330332
buf.toList
@@ -335,9 +337,9 @@ object Interactive {
335337
* the tree closest enclosing `pos` and ends with an element of `trees`.
336338
*/
337339
def pathTo(trees: List[SourceTree], pos: SourcePosition)(implicit ctx: Context): List[Tree] = {
338-
val allTrees = trees.flatMap(t => t.tree :: t.topLevelImports)
339-
allTrees.find(t => t.pos.contains(pos.pos)) match {
340-
case Some(tree) => pathTo(tree, pos.pos)
340+
trees.find(t => t.pos.contains(pos)) match {
341+
case Some(tree) =>
342+
pathTo(tree.tree, pos.pos)
341343
case None => Nil
342344
}
343345
}

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: 2 additions & 2 deletions
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
@@ -172,7 +172,7 @@ class ReplDriver(settings: Array[String],
172172
implicit val ctx: Context = state.run.runContext
173173
val file = new dotc.util.SourceFile("compl", expr)
174174
val srcPos = dotc.util.SourcePosition(file, Position(cursor))
175-
val (startOffset, completions) = Interactive.completions(SourceTree(Nil, tree, file) :: Nil, srcPos)(ctx)
175+
val (startOffset, completions) = Interactive.completions(SourceNamedTree(tree, file) :: Nil, srcPos)(ctx)
176176
val query =
177177
if (startOffset < cursor) expr.substring(startOffset, cursor) else ""
178178

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)