Skip to content

Add sourcepath to IDE setup #3949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5a94139
Add sourcepath to IDE setup
odersky Jan 30, 2018
b27cf86
Turn -scansource on for IDE
odersky Jan 30, 2018
cdbea55
Refactor ClassSymbol#tree
odersky Jan 31, 2018
940ab24
Fix link and tasty tests
odersky Jan 31, 2018
dd8ad5c
Refactoring: Move stuff from DottyUnpickler to TreeProvider
odersky Jan 31, 2018
b615dc1
Disable more from tasty tests
odersky Jan 31, 2018
dedaeac
Allow symbols to be loaded from source in IDE
odersky Feb 1, 2018
c863922
Fix computation of moduleClass
odersky Feb 1, 2018
ef0473c
Re-enable FromTasty test
odersky Feb 1, 2018
83ccf31
Disable more tasty tests
odersky Feb 1, 2018
a72b577
Disable one more from tasty test.
odersky Feb 1, 2018
de4f83f
Drop lateUnits
odersky Feb 1, 2018
cb86aa4
Disable yet another fromTasty cmd test
odersky Feb 1, 2018
b6b09cc
Make findReferences more robust and faster
odersky Feb 1, 2018
e407c29
Disable even more cmd tests
odersky Feb 1, 2018
82d25a0
Cache identifier search in trees
odersky Feb 1, 2018
5bc01c2
Delete unused method
odersky Feb 1, 2018
1d5909e
Refine bringForward to work with overloaded symbols
odersky Feb 2, 2018
f00a9ec
Fix spelling of includeOverridden
odersky Feb 2, 2018
78ee30d
Compute trees from sources in compilation unit used for entering symbols
odersky Feb 2, 2018
ed4db4a
Rewrite matchSymbol
odersky Feb 2, 2018
3d6a126
Don't use matchSymbol in SourceTree
odersky Feb 2, 2018
00e90a2
Don't force annotations on cleanup
odersky Feb 2, 2018
6ea77cd
Redo scheme for typing late-loaded units
odersky Feb 2, 2018
81a843d
Fix findReferences for modules
odersky Feb 2, 2018
6129cc0
Bring matchSymbol in line with sourceSymbol
odersky Feb 2, 2018
3a1d7fa
Polishings
odersky Feb 2, 2018
bde4dd7
Fix namedTrees traversal of Inline nodes
odersky Feb 2, 2018
d5bb17f
Make sure typer is a Typer
odersky Feb 2, 2018
0232252
Add navigation to overridden symbols
odersky Feb 2, 2018
4cfb00f
Refactor completions
odersky Feb 2, 2018
cdb202d
Only collect simple names when reading unpickler name tables
odersky Feb 3, 2018
9f4dac2
Collect references as well as definitions for computing ids of a tree
odersky Feb 3, 2018
7d86966
Maintain compilationUnits mapping
odersky Feb 4, 2018
9747f6b
Centralize methods for local context creation
odersky Feb 4, 2018
5d3b040
Redo completions
odersky Feb 4, 2018
518e9fd
Improve completion
odersky Feb 4, 2018
d93a8eb
Consider implicit conversions for possible completions
odersky Feb 4, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -896,8 +896,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma

def decls: List[Symbol] = tp.decls.toList

def members: List[Symbol] =
tp.memberDenots(takeAllFilter, (name, buf) => buf ++= tp.member(name).alternatives).map(_.symbol).toList
def members: List[Symbol] = tp.allMembers.map(_.symbol).toList

