Skip to content

Commit c0192cf

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 1236ba5 commit c0192cf

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
@@ -625,16 +625,27 @@ object Symbols {
625625
* then return the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree.
626626
* This will force the info of the class.
627627
*/
628-
def tree(implicit ctx: Context): Tree = denot.infoOrCompleter match {
628+
def tree(implicit ctx: Context): Tree = treeContaining("")
629+
630+
/** Same as `tree` but load only Tasty tree if the name table of the unpickler
631+
* contains `id`.
632+
*/
633+
def treeContaining(id: String)(implicit ctx: Context): Tree = denot.infoOrCompleter match {
629634
case _: NoCompleter =>
630635
tpd.EmptyTree
631636
case _ =>
632637
denot.ensureCompleted()
633638
myTree match {
634-
case fn: TreeProvider => myTree = fn.tree
635-
case _ =>
639+
case fn: TreeProvider =>
640+
if (id.isEmpty || fn.mightContain(id)) {
641+
val tree = fn.tree
642+
myTree = tree
643+
tree
644+
}
645+
else tpd.EmptyTree
646+
case tree: Tree @ unchecked =>
647+
tree
636648
}
637-
myTree.asInstanceOf[Tree]
638649
}
639650

640651
def treeOrProvider: TreeOrProvider = myTree
@@ -658,7 +669,7 @@ object Symbols {
658669
denot = underlying.denot
659670
}
660671

661-
@sharable val NoSymbol = new Symbol(NoCoord, 0) {
672+
@sharable val NoSymbol: Symbol = new Symbol(NoCoord, 0) {
662673
override def associatedFile(implicit ctx: Context): AbstractFile = NoSource.file
663674
override def recomputeDenot(lastd: SymDenotation)(implicit ctx: Context): SymDenotation = NoDenotation
664675
}

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)