Skip to content

Allow completion from source #3686

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 6 commits into from
Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class Compiler {

def reset()(implicit ctx: Context): Unit = {
ctx.base.reset()
ctx.runInfo.clear()
if (ctx.run != null) ctx.run.reset()
}

def newRun(implicit ctx: Context): Run = {
Expand Down
121 changes: 74 additions & 47 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ import transform.TreeChecker
import rewrite.Rewrites
import java.io.{BufferedWriter, OutputStreamWriter}
import printing.XprintMode
import parsing.Parsers.Parser
import typer.ImplicitRunInfo
import collection.mutable

import scala.annotation.tailrec
import dotty.tools.io.VirtualFile
import scala.util.control.NonFatal

/** A compiler run. Exports various methods to compile source files */
class Run(comp: Compiler, ictx: Context) {
import Run._
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {

/** Produces the following contexts, from outermost to innermost
*
Expand All @@ -53,12 +54,49 @@ class Run(comp: Compiler, ictx: Context) {
ctx.initialize()(start) // re-initialize the base context with start
def addImport(ctx: Context, refFn: () => TermRef) =
ctx.fresh.setImportInfo(ImportInfo.rootImport(refFn)(ctx))
(start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport)
(start.setRun(this) /: defn.RootImportFns)(addImport)
}

protected[this] implicit val ctx: Context = rootContext(ictx)
private[this] var myCtx = rootContext(ictx)

/** The context created for this run */
def runContext = myCtx

protected[this] implicit def ctx: Context = myCtx
assert(ctx.runId <= Periods.MaxPossibleRunId)

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.
*/
def units: List[CompilationUnit] = myUnits

private def units_=(us: List[CompilationUnit]): Unit =
myUnits = us

/** The files currently being compiled, this may return different results over time.
* These files do not have to be source files since it's possible to compile
* from TASTY.
*/
def files: Set[AbstractFile] = {
if (myUnits ne myUnitsCached) {
myUnitsCached = myUnits
myFiles = myUnits.map(_.source.file).toSet
}
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 units, as a set */
def lateFiles: collection.Set[AbstractFile] = myLateFiles

def getSource(fileName: String): SourceFile = {
val f = new PlainFile(io.Path(fileName))
if (f.isDirectory) {
Expand All @@ -78,7 +116,7 @@ class Run(comp: Compiler, ictx: Context) {
compileSources(sources)
} catch {
case NonFatal(ex) =>
ctx.echo(i"exception occurred while compiling ${ctx.runInfo.units}%, %")
ctx.echo(i"exception occurred while compiling $units%, %")
throw ex
}

Expand All @@ -90,17 +128,17 @@ class Run(comp: Compiler, ictx: Context) {
*/
def compileSources(sources: List[SourceFile]) =
if (sources forall (_.exists)) {
ctx.runInfo.units = sources map (new CompilationUnit(_))
units = sources map (new CompilationUnit(_))
compileUnits()
}

def compileUnits(us: List[CompilationUnit]): Unit = {
ctx.runInfo.units = us
units = us
compileUnits()
}

def compileUnits(us: List[CompilationUnit], ctx: Context): Unit = {
ctx.runInfo.units = us
units = us
compileUnits()(ctx)
}

Expand All @@ -122,16 +160,16 @@ class Run(comp: Compiler, ictx: Context) {
if (phase.isRunnable)
Stats.trackTime(s"$phase ms ") {
val start = System.currentTimeMillis
ctx.runInfo.units = phase.runOn(ctx.runInfo.units)
units = phase.runOn(units)
if (ctx.settings.Xprint.value.containsPhase(phase)) {
for (unit <- ctx.runInfo.units) {
for (unit <- units) {
lastPrintedTree =
printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
}
}
ctx.informTime(s"$phase ", start)
Stats.record(s"total trees at end of $phase", ast.Trees.ntrees)
for (unit <- ctx.runInfo.units)
for (unit <- units)
Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize)
}
}
Expand All @@ -142,6 +180,22 @@ class Run(comp: Compiler, ictx: Context) {
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
}

/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
* The newly added symbols replace any previously entered symbols.
*/
def enterRoots(file: AbstractFile)(implicit ctx: Context): Unit =
if (!files.contains(file) && !lateFiles.contains(file)) {
val unit = new CompilationUnit(getSource(file.path))
myLateUnits += unit
myLateFiles += file
enterRoots(unit)(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 Expand Up @@ -180,46 +234,19 @@ class Run(comp: Compiler, ictx: Context) {
compileSources(List(new SourceFile(virtualFile, Codec.UTF8)))
}

/** The context created for this run */
def runContext = ctx

/** Print summary; return # of errors encountered */
def printSummary(): Reporter = {
ctx.runInfo.printMaxConstraint()
printMaxConstraint()
val r = ctx.reporter
r.printSummary
r
}
}

object Run {
/** Info that changes on each compiler run */
class RunInfo(initctx: Context) extends ImplicitRunInfo with ConstraintRunInfo {
implicit val ctx: Context = initctx

private[this] var myUnits: List[CompilationUnit] = _
private[this] var myUnitsCached: List[CompilationUnit] = _
private[this] var myFiles: Set[AbstractFile] = _

/** The compilation units currently being compiled, this may return different
* results over time.
*/
def units: List[CompilationUnit] = myUnits

private[Run] def units_=(us: List[CompilationUnit]): Unit =
myUnits = us


/** The files currently being compiled, this may return different results over time.
* These files do not have to be source files since it's possible to compile
* from TASTY.
*/
def files: Set[AbstractFile] = {
if (myUnits ne myUnitsCached) {
myUnitsCached = myUnits
myFiles = myUnits.map(_.source.file).toSet
}
myFiles
}

override def reset() = {
super[ImplicitRunInfo].reset()
super[ConstraintRunInfo].reset()
myCtx = null
myUnits = null
myUnitsCached = null
}
}
}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/PathResolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class PathResolver(implicit ctx: Context) {
lazy val result: ClassPath = {
val cp = AggregateClassPath(containers.toIndexedSeq)

if (settings.Ylogcp.value) {
if (settings.YlogClasspath.value) {
Console.println("Classpath built from " + settings.toConciseString(ctx.settingsState))
Console.println("Defaults: " + PathResolver.Defaults)
Console.println("Calculated: " + Calculated)
Expand Down
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class ScalaSettings extends Settings.SettingGroup {
val extdirs = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs)
val javabootclasspath = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath)
val javaextdirs = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs)
val sourcepath = PathSetting("-sourcepath", "Specify location(s) of source files.", "") // Defaults.scalaSourcePath
val sourcepath = PathSetting("-sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath)
val scansource = BooleanSetting("-scansource", "Scan source files to locate classes for which class-name != file-name")

val classpath = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp"
val outputDir = PathSetting("-d", "directory|jar", "destination for generated classfiles.", ".")
val priorityclasspath = PathSetting("-priorityclasspath", "class path that takes precedence over all other paths (or testing only)", "")
Expand Down Expand Up @@ -80,7 +82,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YtermConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val Ylog = PhasesSetting("-Ylog", "Log operations during")
val YemitTasty = BooleanSetting("-Yemit-tasty", "Generate tasty in separate *.tasty file.")
val Ylogcp = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val YlogClasspath = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val YdisableFlatCpCaching = BooleanSetting("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.")

val YnoImports = BooleanSetting("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.")
Expand Down Expand Up @@ -131,6 +133,7 @@ class ScalaSettings extends Settings.SettingGroup {
sys.props("user.dir")
)


val projectName = StringSetting (
"-project",
"project title",
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package dotty.tools.dotc
package core

import Contexts._
import Run.RunInfo
import config.Printers.typr

trait ConstraintRunInfo { self: RunInfo =>
trait ConstraintRunInfo { self: Run =>
private[this] var maxSize = 0
private[this] var maxConstraint: Constraint = _
def recordConstraintSize(c: Constraint, size: Int) =
Expand All @@ -15,4 +14,6 @@ trait ConstraintRunInfo { self: RunInfo =>
}
def printMaxConstraint()(implicit ctx: Context) =
if (maxSize > 0) typr.println(s"max constraint = ${maxConstraint.show}")

protected def reset() = maxConstraint = null
}
13 changes: 5 additions & 8 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import NameOps._
import Uniques._
import SymDenotations._
import Comments._
import Run.RunInfo
import util.Positions._
import ast.Trees._
import ast.untpd
Expand Down Expand Up @@ -43,7 +42,7 @@ object Contexts {
private val (settingsStateLoc, store4) = store3.newLocation[SettingsState]()
private val (freshNamesLoc, store5) = store4.newLocation[FreshNameCreator](new FreshNameCreator.Default)
private val (compilationUnitLoc, store6) = store5.newLocation[CompilationUnit]()
private val (runInfoLoc, store7) = store6.newLocation[RunInfo]()
private val (runLoc, store7) = store6.newLocation[Run]()
private val initialStore = store7

/** A context is passed basically everywhere in dotc.
Expand Down Expand Up @@ -194,8 +193,8 @@ object Contexts {
/** The current compilation unit */
def compilationUnit: CompilationUnit = store(compilationUnitLoc)

/** The current compiler-run specific Info */
def runInfo: RunInfo = store(runInfoLoc)
/** The current compiler-run */
def run: Run = store(runLoc)

/** The new implicit references that are introduced by this scope */
protected var implicitsCache: ContextualImplicits = null
Expand Down Expand Up @@ -460,7 +459,7 @@ object Contexts {
def setPrinterFn(printer: Context => Printer): this.type = updateStore(printerFnLoc, printer)
def setSettings(settingsState: SettingsState): this.type = updateStore(settingsStateLoc, settingsState)
def setCompilationUnit(compilationUnit: CompilationUnit): this.type = updateStore(compilationUnitLoc, compilationUnit)
def setRunInfo(runInfo: RunInfo): this.type = updateStore(runInfoLoc, runInfo)
def setRun(run: Run): this.type = updateStore(runLoc, run)
def setFreshNames(freshNames: FreshNameCreator): this.type = updateStore(freshNamesLoc, freshNames)

def setProperty[T](key: Key[T], value: T): this.type =
Expand Down Expand Up @@ -520,9 +519,7 @@ object Contexts {
tree = untpd.EmptyTree
typeAssigner = TypeAssigner
moreProperties = Map.empty
store = initialStore
.updated(settingsStateLoc, settings.defaultState)
.updated(runInfoLoc, new RunInfo(this))
store = initialStore.updated(settingsStateLoc, settings.defaultState)
typeComparer = new TypeComparer(this)
searchHistory = new SearchHistory(0, Map())
gadt = EmptyGADTMap
Expand Down
18 changes: 9 additions & 9 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ object Denotations {
// printPeriods(current)
this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId)
if (current.validFor.firstPhaseId >= targetId)
insertInsteadOf(current)
current.replaceWith(this)
else {
current.validFor = Period(ctx.runId, current.validFor.firstPhaseId, targetId - 1)
insertAfter(current)
Expand All @@ -950,7 +950,7 @@ object Denotations {
val current1: SingleDenotation = f(current.asSymDenotation)
if (current1 ne current) {
current1.validFor = current.validFor
current1.insertInsteadOf(current)
current.replaceWith(current1)
}
hasNext = current1.nextInRun.validFor.code > current1.validFor.code
current = current1.nextInRun
Expand All @@ -972,14 +972,14 @@ object Denotations {
* The code to achieve this is subtle in that it works correctly
* whether the replaced denotation is the only one in its cycle or not.
*/
private def insertInsteadOf(old: SingleDenotation): Unit = {
var prev = old
while (prev.nextInRun ne old) prev = prev.nextInRun
private[dotc] def replaceWith(newd: SingleDenotation): Unit = {
var prev = this
while (prev.nextInRun ne this) prev = prev.nextInRun
// order of next two assignments is important!
prev.nextInRun = this
this.nextInRun = old.nextInRun
old.validFor = Nowhere
old.nextInRun = this
prev.nextInRun = newd
newd.nextInRun = nextInRun
validFor = Nowhere
nextInRun = newd
}

def staleSymbolError(implicit ctx: Context) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ object OrderingConstraint {
private def newConstraint(boundsMap: ParamBounds, lowerMap: ParamOrdering, upperMap: ParamOrdering)(implicit ctx: Context) : OrderingConstraint = {
val result = new OrderingConstraint(boundsMap, lowerMap, upperMap)
if (Config.checkConstraintsNonCyclic) result.checkNonCyclic()
ctx.runInfo.recordConstraintSize(result, result.boundsMap.size)
ctx.run.recordConstraintSize(result, result.boundsMap.size)
result
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ object SymDenotations {
final def privateWithin(implicit ctx: Context): Symbol = { ensureCompleted(); myPrivateWithin }

/** Set privateWithin. */
protected[core] final def privateWithin_=(sym: Symbol): Unit =
protected[dotc] final def privateWithin_=(sym: Symbol): Unit =
myPrivateWithin = sym

/** The annotations of this denotation */
Expand Down
Loading