def typeSymbol: Symbol = tp.widenDealias.typeSymbol

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object CompilationUnit {
def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit =
mkCompilationUnit(new SourceFile(clsd.symbol.associatedFile, Seq()), unpickled, forceTrees)

/** Make a compilation unit the given unpickled tree */
/** Make a compilation unit, given picked bytes and unpickled tree */
def mkCompilationUnit(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
assert(!unpickled.isEmpty, unpickled)
val unit1 = new CompilationUnit(source)
Expand Down
38 changes: 23 additions & 15 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
(start.setRun(this) /: defn.RootImportFns)(addImport)
}

private[this] var compiling = false

private[this] var myCtx = rootContext(ictx)

/** The context created for this run */
Expand All @@ -72,8 +74,6 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
private[this] var myUnits: List[CompilationUnit] = _
private[this] var myUnitsCached: List[CompilationUnit] = _
private[this] var myFiles: Set[AbstractFile] = _
private[this] val myLateUnits = mutable.ListBuffer[CompilationUnit]()
private[this] var myLateFiles = mutable.Set[AbstractFile]()

/** The compilation units currently being compiled, this may return different
* results over time.
Expand All @@ -95,11 +95,11 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
myFiles
}

/** Units that are added from source completers but that are not compiled in current run. */
def lateUnits: List[CompilationUnit] = myLateUnits.toList
/** The source files of all late entered symbols, as a set */
private[this] var lateFiles = mutable.Set[AbstractFile]()

/** The source files of all late units, as a set */
def lateFiles: collection.Set[AbstractFile] = myLateFiles
/** Actions that need to be performed at the end of the current compilation run */
private[this] var finalizeActions = mutable.ListBuffer[() => Unit]()

def getSource(fileName: String): SourceFile = {
val f = new PlainFile(io.Path(fileName))
Expand Down Expand Up @@ -148,6 +148,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint

protected def compileUnits()(implicit ctx: Context) = Stats.maybeMonitored {
ctx.checkSingleThreaded()
compiling = true

// If testing pickler, make sure to stop after pickling phase:
val stopAfter =
Expand Down Expand Up @@ -189,24 +190,31 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
ctx.phases.foreach(_.initContext(runCtx))
runPhases(runCtx)
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
while (finalizeActions.nonEmpty) {
val action = finalizeActions.remove(0)
action()
}
compiling = false
}

/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
* The newly added symbols replace any previously entered symbols.
* If `typeCheck = true`, also run typer on the compilation unit.
*/
def enterRoots(file: AbstractFile)(implicit ctx: Context): Unit =
def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit =
if (!files.contains(file) && !lateFiles.contains(file)) {
lateFiles += file
val unit = new CompilationUnit(getSource(file.path))
myLateUnits += unit
myLateFiles += file
enterRoots(unit)(runContext.fresh.setCompilationUnit(unit))
def process()(implicit ctx: Context) = {
unit.untpdTree = new Parser(unit.source).parse()
ctx.typer.lateEnter(unit.untpdTree)
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
if (typeCheck)
if (compiling) finalizeActions += (() => typeCheckUnit()) else typeCheckUnit()
}
process()(runContext.fresh.setCompilationUnit(unit))
}

private def enterRoots(unit: CompilationUnit)(implicit ctx: Context): Unit = {
unit.untpdTree = new Parser(unit.source).parse()
ctx.typer.lateEnter(unit.untpdTree)
}

private sealed trait PrintedTree
private /*final*/ case class SomePrintedTree(phase: String, tree: String) extends PrintedTree
private object NoPrintedTree extends PrintedTree
Expand Down
21 changes: 21 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,27 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def tpes: List[Type] = xs map (_.tpe)
}

/** A trait for loaders that compute trees. Currently implemented just by DottyUnpickler. */
trait TreeProvider {
protected def computeTrees(implicit ctx: Context): List[Tree]

private[this] var myTrees: List[Tree] = null

/** Get trees defined by this provider. Cache them if -Yretain-trees is set. */
def trees(implicit ctx: Context): List[Tree] =
if (ctx.settings.YretainTrees.value) {
if (myTrees == null) myTrees = computeTrees
myTrees
} else computeTrees

/** Get first tree defined by this provider, or EmptyTree if none exists */
def tree(implicit ctx: Context): Tree =
trees.headOption.getOrElse(EmptyTree)

/** Is it possible that the tree to load contains a definition of or reference to `id`? */
def mightContain(id: String)(implicit ctx: Context) = true
}

// convert a numeric with a toXXX method
def primitiveConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = {
val mname = ("to" + numericCls.name).toTermName
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ object Printers {
val cyclicErrors: Printer = noPrinter
val dottydoc: Printer = noPrinter
val exhaustivity: Printer = noPrinter
val incremental: Printer = noPrinter
val gadts: Printer = noPrinter
val hk: Printer = noPrinter
val implicits: Printer = noPrinter
val implicitsDetailed: Printer = noPrinter
val inlining: Printer = noPrinter
val interactiv: Printer = new Printer
val overload: Printer = noPrinter
val patmatch: Printer = noPrinter
val pickling: Printer = noPrinter
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,29 @@ object Annotations {

abstract class Annotation {
def tree(implicit ctx: Context): Tree

def symbol(implicit ctx: Context): Symbol =
if (tree.symbol.isConstructor) tree.symbol.owner
else tree.tpe.typeSymbol

def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.derivesFrom(cls)

def appliesToModule: Boolean = true // for now; see remark in SymDenotations

def derivedAnnotation(tree: Tree)(implicit ctx: Context) =
if (tree eq this.tree) this else Annotation(tree)

def arguments(implicit ctx: Context) = ast.tpd.arguments(tree)

def argument(i: Int)(implicit ctx: Context): Option[Tree] = {
val args = arguments
if (i < args.length) Some(args(i)) else None
}
def argumentConstant(i: Int)(implicit ctx: Context): Option[Constant] =
for (ConstantType(c) <- argument(i) map (_.tpe)) yield c

def isEvaluated: Boolean = true

def ensureCompleted(implicit ctx: Context): Unit = tree
}

Expand All @@ -43,6 +49,8 @@ object Annotations {
if (myTree == null) myTree = complete(ctx)
myTree
}

override def isEvaluated = myTree != null
}

/** An annotation indicating the body of a right-hand side,
Expand Down Expand Up @@ -73,7 +81,7 @@ object Annotations {
}
myBody
}
def isEvaluated = evaluated
override def isEvaluated = evaluated
}

object Annotation {
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ object Contexts {
private[this] var _typeAssigner: TypeAssigner = _
protected def typeAssigner_=(typeAssigner: TypeAssigner) = _typeAssigner = typeAssigner
def typeAssigner: TypeAssigner = _typeAssigner
def typer: Typer = _typeAssigner.asInstanceOf[Typer]

/** The currently active import info */
private[this] var _importInfo: ImportInfo = _
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -201,5 +201,9 @@ object Decorators {
def hl(args: Any*)(implicit ctx: Context): String =
new SyntaxFormatter(sc).assemble(args).stripMargin
}

implicit class ArrayInterpolator[T <: AnyRef](val arr: Array[T]) extends AnyVal {
def binarySearch(x: T): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object]], x)
}
}

