Skip to content

Commit d777823

Browse files
committed
Make findReferences more robust and faster
- Don't fail if a class file is not found - Consult name tables of Tasty info for a possible match before loading tree. - Do the same for rename
1 parent 1c3c697 commit d777823

File tree

6 files changed

+39
-14
lines changed

6 files changed

+39
-14
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
889889
/** Get first tree defined by this provider, or EmptyTree if none exists */
890890
def tree(implicit ctx: Context): Tree =
891891
trees.headOption.getOrElse(EmptyTree)
892+
893+
/** Is it possible that the tree to load contains a definition of or reference to `id`? */
894+
def mightContain(id: String)(implicit ctx: Context) = true
892895
}
893896

894897
// convert a numeric with a toXXX method

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -633,16 +633,27 @@ object Symbols {
633633
* then return the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree.
634634
* This will force the info of the class.
635635
*/
636-
def tree(implicit ctx: Context): Tree = denot.infoOrCompleter match {
636+
def tree(implicit ctx: Context): Tree = treeContaining("")
637+
638+
/** Same as `tree` but load only Tasty tree if the name table of the unpickler
639+
* contains `id`.
640+
*/
641+
def treeContaining(id: String)(implicit ctx: Context): Tree = denot.infoOrCompleter match {
637642
case _: NoCompleter =>
638643
tpd.EmptyTree
639644
case _ =>
640645
denot.ensureCompleted()
641646
myTree match {
642-
case fn: TreeProvider => myTree = fn.tree
643-
case _ =>
647+
case fn: TreeProvider =>
648+
if (id.isEmpty || fn.mightContain(id)) {
649+
val tree = fn.tree
650+
myTree = tree
651+
tree
652+
}
653+
else tpd.EmptyTree
654+
case tree: Tree @ unchecked =>
655+
tree
644656
}
645-
myTree.asInstanceOf[Tree]
646657
}
647658

648659
def treeOrProvider: TreeOrProvider = myTree
@@ -666,7 +677,7 @@ object Symbols {
666677
denot = underlying.denot
667678
}
668679

669-
@sharable val NoSymbol = new Symbol(NoCoord, 0) {
680+
@sharable val NoSymbol: Symbol = new Symbol(NoCoord, 0) {
670681
override def associatedFile(implicit ctx: Context): AbstractFile = NoSource.file
671682
override def recomputeDenot(lastd: SymDenotation)(implicit ctx: Context): SymDenotation = NoDenotation
672683
}

compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,11 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t
5151
}
5252

5353
protected def computeTrees(implicit ctx: Context) = treeUnpickler.unpickle()
54+
55+
private[this] var ids: Array[String] = null
56+
57+
override def mightContain(id: String)(implicit ctx: Context): Boolean = {
58+
if (ids == null) ids = unpickler.nameAtRef.contents.toArray.map(_.toString).sorted
59+
java.util.Arrays.binarySearch(ids.asInstanceOf[Array[Object]], id) >= 0
60+
}
5461
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,26 @@ class InteractiveDriver(settings: List[String]) extends Driver {
5353
def openedFiles: Map[URI, SourceFile] = myOpenedFiles
5454
def openedTrees: Map[URI, List[SourceTree]] = myOpenedTrees
5555

56-
def allTrees(implicit ctx: Context): List[SourceTree] = {
56+
def allTrees(implicit ctx: Context): List[SourceTree] = allTreesContaining("")
57+
58+
def allTreesContaining(id: String)(implicit ctx: Context): List[SourceTree] = {
5759
val fromSource = openedTrees.values.flatten.toList
5860
val fromClassPath = (dirClassPathClasses ++ zipClassPathClasses).flatMap { cls =>
5961
val className = cls.toTypeName
60-
List(tree(className), tree(className.moduleClassName)).flatten
62+
List(tree(className, id), tree(className.moduleClassName, id)).flatten
6163
}
6264
(fromSource ++ fromClassPath).distinct
6365
}
6466

65-
private def tree(className: TypeName)(implicit ctx: Context): Option[SourceTree] = {
67+
private def tree(className: TypeName, id: String)(implicit ctx: Context): Option[SourceTree] = {
6668
val clsd = ctx.base.staticRef(className)
6769
clsd match {
6870
case clsd: ClassDenotation =>
69-
SourceTree.fromSymbol(clsd.symbol.asClass)
71+
clsd.ensureCompleted()
72+
SourceTree.fromSymbol(clsd.symbol.asClass, id)
7073
case _ =>
71-
sys.error(s"class not found: $className")
74+
//sys.error(s"class not found: $className")
75+
None
7276
}
7377
}
7478

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ case class SourceTree(tree: tpd.NameTree, source: SourceFile) {
3939
}
4040
}
4141
object SourceTree {
42-
def fromSymbol(sym: ClassSymbol)(implicit ctx: Context): Option[SourceTree] = {
42+
def fromSymbol(sym: ClassSymbol, id: String = "")(implicit ctx: Context): Option[SourceTree] = {
4343
if (sym == defn.SourceFileAnnot || // FIXME: No SourceFile annotation on SourceFile itself
4444
sym.sourceFile == null) // FIXME: We cannot deal with external projects yet
4545
None
@@ -53,7 +53,7 @@ object SourceTree {
5353
Some(SourceTree(tree, sourceFile))
5454
case _ => None
5555
}
56-
sourceTreeOfClass(sym.tree)
56+
sourceTreeOfClass(sym.treeContaining(id))
5757
}
5858
}
5959
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ class DottyLanguageServer extends LanguageServer
243243
// FIXME: this will search for references in all trees on the classpath, but we really
244244
// only need to look for trees in the target directory if the symbol is defined in the
245245
// current project
246-
val trees = driver.allTrees
246+
val trees = driver.allTreesContaining(sym.name.toString)
247247
val refs = Interactive.namedTrees(trees, includeReferences = true, (tree: tpd.NameTree) =>
248248
(includeDeclaration || !Interactive.isDefinition(tree))
249249
&& Interactive.matchSymbol(tree, sym, includeOverriden = true))
@@ -262,7 +262,7 @@ class DottyLanguageServer extends LanguageServer
262262

263263
if (sym == NoSymbol) new WorkspaceEdit()
264264
else {
265-
val trees = driver.allTrees
265+
val trees = driver.allTreesContaining(sym.name.toString)
266266
val linkedSym = sym.linkedClass
267267
val newName = params.getNewName
268268

0 commit comments

Comments
 (0)