Skip to content

Commit 75cbbd6

Browse files
Merge pull request #5276 from dotty-staging/fix/sourceloader-roottreeprovider
Keep package structure in `rootTreeOrProvider`
2 parents f66225c + 136b0ce commit 75cbbd6

File tree

6 files changed

+72
-4
lines changed

6 files changed

+72
-4
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Compiler {
3939
List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks
4040
List(new PostTyper) :: // Additional checks and cleanups after type checking
4141
List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks
42+
List(new SetRootTree) :: // Set the `rootTreeOrProvider` on class symbols
4243
Nil
4344

4445
/** Phases dealing with TASTY tree pickling and unpickling */

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
200200

201201
/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
202202
* The newly added symbols replace any previously entered symbols.
203-
* If `typeCheck = true`, also run typer on the compilation unit.
203+
* If `typeCheck = true`, also run typer on the compilation unit, and set
204+
* `rootTreeOrProvider`.
204205
*/
205206
def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit =
206207
if (!files.contains(file) && !lateFiles.contains(file)) {
@@ -211,9 +212,13 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
211212
if (unit.isJava) new JavaParser(unit.source).parse()
212213
else new Parser(unit.source).parse()
213214
ctx.typer.lateEnter(unit.untpdTree)
214-
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
215+
def processUnit() = {
216+
unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
217+
val phase = new transform.SetRootTree()
218+
phase.run
219+
}
215220
if (typeCheck)
216-
if (compiling) finalizeActions += (() => typeCheckUnit()) else typeCheckUnit()
221+
if (compiling) finalizeActions += (() => processUnit()) else processUnit()
217222
}
218223
process()(runContext.fresh.setCompilationUnit(unit))
219224
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class InteractiveCompiler extends Compiler {
1313
// after each phase group instead of waiting for the pipeline to finish.
1414
override def phases: List[List[Phase]] = List(
1515
List(new FrontEnd),
16+
List(new transform.SetRootTree),
1617
List(new transform.CookComments)
1718
)
1819
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.CompilationUnit
4+
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import dotty.tools.dotc.core.Phases.Phase
7+
8+
/** Set the `rootTreeOrProvider` property of class symbols. */
9+
class SetRootTree extends Phase {
10+
11+
override val phaseName: String = SetRootTree.name
12+
override def isRunnable(implicit ctx: Context) =
13+
super.isRunnable && ctx.settings.YretainTrees.value
14+
15+
override def run(implicit ctx: Context): Unit = {
16+
val tree = ctx.compilationUnit.tpdTree
17+
traverser.traverse(tree)
18+
}
19+
20+
private def traverser = new tpd.TreeTraverser {
21+
override def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = {
22+
tree match {
23+
case pkg: tpd.PackageDef =>
24+
traverseChildren(pkg)
25+
case td: tpd.TypeDef =>
26+
if (td.symbol.isClass) {
27+
val sym = td.symbol.asClass
28+
tpd.sliceTopLevel(ctx.compilationUnit.tpdTree, sym) match {
29+
case (pkg: tpd.PackageDef) :: Nil =>
30+
sym.rootTreeOrProvider = pkg
31+
case _ =>
32+
sym.rootTreeOrProvider = td
33+
}
34+
}
35+
case _ =>
36+
()
37+
}
38+
}
39+
}
40+
}
41+
42+
object SetRootTree {
43+
val name: String = "SetRootTree"
44+
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1642,7 +1642,11 @@ class Typer extends Namer
16421642
// check value class constraints
16431643
checkDerivedValueClass(cls, body1)
16441644

1645-
if (ctx.settings.YretainTrees.value) cls.rootTreeOrProvider = cdef1
1645+
1646+
// Temporarily set the typed class def as root tree so that we have at least some
1647+
// information in the IDE in case we never reach `SetRootTree`.
1648+
if (ctx.mode.is(Mode.Interactive) && ctx.settings.YretainTrees.value)
1649+
cls.rootTreeOrProvider = cdef1
16461650

16471651
cdef1
16481652

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,19 @@ class RenameTest {
236236

237237
}
238238

239+
@Test def renameImportFromTasty: Unit = {
240+
// Note that everything here is in the empty package; this ensures that we will
241+
// use the sourcefile loader to load `class Bar`.
242+
def testRename(m: CodeMarker) = {
243+
withSources(
244+
code"""object O { class ${m1}Foo${m2} }""",
245+
tasty"""import O.${m3}Foo${m4}
246+
class Bar extends ${m5}Foo${m6}"""
247+
).rename(m, "NewName", Set(m1 to m2, m3 to m4, m5 to m6))
248+
}
239249

250+
testRename(m1)
251+
testRename(m2)
252+
}
240253

241254
}

0 commit comments

Comments
 (0)