Skip to content

Commit 47d4b44

Browse files
committed
IDE: Look for overrides in the whole project
When doing go-to-definition, we used to look for symbols that override the symbol selected for go to definition only in the same source file as the one that was selected. This commit changes that, as suggested in the review of scala#5208.
1 parent 614265d commit 47d4b44

File tree

3 files changed

+58
-28
lines changed

3 files changed

+58
-28
lines changed

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

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import scala.collection._
88
import ast.{NavigateAST, Trees, tpd, untpd}
99
import core._, core.Decorators.{sourcePos => _, _}
1010
import Contexts._, Flags._, Names._, NameOps._, Symbols._, Trees._, Types._
11+
import transform.SymUtils.decorateSymbol
1112
import util.Positions._, util.SourceFile, util.SourcePosition
1213
import core.Denotations.SingleDenotation
1314
import NameKinds.SimpleNameKind
@@ -41,10 +42,7 @@ object Interactive {
4142
/** Include trees whose symbol is overridden by `sym` */
4243
val overridden: Set = Set(1 << 0)
4344

44-
/**
45-
* Include trees whose symbol overrides `sym` (but for performance only in same source
46-
* file)
47-
*/
45+
/** Include trees whose symbol overrides `sym` */
4846
val overriding: Set = Set(1 << 1)
4947

5048
/** Include references */
@@ -473,33 +471,44 @@ object Interactive {
473471
path.find(_.isInstanceOf[DefTree]).getOrElse(EmptyTree)
474472

475473
/**
476-
* Find the definitions of the symbol at the end of `path`.
474+
* Find the definitions of the symbol at the end of `path`. In the case of an import node,
475+
* all imported symbols will be considered.
477476
*
478477
* @param path The path to the symbol for which we want the definitions.
479478
* @param driver The driver responsible for `path`.
480479
* @return The definitions for the symbol at the end of `path`.
481480
*/
482-
def findDefinitions(path: List[Tree], pos: SourcePosition, driver: InteractiveDriver)(implicit ctx: Context): List[SourceTree] = {
483-
enclosingSourceSymbols(path, pos).flatMap { sym =>
484-
val enclTree = enclosingTree(path)
485-
486-
val (trees, include) =
487-
if (enclTree.isInstanceOf[MemberDef])
488-
(driver.allTreesContaining(sym.name.sourceModuleName.toString),
489-
Include.definitions | Include.overriding | Include.overridden)
490-
else sym.topLevelClass match {
491-
case cls: ClassSymbol =>
492-
val trees = Option(cls.sourceFile).flatMap(InteractiveDriver.toUriOption) match {
493-
case Some(uri) if driver.openedTrees.contains(uri) =>
494-
driver.openedTrees(uri)
495-
case _ => // Symbol comes from the classpath
496-
SourceTree.fromSymbol(cls).toList
497-
}
498-
(trees, Include.definitions | Include.overriding)
499-
case _ =>
500-
(Nil, Include.empty)
501-
}
481+
def findDefinitions(path: List[Tree], pos: SourcePosition, driver: InteractiveDriver): List[SourceTree] = {
482+
implicit val ctx = driver.currentCtx
483+
val enclTree = enclosingTree(path)
484+
val includeOverridden = enclTree.isInstanceOf[MemberDef]
485+
val symbols = enclosingSourceSymbols(path, pos)
486+
val includeExternal = symbols.exists(!_.isLocal)
487+
findDefinitions(symbols, driver, includeOverridden, includeExternal)
488+
}
502489

490+
/**
491+
* Find the definitions of `symbols`.
492+
*
493+
* @param symbols The list of symbols for which to find a definition.
494+
* @param driver The driver responsible for the given symbols.
495+
* @param includeOverridden If true, also include the symbols overridden by any of `symbols`.
496+
* @param includeExternal If true, also look for definitions on the classpath.
497+
* @return The definitions for the symbols in `symbols`, and if `includeOverridden` is set, the
498+
* definitions for the symbols that they override.
499+
*/
500+
def findDefinitions(symbols: List[Symbol],
501+
driver: InteractiveDriver,
502+
includeOverridden: Boolean,
503+
includeExternal: Boolean): List[SourceTree] = {
504+
implicit val ctx = driver.currentCtx
505+
val include = Include.definitions | Include.overriding |
506+
(if (includeOverridden) Include.overridden else Include.empty)
507+
symbols.flatMap { sym =>
508+
val name = sym.name.sourceModuleName.toString
509+
val trees =
510+
if (includeExternal) driver.allTreesContaining(name)
511+
else driver.sourceTreesContaining(name)
503512
findTreesMatching(trees, include, sym)
504513
}
505514
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,9 @@ class DottyLanguageServer extends LanguageServer
288288
/*isIncomplete = */ false, items.map(completionItem).asJava))
289289
}
290290

291-
/** If cursor is on a reference, show its definition and all overriding definitions in
292-
* the same source as the primary definition.
291+
/** If cursor is on a reference, show its definition and all overriding definitions.
293292
* If cursor is on a definition, show this definition together with all overridden
294-
* and overriding definitions (in all sources).
293+
* and overriding definitions.
295294
*/
296295
override def definition(params: TextDocumentPositionParams) = computeAsync { cancelToken =>
297296
val uri = new URI(params.getTextDocument.getUri)

language-server/test/dotty/tools/languageserver/DefinitionTest.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,26 @@ class DefinitionTest {
322322
.definition(m11 to m12, List(m3 to m4))
323323
}
324324

325+
@Test def definitionShowOverrides: Unit = {
326+
withSources(
327+
code"""class A { def ${m1}foo${m2}: Int = 0 }""",
328+
code"""class B extends A { def ${m3}foo${m4}: Int = 1 }""",
329+
code"""class C extends A { def ${m5}foo${m6}: Int = 2 }""",
330+
code"""class D extends C { def ${m7}foo${m8}: Int = 3 }""",
331+
code"""object O {
332+
val a = new A().${m9}foo${m10}
333+
val b = new B().${m11}foo${m12}
334+
val c = new C().${m13}foo${m14}
335+
val d = new D().${m15}foo${m16}
336+
}"""
337+
).definition(m1 to m2, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8))
338+
.definition(m3 to m4, List(m1 to m2, m3 to m4))
339+
.definition(m5 to m6, List(m1 to m2, m5 to m6, m7 to m8))
340+
.definition(m7 to m8, List(m1 to m2, m5 to m6, m7 to m8))
341+
.definition(m9 to m10, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8))
342+
.definition(m11 to m12, List(m3 to m4))
343+
.definition(m13 to m14, List(m5 to m6, m7 to m8))
344+
.definition(m15 to m16, List(m7 to m8))
345+
}
346+
325347
}

0 commit comments

Comments
 (0)