Skip to content

Commit

Permalink
Support goto-def on exported methods too
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Jan 21, 2024
1 parent 4e532e9 commit 434f066
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 81 deletions.
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
buf.toList
}

def collectSubTrees[A](f: PartialFunction[Tree, A])(using Context): List[A] =
val buf = mutable.ListBuffer[A]()
foreachSubTree(f.runWith(buf += _)(_))
buf.toList

/** Set this tree as the `defTree` of its symbol and return this tree */
def setDefTree(using Context): ThisTree = {
val sym = tree.symbol
Expand Down
13 changes: 10 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import DenotTransformers.*
import StdNames.*
import NameOps.*
import NameKinds.LazyImplicitName
import ast.tpd
import tpd.{Tree, TreeProvider, TreeOps}
import ast.TreeTypeMap
import ast.*, tpd.*
import Constants.Constant
import Variances.Variance
import reporting.Message
Expand Down Expand Up @@ -336,6 +334,15 @@ object Symbols extends SymUtils {
denot.info.dropAlias.finalResultType.typeConstructor match
case tp: NamedType => tp.symbol.sourceSymbol
case _ => this
else if denot.is(ExportedTerm) then
val root = denot.maybeOwner match
case cls: ClassSymbol => cls.rootTreeContaining(name.toString)
case _ => EmptyTree
val targets = root.collectSubTrees:
case tree: DefDef if tree.name == name => methPart(tree.rhs).tpe
targets.match
case (tp: NamedType) :: _ => tp.symbol
case _ => this
else if (denot.is(Synthetic)) {
val linked = denot.linkedClass
if (linked.exists && !linked.is(Synthetic))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
package dotty.tools.pc
package dotty.tools
package pc

import scala.annotation.tailrec

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.tpd.*
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.core.Flags.*
import dotty.tools.dotc.core.Names.Name
import dotty.tools.dotc.core.StdNames
import dotty.tools.dotc.core.Symbols.*
import dotty.tools.dotc.core.Types.Type
import dotty.tools.dotc.interactive.SourceTree
import dotty.tools.dotc.util.SourceFile
import dotty.tools.dotc.util.SourcePosition
import dotc.*
import ast.*, tpd.*
import core.*, Contexts.*, Decorators.*, Flags.*, Names.*, Symbols.*, Types.*
import interactive.*
import util.*
import util.SourcePosition

object MetalsInteractive:

Expand Down Expand Up @@ -205,7 +200,7 @@ object MetalsInteractive:
Nil

case path @ head :: tail =>
if head.symbol.is(ExportedType) then
if head.symbol.is(Exported) then
val sym = head.symbol.sourceSymbol
List((sym, sym.info))
else if head.symbol.is(Synthetic) then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,89 +199,67 @@ class PcDefinitionSuite extends BasePcDefinitionSuite:
|""".stripMargin
)

@Test def `exportType1` =
check(
"""object enumerations:
| trait <<SymbolKind>>
| trait CymbalKind
|
|object all:
| export enumerations.*
|
|@main def hello =
| import all.SymbolKind
| import enumerations.CymbalKind
|
| val x = new Symbo@@lKind {}
| val y = new CymbalKind {}
@Test def exportType0 =
check(
"""object Foo:
| trait <<Cat>>
|object Bar:
| export Foo.*
|class Test:
| import Bar.*
| def test = new Ca@@t {}
|""".stripMargin
)

@Test def `exportType1Wild` =
check(
"""object enumerations:
| trait <<SymbolKind>>
| trait CymbalKind
|
|object all:
| export enumerations.SymbolKind
|
|@main def hello =
| import all.SymbolKind
| import enumerations.CymbalKind
|
| val x = new Symbo@@lKind {}
| val y = new CymbalKind {}
@Test def exportType1 =
check(
"""object Foo:
| trait <<Cat>>[A]
|object Bar:
| export Foo.*
|class Test:
| import Bar.*
| def test = new Ca@@t[Int] {}
|""".stripMargin
)

@Test def `exportTerm1` =
@Test def exportTerm0Nullary =
check(
"""class BitMap
|class Scanner:
| def scan(): BitMap = ???
|class Copier:
| private val scanUnit = new Scanner
| export scanUnit.<<scan>>
| def t1 = sc@@an()
"""trait Foo:
| def <<meth>>: Int
|class Bar(val foo: Foo):
| export foo.*
| def test(bar: Bar) = bar.me@@th
|""".stripMargin
)

@Test def `exportTerm2` =
@Test def exportTerm0 =
check(
"""class BitMap
|class Scanner:
| def scan(): BitMap = ???
|class Copier:
| private val scanUnit = new Scanner
| export scanUnit.<<scan>>
|class Test:
| def t2(cpy: Copier) = cpy.sc@@an()
"""trait Foo:
| def <<meth>>(): Int
|class Bar(val foo: Foo):
| export foo.*
| def test(bar: Bar) = bar.me@@th()
|""".stripMargin
)

@Test def `exportTerm1Wild` =
@Test def exportTerm1 =
check(
"""class BitMap
|class Scanner:
| def scan(): BitMap = ???
|class Copier:
| private val scanUnit = new Scanner
| export scanUnit.<<*>>
| def t1 = sc@@an()
"""trait Foo:
| def <<meth>>(x: Int): Int
|class Bar(val foo: Foo):
| export foo.*
| def test(bar: Bar) = bar.me@@th(0)
|""".stripMargin
)

@Test def `exportTerm2Wild` =
@Test def exportTerm1Poly =
check(
"""class BitMap
|class Scanner:
| def scan(): BitMap = ???
|class Copier:
| private val scanUnit = new Scanner
| export scanUnit.<<*>>
|class Test:
| def t2(cpy: Copier) = cpy.sc@@an()
"""trait Foo:
| def <<meth>>[A](x: A): A
|class Bar(val foo: Foo):
| export foo.*
| def test(bar: Bar) = bar.me@@th(0)
|""".stripMargin
)

Expand Down

0 comments on commit 434f066

Please sign in to comment.