Skip to content

Commit d789e52

Browse files
committed
Merge remote-tracking branch 'upstream/master' into batch-files
2 parents 3ed96b8 + 6eddf68 commit d789e52

File tree

62 files changed

+592
-216
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+592
-216
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/Driver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Driver {
6161
}
6262

6363
/** Setup extra classpath and figure out class names for tasty file inputs */
64-
private def fromTastySetup(fileNames0: List[String], ctx0: Context) = {
64+
protected def fromTastySetup(fileNames0: List[String], ctx0: Context): (List[String], Context) = {
6565
if (ctx0.settings.fromTasty.value(ctx0)) {
6666
// Resolve classpath and class names of tasty files
6767
val (classPaths, classNames) = fileNames0.map { name =>

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/Interactive.scala

Lines changed: 64 additions & 47 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
@@ -33,6 +34,7 @@ object Interactive {
3334
def isDefinitions: Boolean = (bits & definitions.bits) != 0
3435
def isLinkedClass: Boolean = (bits & linkedClass.bits) != 0
3536
def isImports: Boolean = (bits & imports.bits) != 0
37+
def isLocal: Boolean = (bits & local.bits) != 0
3638
}
3739

3840
/** The empty set */
@@ -41,10 +43,7 @@ object Interactive {
4143
/** Include trees whose symbol is overridden by `sym` */
4244
val overridden: Set = Set(1 << 0)
4345

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

5049
/** Include references */
@@ -59,6 +58,9 @@ object Interactive {
5958
/** Include imports in the results */
6059
val imports: Set = Set(1 << 5)
6160

61+
/** Include local symbols, inspect local trees */
62+
val local: Set = Set(1 << 6)
63+
6264
/** All the flags */
6365
val all: Set = Set(~0)
6466
}
@@ -164,40 +166,44 @@ object Interactive {
164166
else
165167
namedTrees(trees, include, matchSymbol(_, sym, include))
166168

167-
/** Find named trees with a non-empty position whose name contains `nameSubstring` in `trees`.
168-
*/
169-
def namedTrees(trees: List[SourceTree], nameSubstring: String)
170-
(implicit ctx: Context): List[SourceTree] = {
171-
val predicate: NameTree => Boolean = _.name.toString.contains(nameSubstring)
172-
namedTrees(trees, Include.empty, predicate)
173-
}
174-
175169
/** Find named trees with a non-empty position satisfying `treePredicate` in `trees`.
176170
*
177-
* @param includeReferences If true, include references and not just definitions
171+
* @param trees The trees to inspect.
172+
* @param include Whether to include references, definitions, etc.
173+
* @param treePredicate An additional predicate that the trees must match.
174+
* @return The trees with a non-empty position satisfying `treePredicate`.
178175
*/
179-
def namedTrees(trees: List[SourceTree], include: Include.Set, treePredicate: NameTree => Boolean)
180-
(implicit ctx: Context): List[SourceTree] = safely {
176+
def namedTrees(trees: List[SourceTree],
177+
include: Include.Set,
178+
treePredicate: NameTree => Boolean = util.common.alwaysTrue
179+
)(implicit ctx: Context): List[SourceTree] = safely {
181180
val buf = new mutable.ListBuffer[SourceTree]
182181

183182
def traverser(source: SourceFile) = {
184183
new untpd.TreeTraverser {
184+
private def handle(utree: untpd.NameTree): Unit = {
185+
val tree = utree.asInstanceOf[tpd.NameTree]
186+
if (tree.symbol.exists
187+
&& !tree.symbol.is(Synthetic)
188+
&& !tree.symbol.isPrimaryConstructor
189+
&& tree.pos.exists
190+
&& !tree.pos.isZeroExtent
191+
&& (include.isReferences || isDefinition(tree))
192+
&& treePredicate(tree))
193+
buf += SourceTree(tree, source)
194+
}
185195
override def traverse(tree: untpd.Tree)(implicit ctx: Context) = {
186196
tree match {
187197
case imp: untpd.Import if include.isImports && tree.hasType =>
188198
val tree = imp.asInstanceOf[tpd.Import]
189199
val selections = tpd.importSelections(tree)
190200
traverse(imp.expr)
191201
selections.foreach(traverse)
202+
case utree: untpd.ValOrDefDef if tree.hasType =>
203+
handle(utree)
204+
if (include.isLocal) traverseChildren(tree)
192205
case utree: untpd.NameTree if tree.hasType =>
193-
val tree = utree.asInstanceOf[tpd.NameTree]
194-
if (tree.symbol.exists
195-
&& !tree.symbol.is(Synthetic)
196-
&& tree.pos.exists
197-
&& !tree.pos.isZeroExtent
198-
&& (include.isReferences || isDefinition(tree))
199-
&& treePredicate(tree))
200-
buf += SourceTree(tree, source)
206+
handle(utree)
201207
traverseChildren(tree)
202208
case tree: untpd.Inlined =>
203209
traverse(tree.call)
@@ -228,8 +234,7 @@ object Interactive {
228234
)(implicit ctx: Context): List[SourceTree] = {
229235
val linkedSym = symbol.linkedClass
230236
val fullPredicate: NameTree => Boolean = tree =>
231-
( !tree.symbol.isPrimaryConstructor
232-
&& (includes.isDefinitions || !Interactive.isDefinition(tree))
237+
( (includes.isDefinitions || !Interactive.isDefinition(tree))
233238
&& ( Interactive.matchSymbol(tree, symbol, includes)
234239
|| ( includes.isLinkedClass
235240
&& linkedSym.exists
@@ -320,34 +325,46 @@ object Interactive {
320325
path.find(_.isInstanceOf[DefTree]).getOrElse(EmptyTree)
321326

322327
/**
323-
* Find the definitions of the symbol at the end of `path`.
328+
* Find the definitions of the symbol at the end of `path`. In the case of an import node,
329+
* all imported symbols will be considered.
324330
*
325331
* @param path The path to the symbol for which we want the definitions.
326332
* @param driver The driver responsible for `path`.
327333
* @return The definitions for the symbol at the end of `path`.
328334
*/
329-
def findDefinitions(path: List[Tree], pos: SourcePosition, driver: InteractiveDriver)(implicit ctx: Context): List[SourceTree] = {
330-
enclosingSourceSymbols(path, pos).flatMap { sym =>
331-
val enclTree = enclosingTree(path)
332-
333-
val (trees, include) =
334-
if (enclTree.isInstanceOf[MemberDef])
335-
(driver.allTreesContaining(sym.name.sourceModuleName.toString),
336-
Include.definitions | Include.overriding | Include.overridden)
337-
else sym.topLevelClass match {
338-
case cls: ClassSymbol =>
339-
val trees = Option(cls.sourceFile).flatMap(InteractiveDriver.toUriOption) match {
340-
case Some(uri) if driver.openedTrees.contains(uri) =>
341-
driver.openedTrees(uri)
342-
case _ => // Symbol comes from the classpath
343-
SourceTree.fromSymbol(cls).toList
344-
}
345-
(trees, Include.definitions | Include.overriding)
346-
case _ =>
347-
(Nil, Include.empty)
348-
}
335+
def findDefinitions(path: List[Tree], pos: SourcePosition, driver: InteractiveDriver): List[SourceTree] = {
336+
implicit val ctx = driver.currentCtx
337+
val enclTree = enclosingTree(path)
338+
val includeOverridden = enclTree.isInstanceOf[MemberDef]
339+
val symbols = enclosingSourceSymbols(path, pos)
340+
val includeExternal = symbols.exists(!_.isLocal)
341+
findDefinitions(symbols, driver, includeOverridden, includeExternal)
342+
}
349343

350-
findTreesMatching(trees, include, sym)
344+
/**
345+
* Find the definitions of `symbols`.
346+
*
347+
* @param symbols The list of symbols for which to find a definition.
348+
* @param driver The driver responsible for the given symbols.
349+
* @param includeOverridden If true, also include the symbols overridden by any of `symbols`.
350+
* @param includeExternal If true, also look for definitions on the classpath.
351+
* @return The definitions for the symbols in `symbols`, and if `includeOverridden` is set, the
352+
* definitions for the symbols that they override.
353+
*/
354+
def findDefinitions(symbols: List[Symbol],
355+
driver: InteractiveDriver,
356+
includeOverridden: Boolean,
357+
includeExternal: Boolean): List[SourceTree] = {
358+
implicit val ctx = driver.currentCtx
359+
val include = Include.definitions | Include.overriding |
360+
(if (includeOverridden) Include.overridden else Include.empty)
361+
symbols.flatMap { sym =>
362+
val name = sym.name.sourceModuleName.toString
363+
val includeLocal = if (sym.exists && sym.isLocal) Include.local else Include.empty
364+
val trees =
365+
if (includeExternal) driver.allTreesContaining(name)
366+
else driver.sourceTreesContaining(name)
367+
findTreesMatching(trees, include | includeLocal, sym)
351368
}
352369
}
353370

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
}

compiler/src/dotty/tools/dotc/tastyreflect/QuotedOpsImpl.scala

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package dotty.tools.dotc.tastyreflect
22

3-
import dotty.tools.dotc.core.Contexts.FreshContext
43
import dotty.tools.dotc.core.quoted.PickledQuotes
5-
import dotty.tools.dotc.reporting.Reporter
6-
import dotty.tools.dotc.reporting.diagnostic.MessageContainer
74

85
trait QuotedOpsImpl extends scala.tasty.reflect.QuotedOps with CoreImpl {
96

@@ -18,30 +15,17 @@ trait QuotedOpsImpl extends scala.tasty.reflect.QuotedOps with CoreImpl {
1815
def TermToQuoteDeco(term: Term): TermToQuotedAPI = new TermToQuotedAPI {
1916

2017
def seal[T: scala.quoted.Type](implicit ctx: Context): scala.quoted.Expr[T] = {
21-
typecheck(ctx)
18+
typecheck()
2219
new scala.quoted.Exprs.TastyTreeExpr(term).asInstanceOf[scala.quoted.Expr[T]]
2320
}
2421

25-
private def typecheck[T: scala.quoted.Type](ctx: Context): Unit = {
26-
implicit val ctx0: FreshContext = ctx.fresh
27-
ctx0.setTyperState(ctx0.typerState.fresh())
28-
ctx0.typerState.setReporter(new Reporter {
29-
def doReport(m: MessageContainer)(implicit ctx: Context): Unit = ()
30-
})
31-
val tp = QuotedTypeDeco(implicitly[scala.quoted.Type[T]]).unseal
32-
ctx0.typer.typed(term, tp.tpe)
33-
if (ctx0.reporter.hasErrors) {
34-
val stack = new Exception().getStackTrace
35-
def filter(elem: StackTraceElement) =
36-
elem.getClassName.startsWith("dotty.tools.dotc.tasty.ReflectionImpl") ||
37-
!elem.getClassName.startsWith("dotty.tools.dotc")
22+
private def typecheck[T: scala.quoted.Type]()(implicit ctx: Context): Unit = {
23+
val tpt = QuotedTypeDeco(implicitly[scala.quoted.Type[T]]).unseal
24+
if (!(term.tpe <:< tpt.tpe)) {
3825
throw new scala.tasty.TastyTypecheckError(
39-
s"""Error during tasty reflection while typing term
40-
|term: ${term.show}
41-
|with expected type: ${tp.tpe.show}
42-
|
43-
| ${stack.takeWhile(filter).mkString("\n ")}
44-
""".stripMargin
26+
s"""Term: ${term.show}
27+
|did not conform to type: ${tpt.tpe.show}
28+
|""".stripMargin
4529
)
4630
}
4731
}

compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,8 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers
236236
}
237237

238238
object Select extends SelectExtractor {
239-
def unapply(x: Term)(implicit ctx: Context): Option[(Term, String, Option[Signature])] = x match {
240-
case x: tpd.Select if x.isTerm =>
241-
val sig =
242-
if (x.symbol.signature == core.Signature.NotAMethod) None
243-
else Some(x.symbol.signature)
244-
Some((x.qualifier, x.name.toString, sig))
239+
def unapply(x: Term)(implicit ctx: Context): Option[(Term, String)] = x match {
240+
case x: tpd.Select if x.isTerm => Some((x.qualifier, x.name.toString))
245241
case _ => None
246242
}
247243
}
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

doc-tool/src/dotty/tools/dottydoc/DocDriver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class DocDriver extends Driver {
2727
ctx.setProperty(ContextDoc, new ContextDottydoc)
2828

2929
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
30-
(fileNames, ctx)
30+
fromTastySetup(fileNames, ctx)
3131
}
3232

3333
override def newCompiler(implicit ctx: Context): Compiler = new DocCompiler

doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ trait TypeLinker extends MemberLookup {
106106
ref.copy(left = linkReference(ent, left, packs), right = linkReference(ent, right, packs))
107107
case ref @ NamedReference(_, rf, _, _) =>
108108
ref.copy(ref = linkRef(rf))
109-
case ref @ FunctionReference(args, rv) =>
109+
case ref @ FunctionReference(args, rv, _) =>
110110
ref.copy(args = args.map(linkReference(ent, _, packs)), returnValue = linkReference(ent, rv, packs))
111111
case ref @ TupleReference(args) =>
112112
ref.copy(args = args.map(linkRef))

0 commit comments

Comments
 (0)