Skip to content

Commit d0d9594

Browse files
authored
Merge pull request #320 from scala/backport-lts-3.3-22771
Backport "fix: go to def should lead to all: apply, object and class" to 3.3 LTS
2 parents 171926a + 3c90b91 commit d0d9594

File tree

3 files changed

+118
-47
lines changed

3 files changed

+118
-47
lines changed

presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ object MetalsInteractive:
100100
pos: SourcePosition,
101101
indexed: IndexedContext,
102102
skipCheckOnName: Boolean = false
103-
): List[Symbol] =
103+
)(using Context): List[Symbol] =
104104
enclosingSymbolsWithExpressionType(path, pos, indexed, skipCheckOnName)
105-
.map(_._1)
105+
.map(_._1.sourceSymbol)
106106

107107
/**
108108
* Returns the list of tuple enclosing symbol and
@@ -203,6 +203,15 @@ object MetalsInteractive:
203203
case _ =>
204204
Nil
205205

206+
case head :: (sel @ Select(_, name)) :: _
207+
if head.sourcePos.encloses(sel.sourcePos) && (name == StdNames.nme.apply || name == StdNames.nme.unapply) =>
208+
val optObjectSymbol = List(head.symbol).filter(sym => !(sym.is(Synthetic) && sym.is(Module)))
209+
val classSymbol = head.symbol.companionClass
210+
val optApplySymbol = List(sel.symbol).filter(sym => !sym.is(Synthetic))
211+
val symbols = optObjectSymbol ++ (classSymbol :: optApplySymbol)
212+
symbols.collect:
213+
case sym if sym.exists => (sym, sym.info, None)
214+
206215
case path @ head :: tail =>
207216
if head.symbol.is(Exported) then
208217
val sym = head.symbol.sourceSymbol

presentation-compiler/src/main/dotty/tools/pc/PcDefinitionProvider.scala

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class PcDefinitionProvider(
7979
.untypedPath(pos.span)
8080
.collect { case t: untpd.Tree => t }
8181

82-
definitionsForSymbol(untpdPath.headOption.map(_.symbol).toList, uri, pos)
82+
definitionsForSymbols(untpdPath.headOption.map(_.symbol).toList, uri, pos)
8383
end fallbackToUntyped
8484

8585
private def findDefinitions(
@@ -89,7 +89,7 @@ class PcDefinitionProvider(
8989
uri: URI,
9090
): DefinitionResult =
9191
import indexed.ctx
92-
definitionsForSymbol(
92+
definitionsForSymbols(
9393
MetalsInteractive.enclosingSymbols(path, pos, indexed),
9494
uri,
9595
pos
@@ -113,68 +113,58 @@ class PcDefinitionProvider(
113113
case Nil =>
114114
path.headOption match
115115
case Some(value: Literal) =>
116-
definitionsForSymbol(List(value.typeOpt.widen.typeSymbol), uri, pos)
116+
definitionsForSymbols(List(value.typeOpt.widen.typeSymbol), uri, pos)
117117
case _ => DefinitionResultImpl.empty
118118
case _ =>
119-
definitionsForSymbol(typeSymbols, uri, pos)
120-
119+
definitionsForSymbols(typeSymbols, uri, pos)
121120
end findTypeDefinitions
122121

123-
private def definitionsForSymbol(
122+
private def definitionsForSymbols(
124123
symbols: List[Symbol],
125124
uri: URI,
126125
pos: SourcePosition
127126
)(using ctx: Context): DefinitionResult =
128-
symbols match
129-
case symbols @ (sym :: other) =>
130-
val isLocal = sym.source == pos.source
131-
if isLocal then
132-
val include = Include.definitions | Include.local
133-
val (exportedDefs, otherDefs) =
134-
Interactive.findTreesMatching(driver.openedTrees(uri), include, sym)
135-
.partition(_.tree.symbol.is(Exported))
136-
137-
otherDefs.headOption.orElse(exportedDefs.headOption) match
138-
case Some(srcTree) =>
139-
val pos = srcTree.namePos
140-
if pos.exists then
141-
val loc = new Location(params.uri().toString(), pos.toLsp)
142-
DefinitionResultImpl(
143-
SemanticdbSymbols.symbolName(sym),
144-
List(loc).asJava,
145-
)
146-
else DefinitionResultImpl.empty
147-
case None =>
148-
DefinitionResultImpl.empty
149-
else
150-
val res = new ArrayList[Location]()
151-
semanticSymbolsSorted(symbols)
152-
.foreach { sym =>
153-
res.addAll(search.definition(sym, params.uri()))
154-
}
155-
DefinitionResultImpl(
156-
SemanticdbSymbols.symbolName(sym),
157-
res
158-
)
159-
end if
127+
semanticSymbolsSorted(symbols) match
160128
case Nil => DefinitionResultImpl.empty
161-
end match
162-
end definitionsForSymbol
129+
case syms @ ((_, headSym) :: tail) =>
130+
val locations = syms.flatMap:
131+
case (sym, semanticdbSymbol) =>
132+
locationsForSymbol(sym, semanticdbSymbol, uri, pos)
133+
DefinitionResultImpl(headSym, locations.asJava)
134+
135+
private def locationsForSymbol(
136+
symbol: Symbol,
137+
semanticdbSymbol: String,
138+
uri: URI,
139+
pos: SourcePosition
140+
)(using ctx: Context): List[Location] =
141+
val isLocal = symbol.source == pos.source
142+
if isLocal then
143+
val trees = driver.openedTrees(uri)
144+
val include = Include.definitions | Include.local
145+
val (exportedDefs, otherDefs) =
146+
Interactive.findTreesMatching(trees, include, symbol)
147+
.partition(_.tree.symbol.is(Exported))
148+
otherDefs.headOption.orElse(exportedDefs.headOption).collect:
149+
case srcTree if srcTree.namePos.exists =>
150+
new Location(params.uri().toString(), srcTree.namePos.toLsp)
151+
.toList
152+
else search.definition(semanticdbSymbol, uri).asScala.toList
163153

164154
def semanticSymbolsSorted(
165155
syms: List[Symbol]
166-
)(using ctx: Context): List[String] =
156+
)(using ctx: Context): List[(Symbol, String)] =
167157
syms
168-
.map { sym =>
158+
.collect { case sym if sym.exists =>
169159
// in case of having the same type and teerm symbol
170160
// term comes first
171161
// used only for ordering symbols that come from `Import`
172162
val termFlag =
173163
if sym.is(ModuleClass) then sym.sourceModule.isTerm
174164
else sym.isTerm
175-
(termFlag, SemanticdbSymbols.symbolName(sym))
165+
(termFlag, sym.sourceSymbol, SemanticdbSymbols.symbolName(sym))
176166
}
177-
.sorted
178-
.map(_._2)
167+
.sortBy { case (termFlag, _, name) => (termFlag, name) }
168+
.map(_.tail)
179169

180170
end PcDefinitionProvider

presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,3 +531,75 @@ class PcDefinitionSuite extends BasePcDefinitionSuite:
531531
|val a = MyIntOut(1).un@@even
532532
|""".stripMargin,
533533
)
534+
535+
@Test def `object` =
536+
check(
537+
"""|package a
538+
|object <<Bar>> {
539+
| def foo = 42
540+
|}
541+
|val m = B@@ar.foo
542+
|""".stripMargin
543+
)
544+
545+
@Test def i7267 =
546+
check(
547+
"""|package a
548+
|trait Foo {
549+
| def someNum: Int
550+
| def <<apply>>(i: Int): Unit = println(someNum)
551+
|}
552+
|object <<Bar>> extends Foo {
553+
| def someNum = 42
554+
|}
555+
|
556+
|object Test {
557+
| B@@ar(2)
558+
|}
559+
|""".stripMargin
560+
)
561+
562+
@Test def `i7267-2` =
563+
check(
564+
"""|package b
565+
|trait Foo {
566+
| def someNum: Int
567+
| def <<unapply>>(i: Int): Option[Int] = Some(i)
568+
|}
569+
|object <<Bar>> extends Foo {
570+
| def someNum = 42
571+
|}
572+
|
573+
|object Test {
574+
| Bar.someNum match {
575+
| case B@@ar(1) => ???
576+
| case _ =>
577+
| }
578+
|}
579+
|""".stripMargin
580+
)
581+
582+
@Test def `i7267-3` =
583+
check(
584+
"""|package c
585+
|case class <<Bar>>()
586+
|object <<Bar>>
587+
|object O {
588+
| val a = B@@ar()
589+
|}
590+
|""".stripMargin
591+
)
592+
593+
@Test def `i7267-4` =
594+
check(
595+
"""|package d
596+
|class <<Bar>>()
597+
|object <<Bar>> {
598+
| def <<apply>>(): Bar = new Bar()
599+
|}
600+
|object O {
601+
| val a = B@@ar()
602+
|}
603+
|""".stripMargin
604+
)
605+

0 commit comments

Comments
 (0)