5 changes: 1 addition & 4 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -789,10 +789,7 @@ object Denotations {
this match {
case symd: SymDenotation =>
if (ctx.stillValid(symd)) return updateValidity()
if (ctx.acceptStale(symd)) {
val newd = symd.owner.info.decls.lookup(symd.name)
return (newd.denot: SingleDenotation).orElse(symd).updateValidity()
}
if (ctx.acceptStale(symd)) return symd.currentSymbol.denot.orElse(symd).updateValidity()
case _ =>
}
if (!symbol.exists) return updateValidity()
Expand Down
21 changes: 18 additions & 3 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import util.SimpleIdentityMap
import util.Stats
import java.util.WeakHashMap
import config.Config
import config.Printers.{incremental, noPrinter}
import config.Printers.noPrinter
import reporting.diagnostic.Message
import reporting.diagnostic.messages.BadSymbolicReference
import reporting.trace
Expand Down Expand Up @@ -206,7 +206,7 @@ object SymDenotations {
* Uncompleted denotations set myInfo to a LazyType.
*/
final def info(implicit ctx: Context): Type = {
def completeInfo = {
def completeInfo = { // Written this way so that `info` is small enough to be inlined
completeFrom(myInfo.asInstanceOf[LazyType]); info
}
if (myInfo.isInstanceOf[LazyType]) completeInfo else myInfo
Expand Down Expand Up @@ -959,7 +959,6 @@ object SymDenotations {
}
}


/** The class with the same (type-) name as this module or module class,
* and which is also defined in the same scope and compilation unit.
* NoSymbol if this class does not exist.
Expand Down Expand Up @@ -1135,6 +1134,22 @@ object SymDenotations {
/** The primary constructor of a class or trait, NoSymbol if not applicable. */
def primaryConstructor(implicit ctx: Context): Symbol = NoSymbol

/** The current declaration in this symbol's class owner that has the same name
* as this one, and, if there are several, also has the same signature.
*/
def currentSymbol(implicit ctx: Context): Symbol = {
val candidates = owner.info.decls.lookupAll(name)
def test(sym: Symbol): Symbol =
if (sym == symbol || sym.signature == signature) sym
else if (candidates.hasNext) test(candidates.next)
else NoSymbol
if (candidates.hasNext) {
val sym = candidates.next
if (candidates.hasNext) test(sym) else sym
}
else NoSymbol
}

// ----- type-related ------------------------------------------------

/** The type parameters of a class symbol, Nil for all other symbols */
Expand Down
28 changes: 16 additions & 12 deletions compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import util.Stats
import Decorators._
import scala.util.control.NonFatal
import ast.Trees._
import ast.tpd
import parsing.Parsers.OutlineParser
import reporting.trace

Expand Down Expand Up @@ -118,7 +119,9 @@ class SymbolLoaders {
scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {

val completer = new SourcefileLoader(src)
if (ctx.settings.scansource.value) {
if (ctx.settings.scansource.value && ctx.run != null) {
System.out.print(i"scanning $src ...")
System.out.flush()
if (src.exists && !src.isDirectory) {
val filePath = owner.ownersIterator.takeWhile(!_.isRoot).map(_.name.toTermName).toList

Expand Down Expand Up @@ -160,6 +163,7 @@ class SymbolLoaders {

val unit = new CompilationUnit(ctx.run.getSource(src.path))
enterScanned(unit)(ctx.run.runContext.fresh.setCompilationUnit(unit))
System.out.println(" done")
}
}
else enterClassAndModule(owner, name, completer, scope = scope)
Expand Down Expand Up @@ -338,15 +342,8 @@ abstract class SymbolLoader extends LazyType {
postProcess(root.scalacLinkedClass.denot)
}
}
}

class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {

override def sourceFileOrNull: AbstractFile = classfile

def description(implicit ctx: Context) = "class file " + classfile.toString

def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
protected def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
val linkedDenot = rootDenot.scalacLinkedClass.denot match {
case d: ClassDenotation => d
case d =>
Expand All @@ -368,6 +365,13 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
if (rootDenot is ModuleClass) (linkedDenot, rootDenot)
else (rootDenot, linkedDenot)
}
}

class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {

override def sourceFileOrNull: AbstractFile = classfile

def description(implicit ctx: Context) = "class file " + classfile.toString

override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
load(root)
Expand All @@ -379,8 +383,8 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
if (mayLoadTreesFromTasty) {
result match {
case Some(unpickler: tasty.DottyUnpickler) =>
classRoot.symbol.asClass.unpickler = unpickler
moduleRoot.symbol.asClass.unpickler = unpickler
classRoot.classSymbol.treeOrProvider = unpickler
moduleRoot.classSymbol.treeOrProvider = unpickler
case _ =>
}
}
Expand All @@ -394,5 +398,5 @@ class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
def description(implicit ctx: Context) = "source file " + srcfile.toString
override def sourceFileOrNull = srcfile
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
ctx.run.enterRoots(srcfile)
ctx.run.lateCompile(srcfile, typeCheck = ctx.settings.YretainTrees.value)
}
Loading