aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2016-02-05 00:34:02 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-02-05 00:34:02 +0100
commit9d8c92d1d52fcfa95d57ce88d91dbb84c8ecfbd1 (patch)
tree83b51507c3548d95a02840b83d530e3b6c700e0f
parent93dd1cf1fdbf56ca3c153aa5a25fb4c48782acf5 (diff)
parent7eba7f7a6778cc0ddfb2ce81dee64dd4fa23490a (diff)
downloaddotty-9d8c92d1d52fcfa95d57ce88d91dbb84c8ecfbd1.tar.gz
dotty-9d8c92d1d52fcfa95d57ce88d91dbb84c8ecfbd1.tar.bz2
dotty-9d8c92d1d52fcfa95d57ce88d91dbb84c8ecfbd1.zip
Merge pull request #1052 from smarter/fix/driver-api
Improve and document the Driver#process API, fix partest logging
-rw-r--r--src/dotty/tools/dotc/Compiler.scala4
-rw-r--r--src/dotty/tools/dotc/CompilerCallback.scala2
-rw-r--r--src/dotty/tools/dotc/Driver.scala68
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala24
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala2
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala21
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala3
-rw-r--r--test/dotty/partest/DPDirectCompiler.scala18
-rw-r--r--test/test/CompilerTest.scala4
-rw-r--r--test/test/DottyTest.scala11
10 files changed, 86 insertions, 71 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 42d223fe9..199657864 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -111,15 +111,13 @@ class Compiler {
.setOwner(defn.RootClass)
.setTyper(new Typer)
.setMode(Mode.ImplicitsEnabled)
- .setTyperState(new MutableTyperState(ctx.typerState, rootReporter(ctx), isCommittable = true))
+ .setTyperState(new MutableTyperState(ctx.typerState, ctx.typerState.reporter, isCommittable = true))
ctx.definitions.init(start) // set context of definitions to start
def addImport(ctx: Context, refFn: () => TermRef) =
ctx.fresh.setImportInfo(ImportInfo.rootImport(refFn)(ctx))
(start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport)
}
- protected def rootReporter(implicit ctx: Context): Reporter = new ConsoleReporter()(ctx)
-
def reset()(implicit ctx: Context): Unit = {
ctx.base.reset()
ctx.runInfo.clear()
diff --git a/src/dotty/tools/dotc/CompilerCallback.scala b/src/dotty/tools/dotc/CompilerCallback.scala
index 98e8e2713..e2f56430b 100644
--- a/src/dotty/tools/dotc/CompilerCallback.scala
+++ b/src/dotty/tools/dotc/CompilerCallback.scala
@@ -18,7 +18,7 @@ import java.io.File
* }
* dotty.tools.dotc.process(args, callback)
* // Or, if you have a custom root context `rootCtx`:
- * dotty.tools.dotc.process(args, rootCtx.setCompilerCallback(callback))
+ * dotty.tools.dotc.process(args, rootCtx.fresh.setCompilerCallback(callback))
* }}}
*/
trait CompilerCallback {
diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala
index 1627b6e48..7f22fc774 100644
--- a/src/dotty/tools/dotc/Driver.scala
+++ b/src/dotty/tools/dotc/Driver.scala
@@ -33,28 +33,64 @@ abstract class Driver extends DotClass {
protected def sourcesRequired = true
def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
- val summary = CompilerCommand.distill(args)(rootCtx)
- // FIXME: We should reuse rootCtx instead of creating newCtx, but this
- // makes some tests fail with "denotation module _root_ invalid in run 2."
- val newCtx = initCtx.setCompilerCallback(rootCtx.compilerCallback)
- implicit val ctx: Context = newCtx.fresh.setSettings(summary.sstate)
- val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
+ val ctx = rootCtx.fresh
+ val summary = CompilerCommand.distill(args)(ctx)
+ ctx.setSettings(summary.sstate)
+ val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
(fileNames, ctx)
}
- def process(args: Array[String], rootCtx: Context): Reporter = {
- val (fileNames, ctx) = setup(args, rootCtx)
- doCompile(newCompiler(), fileNames)(ctx)
- }
- def process(args: Array[String], callback: CompilerCallback): Reporter = {
- process(args, initCtx.setCompilerCallback(callback))
+ /** Principal entry point to the compiler.
+ * Creates a new compiler instance and run it with arguments `args`.
+ *
+ * The optional arguments of this method all have `null` as their default
+ * value, this makes it easier to call this method by reflection or from Java.
+ *
+ * @param args Arguments to pass to the compiler.
+ * @param reporter Used to log errors, warnings, and info messages.
+ * The default reporter is used if this is `null`.
+ * @param callback Used to execute custom code during the compilation
+ * process. No callbacks will be executed if this is `null`.
+ * @return The `Reporter` used. Use `Reporter#hasErrors` to check
+ * if compilation succeeded.
+ */
+ final def process(args: Array[String], reporter: Reporter = null,
+ callback: CompilerCallback = null): Reporter = {
+ val ctx = initCtx.fresh
+ if (reporter != null)
+ ctx.setReporter(reporter)
+ if (callback != null)
+ ctx.setCompilerCallback(callback)
+ process(args, ctx)
}
- // We overload `process` instead of using a default argument so that we
- // can easily call this method using reflection from `RawCompiler` in sbt.
- def process(args: Array[String]): Reporter = {
- process(args, initCtx)
+ /** Entry point to the compiler with no optional arguments.
+ *
+ * This overload is provided for compatibility reasons: the
+ * `RawCompiler` of sbt expects this method to exist and calls
+ * it using reflection. Keeping it means that we can change
+ * the other overloads without worrying about breaking compatibility
+ * with sbt.
+ */
+ final def process(args: Array[String]): Reporter =
+ process(args, null, null)
+
+ /** Entry point to the compiler using a custom `Context`.
+ *
+ * In most cases, you do not need a custom `Context` and should
+ * instead use one of the other overloads of `process`. However,
+ * the other overloads cannot be overriden, instead you
+ * should override this one which they call internally.
+ *
+ * @param args Arguments to pass to the compiler.
+ * @param rootCtx The root Context to use.
+ * @return The `Reporter` used. Use `Reporter#hasErrors` to check
+ * if compilation succeeded.
+ */
+ def process(args: Array[String], rootCtx: Context): Reporter = {
+ val (fileNames, ctx) = setup(args, rootCtx)
+ doCompile(newCompiler(), fileNames)(ctx)
}
def main(args: Array[String]): Unit = {
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index ae221cc3e..b205a40f0 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -72,22 +72,16 @@ object Contexts {
def next = { val c = current; current = current.outer; c }
}
- /** Set the compiler callback, shared by all contexts with the same `base` */
- def setCompilerCallback(callback: CompilerCallback): this.type = {
- base.compilerCallback = callback; this
- }
-
/** The outer context */
private[this] var _outer: Context = _
protected def outer_=(outer: Context) = _outer = outer
def outer: Context = _outer
- // protected def compilerCallback_=(callback: CompilerCallback) =
- // _compilerCallback = callback
- // def compilerCallback: CompilerCallback = _compilerCallback
- // def setCompilerCallback(callback: CompilerCallback): this.type = {
- // this.compilerCallback = callback; this
- // }
+ /** The compiler callback implementation, or null if no callback will be called. */
+ private[this] var _compilerCallback: CompilerCallback = _
+ protected def compilerCallback_=(callback: CompilerCallback) =
+ _compilerCallback = callback
+ def compilerCallback: CompilerCallback = _compilerCallback
/** The current context */
private[this] var _period: Period = _
@@ -426,7 +420,9 @@ object Contexts {
abstract class FreshContext extends Context {
def setPeriod(period: Period): this.type = { this.period = period; this }
def setMode(mode: Mode): this.type = { this.mode = mode; this }
+ def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
+ def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
@@ -481,7 +477,7 @@ object Contexts {
outer = NoContext
period = InitialPeriod
mode = Mode.None
- typerState = new TyperState(new ThrowingReporter(new ConsoleReporter()(this)))
+ typerState = new TyperState(new ConsoleReporter())
printerFn = new RefinedPrinter(_)
owner = NoSymbol
sstate = settings.defaultState
@@ -536,10 +532,6 @@ object Contexts {
/** The essential mutable state of a context base, collected into a common class */
class ContextState {
-
- /** The compiler callback implementation, or null if unset */
- var compilerCallback: CompilerCallback = _
-
// Symbols state
/** A counter for unique ids */
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
index 45268b673..e9b9964c3 100644
--- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -15,7 +15,7 @@ import scala.reflect.internal.util._
*/
class ConsoleReporter(
reader: BufferedReader = Console.in,
- writer: PrintWriter = new PrintWriter(Console.err, true))(ctx: Context)
+ writer: PrintWriter = new PrintWriter(Console.err, true))
extends Reporter with UniqueMessagePositions {
/** maximal number of error messages to be printed */
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index f98d85ce9..5ed7360da 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -247,12 +247,23 @@ abstract class Reporter {
incompleteHandler(d)(ctx)
- /** Print a summary */
- def printSummary(implicit ctx: Context): Unit = {
- if (warningCount > 0) ctx.println(countString(warningCount, "warning") + " found")
- if (errorCount > 0) ctx.println(countString(errorCount, "error") + " found")
+ /** Summary of warnings and errors */
+ def summary: String = {
+ val b = new mutable.ListBuffer[String]
+ if (warningCount > 0)
+ b += countString(warningCount, "warning") + " found"
+ if (errorCount > 0)
+ b += countString(errorCount, "error") + " found"
for ((settingName, count) <- unreportedWarnings)
- ctx.println(s"there were $count ${settingName.tail} warning(s); re-run with $settingName for details")
+ b += s"there were $count ${settingName.tail} warning(s); re-run with $settingName for details"
+ b.mkString("\n")
+ }
+
+ /** Print the summary of warnings and errors */
+ def printSummary(implicit ctx: Context): Unit = {
+ val s = summary
+ if (s != "")
+ ctx.println(s)
}
/** Returns a string meaning "n elements". */
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index daf76f471..150a632a1 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -118,8 +118,7 @@ class TreeChecker extends Phase with SymTransformer {
val prevPhase = ctx.phase.prev // can be a mini-phase
val squahsedPhase = ctx.squashed(prevPhase)
ctx.println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")
- val checkingCtx = ctx.fresh
- .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.reporter)))
+ val checkingCtx = ctx.fresh.setReporter(new ThrowingReporter(ctx.reporter))
val checker = new Checker(previousPhases(phasesToRun.toList)(ctx))
try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx)
catch {
diff --git a/test/dotty/partest/DPDirectCompiler.scala b/test/dotty/partest/DPDirectCompiler.scala
index ca56ac3e9..410dac338 100644
--- a/test/dotty/partest/DPDirectCompiler.scala
+++ b/test/dotty/partest/DPDirectCompiler.scala
@@ -5,7 +5,7 @@ import scala.tools.partest.{ TestState, nest }
import java.io.{ File, PrintWriter, FileWriter }
-/* NOTE: Adapted from partest.DirectCompiler and DottyTest */
+/* NOTE: Adapted from partest.DirectCompiler */
class DPDirectCompiler(runner: DPTestRunner) extends nest.DirectCompiler(runner) {
override def compile(opts0: List[String], sources: List[File]): TestState = {
@@ -13,24 +13,14 @@ class DPDirectCompiler(runner: DPTestRunner) extends nest.DirectCompiler(runner)
val clogWriter = new PrintWriter(clogFWriter, true)
clogWriter.println("\ncompiling " + sources.mkString(" ") + "\noptions: " + opts0.mkString(" "))
- implicit val ctx: dotty.tools.dotc.core.Contexts.Context = {
- val base = new dotty.tools.dotc.core.Contexts.ContextBase
- import base.settings._
- val ctx = base.initialCtx.fresh.setSetting(printtypes, true)
- .setSetting(pageWidth, 90).setSetting(log, List("<some"))
- base.definitions.init(ctx)
- ctx
- }
-
try {
val processor =
if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main
- val clogger = new ConsoleReporter(writer = clogWriter)(ctx)
- val logCtx = ctx.fresh.setTyperState(ctx.typerState.withReporter(clogger))
- val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, logCtx)
+ val clogger = new ConsoleReporter(writer = clogWriter)
+ val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, clogger)
if (!reporter.hasErrors) runner.genPass()
else {
- reporter.printSummary(ctx)
+ clogWriter.println(reporter.summary)
runner.genFail(s"compilation failed with ${reporter.errorCount} errors")
}
} catch {
diff --git a/test/test/CompilerTest.scala b/test/test/CompilerTest.scala
index c65710e7d..526392576 100644
--- a/test/test/CompilerTest.scala
+++ b/test/test/CompilerTest.scala
@@ -33,7 +33,7 @@ import org.junit.Test
* object Test { def main(args: Array[String]): Unit = ... }
* Classpath jars can be added to partestDeps in the sbt Build.scala.
*/
-abstract class CompilerTest extends DottyTest {
+abstract class CompilerTest {
/** Override with output dir of test so it can be patched. Partest expects
* classes to be in partest-generated/[kind]/[testname]-[kind].obj/ */
@@ -181,7 +181,7 @@ abstract class CompilerTest extends DottyTest {
private def compileArgs(args: Array[String], xerrors: Int = 0)(implicit defaultOptions: List[String]): Unit = {
val allArgs = args ++ defaultOptions
val processor = if (allArgs.exists(_.startsWith("#"))) Bench else Main
- val nerrors = processor.process(allArgs, ctx).errorCount
+ val nerrors = processor.process(allArgs).errorCount
assert(nerrors == xerrors, s"Wrong # of errors. Expected: $xerrors, found: $nerrors")
}
diff --git a/test/test/DottyTest.scala b/test/test/DottyTest.scala
index fc9cff782..4664605d1 100644
--- a/test/test/DottyTest.scala
+++ b/test/test/DottyTest.scala
@@ -22,17 +22,6 @@ class DottyTest /*extends ContextEscapeDetection*/ {
val base = new ContextBase
import base.settings._
val ctx = base.initialCtx.fresh
- //.setSetting(verbose, true)
- // .withSetting(debug, true)
- // .withSetting(debugTrace, true)
- // .withSetting(prompt, true)
- //.setSetting(Ylogcp, true)
- //.setSetting(printtypes, true)
- .setSetting(pageWidth, 90)
- .setSetting(log, List("<some"))
- // .withTyperState(new TyperState(new ConsoleReporter()(base.initialCtx)))
-
- // .withSetting(uniqid, true)
base.definitions.init(ctx)
ctx
}