Skip to content

Commit 9d8c92d

Browse files
committed
Merge pull request #1052 from smarter/fix/driver-api
Improve and document the Driver#process API, fix partest logging
2 parents 93dd1cf + 7eba7f7 commit 9d8c92d

File tree

10 files changed

+86
-71
lines changed

10 files changed

+86
-71
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,13 @@ class Compiler {
111111
.setOwner(defn.RootClass)
112112
.setTyper(new Typer)
113113
.setMode(Mode.ImplicitsEnabled)
114-
.setTyperState(new MutableTyperState(ctx.typerState, rootReporter(ctx), isCommittable = true))
114+
.setTyperState(new MutableTyperState(ctx.typerState, ctx.typerState.reporter, isCommittable = true))
115115
ctx.definitions.init(start) // set context of definitions to start
116116
def addImport(ctx: Context, refFn: () => TermRef) =
117117
ctx.fresh.setImportInfo(ImportInfo.rootImport(refFn)(ctx))
118118
(start.setRunInfo(new RunInfo(start)) /: defn.RootImportFns)(addImport)
119119
}
120120

121-
protected def rootReporter(implicit ctx: Context): Reporter = new ConsoleReporter()(ctx)
122-
123121
def reset()(implicit ctx: Context): Unit = {
124122
ctx.base.reset()
125123
ctx.runInfo.clear()

src/dotty/tools/dotc/CompilerCallback.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import java.io.File
1818
* }
1919
* dotty.tools.dotc.process(args, callback)
2020
* // Or, if you have a custom root context `rootCtx`:
21-
* dotty.tools.dotc.process(args, rootCtx.setCompilerCallback(callback))
21+
* dotty.tools.dotc.process(args, rootCtx.fresh.setCompilerCallback(callback))
2222
* }}}
2323
*/
2424
trait CompilerCallback {

src/dotty/tools/dotc/Driver.scala

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,64 @@ abstract class Driver extends DotClass {
3333
protected def sourcesRequired = true
3434

3535
def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
36-
val summary = CompilerCommand.distill(args)(rootCtx)
37-
// FIXME: We should reuse rootCtx instead of creating newCtx, but this
38-
// makes some tests fail with "denotation module _root_ invalid in run 2."
39-
val newCtx = initCtx.setCompilerCallback(rootCtx.compilerCallback)
40-
implicit val ctx: Context = newCtx.fresh.setSettings(summary.sstate)
41-
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
36+
val ctx = rootCtx.fresh
37+
val summary = CompilerCommand.distill(args)(ctx)
38+
ctx.setSettings(summary.sstate)
39+
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
4240
(fileNames, ctx)
4341
}
4442

45-
def process(args: Array[String], rootCtx: Context): Reporter = {
46-
val (fileNames, ctx) = setup(args, rootCtx)
47-
doCompile(newCompiler(), fileNames)(ctx)
48-
}
4943

50-
def process(args: Array[String], callback: CompilerCallback): Reporter = {
51-
process(args, initCtx.setCompilerCallback(callback))
44+
/** Principal entry point to the compiler.
45+
* Creates a new compiler instance and run it with arguments `args`.
46+
*
47+
* The optional arguments of this method all have `null` as their default
48+
* value, this makes it easier to call this method by reflection or from Java.
49+
*
50+
* @param args Arguments to pass to the compiler.
51+
* @param reporter Used to log errors, warnings, and info messages.
52+
* The default reporter is used if this is `null`.
53+
* @param callback Used to execute custom code during the compilation
54+
* process. No callbacks will be executed if this is `null`.
55+
* @return The `Reporter` used. Use `Reporter#hasErrors` to check
56+
* if compilation succeeded.
57+
*/
58+
final def process(args: Array[String], reporter: Reporter = null,
59+
callback: CompilerCallback = null): Reporter = {
60+
val ctx = initCtx.fresh
61+
if (reporter != null)
62+
ctx.setReporter(reporter)
63+
if (callback != null)
64+
ctx.setCompilerCallback(callback)
65+
process(args, ctx)
5266
}
5367

54-
// We overload `process` instead of using a default argument so that we
55-
// can easily call this method using reflection from `RawCompiler` in sbt.
56-
def process(args: Array[String]): Reporter = {
57-
process(args, initCtx)
68+
/** Entry point to the compiler with no optional arguments.
69+
*
70+
* This overload is provided for compatibility reasons: the
71+
* `RawCompiler` of sbt expects this method to exist and calls
72+
* it using reflection. Keeping it means that we can change
73+
* the other overloads without worrying about breaking compatibility
74+
* with sbt.
75+
*/
76+
final def process(args: Array[String]): Reporter =
77+
process(args, null, null)
78+
79+
/** Entry point to the compiler using a custom `Context`.
80+
*
81+
* In most cases, you do not need a custom `Context` and should
82+
* instead use one of the other overloads of `process`. However,
83+
* the other overloads cannot be overriden, instead you
84+
* should override this one which they call internally.
85+
*
86+
* @param args Arguments to pass to the compiler.
87+
* @param rootCtx The root Context to use.
88+
* @return The `Reporter` used. Use `Reporter#hasErrors` to check
89+
* if compilation succeeded.
90+
*/
91+
def process(args: Array[String], rootCtx: Context): Reporter = {
92+
val (fileNames, ctx) = setup(args, rootCtx)
93+
doCompile(newCompiler(), fileNames)(ctx)
5894
}
5995

6096
def main(args: Array[String]): Unit = {

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,16 @@ object Contexts {
7272
def next = { val c = current; current = current.outer; c }
7373
}
7474

75-
/** Set the compiler callback, shared by all contexts with the same `base` */
76-
def setCompilerCallback(callback: CompilerCallback): this.type = {
77-
base.compilerCallback = callback; this
78-
}
79-
8075
/** The outer context */
8176
private[this] var _outer: Context = _
8277
protected def outer_=(outer: Context) = _outer = outer
8378
def outer: Context = _outer
8479

85-
// protected def compilerCallback_=(callback: CompilerCallback) =
86-
// _compilerCallback = callback
87-
// def compilerCallback: CompilerCallback = _compilerCallback
88-
// def setCompilerCallback(callback: CompilerCallback): this.type = {
89-
// this.compilerCallback = callback; this
90-
// }
80+
/** The compiler callback implementation, or null if no callback will be called. */
81+
private[this] var _compilerCallback: CompilerCallback = _
82+
protected def compilerCallback_=(callback: CompilerCallback) =
83+
_compilerCallback = callback
84+
def compilerCallback: CompilerCallback = _compilerCallback
9185

9286
/** The current context */
9387
private[this] var _period: Period = _
@@ -426,7 +420,9 @@ object Contexts {
426420
abstract class FreshContext extends Context {
427421
def setPeriod(period: Period): this.type = { this.period = period; this }
428422
def setMode(mode: Mode): this.type = { this.mode = mode; this }
423+
def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
429424
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
425+
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
430426
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
431427
def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
432428
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
@@ -481,7 +477,7 @@ object Contexts {
481477
outer = NoContext
482478
period = InitialPeriod
483479
mode = Mode.None
484-
typerState = new TyperState(new ThrowingReporter(new ConsoleReporter()(this)))
480+
typerState = new TyperState(new ConsoleReporter())
485481
printerFn = new RefinedPrinter(_)
486482
owner = NoSymbol
487483
sstate = settings.defaultState
@@ -536,10 +532,6 @@ object Contexts {
536532

537533
/** The essential mutable state of a context base, collected into a common class */
538534
class ContextState {
539-
540-
/** The compiler callback implementation, or null if unset */
541-
var compilerCallback: CompilerCallback = _
542-
543535
// Symbols state
544536

545537
/** A counter for unique ids */

src/dotty/tools/dotc/reporting/ConsoleReporter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import scala.reflect.internal.util._
1515
*/
1616
class ConsoleReporter(
1717
reader: BufferedReader = Console.in,
18-
writer: PrintWriter = new PrintWriter(Console.err, true))(ctx: Context)
18+
writer: PrintWriter = new PrintWriter(Console.err, true))
1919
extends Reporter with UniqueMessagePositions {
2020

2121
/** maximal number of error messages to be printed */

src/dotty/tools/dotc/reporting/Reporter.scala

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,23 @@ abstract class Reporter {
247247
incompleteHandler(d)(ctx)
248248

249249

250-
/** Print a summary */
251-
def printSummary(implicit ctx: Context): Unit = {
252-
if (warningCount > 0) ctx.println(countString(warningCount, "warning") + " found")
253-
if (errorCount > 0) ctx.println(countString(errorCount, "error") + " found")
250+
/** Summary of warnings and errors */
251+
def summary: String = {
252+
val b = new mutable.ListBuffer[String]
253+
if (warningCount > 0)
254+
b += countString(warningCount, "warning") + " found"
255+
if (errorCount > 0)
256+
b += countString(errorCount, "error") + " found"
254257
for ((settingName, count) <- unreportedWarnings)
255-
ctx.println(s"there were $count ${settingName.tail} warning(s); re-run with $settingName for details")
258+
b += s"there were $count ${settingName.tail} warning(s); re-run with $settingName for details"
259+
b.mkString("\n")
260+
}
261+
262+
/** Print the summary of warnings and errors */
263+
def printSummary(implicit ctx: Context): Unit = {
264+
val s = summary
265+
if (s != "")
266+
ctx.println(s)
256267
}
257268

258269
/** Returns a string meaning "n elements". */

src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ class TreeChecker extends Phase with SymTransformer {
118118
val prevPhase = ctx.phase.prev // can be a mini-phase
119119
val squahsedPhase = ctx.squashed(prevPhase)
120120
ctx.println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")
121-
val checkingCtx = ctx.fresh
122-
.setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.reporter)))
121+
val checkingCtx = ctx.fresh.setReporter(new ThrowingReporter(ctx.reporter))
123122
val checker = new Checker(previousPhases(phasesToRun.toList)(ctx))
124123
try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx)
125124
catch {

test/dotty/partest/DPDirectCompiler.scala

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,22 @@ import scala.tools.partest.{ TestState, nest }
55
import java.io.{ File, PrintWriter, FileWriter }
66

77

8-
/* NOTE: Adapted from partest.DirectCompiler and DottyTest */
8+
/* NOTE: Adapted from partest.DirectCompiler */
99
class DPDirectCompiler(runner: DPTestRunner) extends nest.DirectCompiler(runner) {
1010

1111
override def compile(opts0: List[String], sources: List[File]): TestState = {
1212
val clogFWriter = new FileWriter(runner.cLogFile.jfile, true)
1313
val clogWriter = new PrintWriter(clogFWriter, true)
1414
clogWriter.println("\ncompiling " + sources.mkString(" ") + "\noptions: " + opts0.mkString(" "))
1515

16-
implicit val ctx: dotty.tools.dotc.core.Contexts.Context = {
17-
val base = new dotty.tools.dotc.core.Contexts.ContextBase
18-
import base.settings._
19-
val ctx = base.initialCtx.fresh.setSetting(printtypes, true)
20-
.setSetting(pageWidth, 90).setSetting(log, List("<some"))
21-
base.definitions.init(ctx)
22-
ctx
23-
}
24-
2516
try {
2617
val processor =
2718
if (opts0.exists(_.startsWith("#"))) dotty.tools.dotc.Bench else dotty.tools.dotc.Main
28-
val clogger = new ConsoleReporter(writer = clogWriter)(ctx)
29-
val logCtx = ctx.fresh.setTyperState(ctx.typerState.withReporter(clogger))
30-
val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, logCtx)
19+
val clogger = new ConsoleReporter(writer = clogWriter)
20+
val reporter = processor.process((sources.map(_.toString) ::: opts0).toArray, clogger)
3121
if (!reporter.hasErrors) runner.genPass()
3222
else {
33-
reporter.printSummary(ctx)
23+
clogWriter.println(reporter.summary)
3424
runner.genFail(s"compilation failed with ${reporter.errorCount} errors")
3525
}
3626
} catch {

test/test/CompilerTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import org.junit.Test
3333
* object Test { def main(args: Array[String]): Unit = ... }
3434
* Classpath jars can be added to partestDeps in the sbt Build.scala.
3535
*/
36-
abstract class CompilerTest extends DottyTest {
36+
abstract class CompilerTest {
3737

3838
/** Override with output dir of test so it can be patched. Partest expects
3939
* classes to be in partest-generated/[kind]/[testname]-[kind].obj/ */
@@ -181,7 +181,7 @@ abstract class CompilerTest extends DottyTest {
181181
private def compileArgs(args: Array[String], xerrors: Int = 0)(implicit defaultOptions: List[String]): Unit = {
182182
val allArgs = args ++ defaultOptions
183183
val processor = if (allArgs.exists(_.startsWith("#"))) Bench else Main
184-
val nerrors = processor.process(allArgs, ctx).errorCount
184+
val nerrors = processor.process(allArgs).errorCount
185185
assert(nerrors == xerrors, s"Wrong # of errors. Expected: $xerrors, found: $nerrors")
186186
}
187187

test/test/DottyTest.scala

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,6 @@ class DottyTest /*extends ContextEscapeDetection*/ {
2222
val base = new ContextBase
2323
import base.settings._
2424
val ctx = base.initialCtx.fresh
25-
//.setSetting(verbose, true)
26-
// .withSetting(debug, true)
27-
// .withSetting(debugTrace, true)
28-
// .withSetting(prompt, true)
29-
//.setSetting(Ylogcp, true)
30-
//.setSetting(printtypes, true)
31-
.setSetting(pageWidth, 90)
32-
.setSetting(log, List("<some"))
33-
// .withTyperState(new TyperState(new ConsoleReporter()(base.initialCtx)))
34-
35-
// .withSetting(uniqid, true)
3625
base.definitions.init(ctx)
3726
ctx
3827
}

0 commit comments

Comments
 (0)