Skip to content

Commit d63e584

Browse files
committed
Allow symbols to be loaded from source in IDE
Various tweaks necessary so that symbols can be loaded from source.
1 parent d1db0dc commit d63e584

File tree

4 files changed

+43
-17
lines changed

4 files changed

+43
-17
lines changed

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import util.Stats
1414
import Decorators._
1515
import scala.util.control.NonFatal
1616
import ast.Trees._
17+
import ast.tpd
1718
import parsing.Parsers.OutlineParser
1819
import reporting.trace
1920

@@ -118,7 +119,9 @@ class SymbolLoaders {
118119
scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
119120

120121
val completer = new SourcefileLoader(src)
121-
if (ctx.settings.scansource.value) {
122+
if (ctx.settings.scansource.value && ctx.run != null) {
123+
System.out.print(i"scanning $src ...")
124+
System.out.flush()
122125
if (src.exists && !src.isDirectory) {
123126
val filePath = owner.ownersIterator.takeWhile(!_.isRoot).map(_.name.toTermName).toList
124127

@@ -160,6 +163,7 @@ class SymbolLoaders {
160163

161164
val unit = new CompilationUnit(ctx.run.getSource(src.path))
162165
enterScanned(unit)(ctx.run.runContext.fresh.setCompilationUnit(unit))
166+
System.out.println(" done")
163167
}
164168
}
165169
else enterClassAndModule(owner, name, completer, scope = scope)
@@ -338,15 +342,8 @@ abstract class SymbolLoader extends LazyType {
338342
postProcess(root.scalacLinkedClass.denot)
339343
}
340344
}
341-
}
342-
343-
class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
344-
345-
override def sourceFileOrNull: AbstractFile = classfile
346345

347-
def description(implicit ctx: Context) = "class file " + classfile.toString
348-
349-
def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
346+
protected def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
350347
val linkedDenot = rootDenot.scalacLinkedClass.denot match {
351348
case d: ClassDenotation => d
352349
case d =>
@@ -368,6 +365,13 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
368365
if (rootDenot is ModuleClass) (linkedDenot, rootDenot)
369366
else (rootDenot, linkedDenot)
370367
}
368+
}
369+
370+
class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
371+
372+
override def sourceFileOrNull: AbstractFile = classfile
373+
374+
def description(implicit ctx: Context) = "class file " + classfile.toString
371375

372376
override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
373377
load(root)
@@ -393,6 +397,20 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
393397
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
394398
def description(implicit ctx: Context) = "source file " + srcfile.toString
395399
override def sourceFileOrNull = srcfile
396-
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
400+
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = {
397401
ctx.run.enterRoots(srcfile)
402+
if (ctx.settings.YretainTrees.value) {
403+
val (classRoot, moduleRoot) = rootDenots(root.asClass)
404+
classRoot.classSymbol.treeOrProvider = treeProvider
405+
moduleRoot.classSymbol.treeOrProvider = treeProvider
406+
}
407+
}
408+
object treeProvider extends tpd.TreeProvider {
409+
def computeTrees(implicit ctx: Context): List[tpd.Tree] = {
410+
var units = new CompilationUnit(ctx.run.getSource(srcfile.path)) :: Nil
411+
for (phase <- ctx.allPhases; if phase.isTyper)
412+
units = phase.runOn(units)
413+
units.map(_.tpdTree)
414+
}
415+
}
398416
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,18 @@ object Interactive {
176176
}
177177

178178
/** Check if `tree` matches `sym`.
179-
* This is the case if `sym` is the symbol of `tree` or, if `includeOverriden`
180-
* is true, if `sym` is overriden by `tree`.
179+
* This is the case if one of the following is true:
180+
* (1) `sym` is the symbol of `tree`, or
181+
* (2) The two symbols have the same name and class owner, or
182+
* (3) `includeOverriden is true, and `sym` is overriden by `tree`.
183+
*
184+
* The reason for (2) is that if a symbol comes from a SourcefileLoader it is
185+
* different from the symbol that was referred to, until the next run is started.
181186
*/
182187
def matchSymbol(tree: Tree, sym: Symbol, includeOverriden: Boolean)(implicit ctx: Context): Boolean =
183-
(sym == tree.symbol) || (includeOverriden && tree.symbol.allOverriddenSymbols.contains(sym))
188+
(sym == tree.symbol) ||
189+
sym.name == tree.symbol.name && sym.owner.isClass && sym.owner == tree.symbol.owner ||
190+
(includeOverriden && tree.symbol.allOverriddenSymbols.contains(sym))
184191

185192

186193
/** The reverse path to the node that closest encloses position `pos`,

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import ast.tpd
88
import core._, core.Decorators.{sourcePos => _, _}
99
import Contexts._, NameOps._, Symbols._
1010
import util._, util.Positions._
11+
import Interactive.matchSymbol
1112

1213
/** A typechecked named `tree` coming from `source` */
1314
case class SourceTree(tree: tpd.NameTree, source: SourceFile) {
@@ -45,8 +46,9 @@ object SourceTree {
4546
else {
4647
import ast.Trees._
4748
def sourceTreeOfClass(tree: tpd.Tree): Option[SourceTree] = tree match {
48-
case PackageDef(_, stats) => stats.flatMap(sourceTreeOfClass).headOption
49-
case tree: tpd.TypeDef if tree.symbol == sym =>
49+
case PackageDef(_, stats) =>
50+
stats.flatMap(sourceTreeOfClass).headOption
51+
case tree: tpd.TypeDef if matchSymbol(tree, sym, includeOverriden = false) =>
5052
val sourceFile = new SourceFile(sym.sourceFile, Codec.UTF8)
5153
Some(SourceTree(tree, sourceFile))
5254
case _ => None

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ class DottyLanguageServer extends LanguageServer
6565
myDrivers = new mutable.HashMap
6666
for (config <- configs) {
6767
val classpathFlags = List("-classpath", (config.classDirectory +: config.dependencyClasspath).mkString(File.pathSeparator))
68-
val sourcepathFlags = List("-sourcepath", config.sourceDirectories.mkString(File.pathSeparator))
69-
System.out.println(s"sourcepath = $sourcepathFlags")
68+
val sourcepathFlags = List("-sourcepath", config.sourceDirectories.mkString(File.pathSeparator), "-scansource")
7069
val settings = defaultFlags ++ config.compilerArguments.toList ++ classpathFlags ++ sourcepathFlags
7170
myDrivers.put(config, new InteractiveDriver(settings))
7271
}

0 commit comments

Comments
 (0)