diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-09-26 07:43:48 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-09-27 15:49:01 +0200 |
commit | ca9d2149e964604daf3a8d88d6946217ef90c643 (patch) | |
tree | 0d285f2f1a28382be9a43cddd8d148a73b7422f5 | |
parent | 7911f9e85b3798d449d6b551d7c8be15cc63f240 (diff) | |
download | scala-ca9d2149e964604daf3a8d88d6946217ef90c643.tar.gz scala-ca9d2149e964604daf3a8d88d6946217ef90c643.tar.bz2 scala-ca9d2149e964604daf3a8d88d6946217ef90c643.zip |
removes front ends from scala-reflect.jar
It was an interesting idea to give macro developers control over front ends,
but it hasn't given any visible results.
To the contrast, front ends have proven useful for toolboxes to easily control
what errors get printed where.
Therefore I'm moving front ends to scala-compiler.jar to clean up the API.
Yay for scaladoc-driven development!
-rw-r--r-- | src/compiler/scala/reflect/macros/runtime/Aliases.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/reflect/macros/runtime/FrontEnds.scala | 26 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/FrontEnd.scala | 50 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/FrontEnds.scala | 88 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBox.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBoxFactory.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/package.scala | 90 | ||||
-rw-r--r-- | src/reflect/scala/reflect/api/FrontEnds.scala | 70 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/Aliases.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/FrontEnds.scala | 14 | ||||
-rw-r--r-- | test/files/run/toolbox_console_reporter.check | 8 | ||||
-rw-r--r-- | test/files/run/toolbox_console_reporter.scala | 35 | ||||
-rw-r--r-- | test/files/run/toolbox_silent_reporter.scala | 4 |
13 files changed, 180 insertions, 214 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/Aliases.scala b/src/compiler/scala/reflect/macros/runtime/Aliases.scala index 30e72997f7..23489ed4ec 100644 --- a/src/compiler/scala/reflect/macros/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/macros/runtime/Aliases.scala @@ -10,7 +10,7 @@ trait Aliases { override type TermName = universe.TermName override type TypeName = universe.TypeName override type Tree = universe.Tree - // override type Position = universe.Position + override type Position = universe.Position override type Scope = universe.Scope override type Modifiers = universe.Modifiers diff --git a/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala index 9f328eb82b..a6a198e1b4 100644 --- a/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala @@ -1,28 +1,9 @@ package scala.reflect.macros package runtime -trait FrontEnds extends scala.tools.reflect.FrontEnds { +trait FrontEnds { self: Context => - import universe._ - import mirror._ - - override type Position = universe.Position - - def frontEnd: FrontEnd = wrapReporter(universe.reporter) - - def setFrontEnd(frontEnd: FrontEnd): this.type = { - universe.reporter = wrapFrontEnd(frontEnd) - this - } - - def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T = { - val old = universe.reporter - setFrontEnd(frontEnd) - try op - finally universe.reporter = old - } - def echo(pos: Position, msg: String): Unit = universe.reporter.echo(pos, msg) def info(pos: Position, msg: String, force: Boolean): Unit = universe.reporter.info(pos, msg, force) @@ -36,9 +17,4 @@ trait FrontEnds extends scala.tools.reflect.FrontEnds { def error(pos: Position, msg: String): Unit = callsiteTyper.context.error(pos, msg) def abort(pos: Position, msg: String): Nothing = throw new AbortMacroException(pos, msg) - - def interactive(): Unit = universe.reporter match { - case reporter: scala.tools.nsc.reporters.AbstractReporter => reporter.displayPrompt() - case _ => () - } } diff --git a/src/compiler/scala/tools/reflect/FrontEnd.scala b/src/compiler/scala/tools/reflect/FrontEnd.scala new file mode 100644 index 0000000000..f0d3d5973d --- /dev/null +++ b/src/compiler/scala/tools/reflect/FrontEnd.scala @@ -0,0 +1,50 @@ +package scala.tools +package reflect + +import scala.reflect.internal.util.Position + +trait FrontEnd { + object severity extends Enumeration + class Severity(val id: Int) extends severity.Value { + var count: Int = 0 + override def toString() = this match { + case INFO => "INFO" + case WARNING => "WARNING" + case ERROR => "ERROR" + case _ => "<unknown>" + } + } + val INFO = new Severity(0) + val WARNING = new Severity(1) + val ERROR = new Severity(2) + + def hasErrors = ERROR.count > 0 + def hasWarnings = WARNING.count > 0 + + case class Info(val pos: Position, val msg: String, val severity: Severity) + val infos = new scala.collection.mutable.LinkedHashSet[Info] + + /** Handles incoming info */ + def log(pos: Position, msg: String, severity: Severity) { + infos += new Info(pos, msg, severity) + severity.count += 1 + display(infos.last) + } + + /** Displays incoming info */ + def display(info: Info): Unit + + /** Services a request to drop into interactive mode */ + def interactive(): Unit + + /** Refreshes the UI */ + def flush(): Unit = {} + + /** Resets the reporter */ + def reset(): Unit = { + INFO.count = 0 + WARNING.count = 0 + ERROR.count = 0 + infos.clear() + } +} diff --git a/src/compiler/scala/tools/reflect/FrontEnds.scala b/src/compiler/scala/tools/reflect/FrontEnds.scala deleted file mode 100644 index d0c3c1c774..0000000000 --- a/src/compiler/scala/tools/reflect/FrontEnds.scala +++ /dev/null @@ -1,88 +0,0 @@ -package scala.tools -package reflect - -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import scala.reflect.ClassTag - -trait FrontEnds extends scala.reflect.api.FrontEnds { - - type Position = scala.reflect.internal.util.Position - - def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd = { - val settings = new Settings() - if (minSeverity <= 0) settings.verbose.value = true - if (minSeverity > 1) settings.nowarn.value = true - wrapReporter(new ConsoleReporter(settings)) - } - - abstract class FrontEndToReporterProxy(val frontEnd: FrontEnd) extends AbstractReporter { - import frontEnd.{Severity => ApiSeverity} - val API_INFO = frontEnd.INFO - val API_WARNING = frontEnd.WARNING - val API_ERROR = frontEnd.ERROR - - type NscSeverity = Severity - val NSC_INFO = INFO - val NSC_WARNING = WARNING - val NSC_ERROR = ERROR - - def display(pos: Position, msg: String, nscSeverity: NscSeverity): Unit = - frontEnd.log(pos, msg, nscSeverity match { - case NSC_INFO => API_INFO - case NSC_WARNING => API_WARNING - case NSC_ERROR => API_ERROR - }) - - def displayPrompt(): Unit = - frontEnd.interactive() - - override def flush(): Unit = { - super.flush() - frontEnd.flush() - } - - override def reset(): Unit = { - super.reset() - frontEnd.reset() - } - } - - def wrapFrontEnd(frontEnd: FrontEnd): Reporter = new FrontEndToReporterProxy(frontEnd) { - val settings = new Settings() - settings.verbose.value = true - settings.nowarn.value = false - } - - class ReporterToFrontEndProxy(val reporter: Reporter) extends FrontEnd { - val API_INFO = INFO - val API_WARNING = WARNING - val API_ERROR = ERROR - - override def hasErrors = reporter.hasErrors - override def hasWarnings = reporter.hasWarnings - - def display(info: Info): Unit = info.severity match { - case API_INFO => reporter.info(info.pos, info.msg, false) - case API_WARNING => reporter.warning(info.pos, info.msg) - case API_ERROR => reporter.error(info.pos, info.msg) - } - - def interactive(): Unit = reporter match { - case reporter: AbstractReporter => reporter.displayPrompt() - case _ => // do nothing - } - - override def flush(): Unit = { - super.flush() - reporter.flush() - } - - override def reset(): Unit = { - super.reset() - reporter.reset() - } - } - - def wrapReporter(reporter: Reporter): FrontEnd = new ReporterToFrontEndProxy(reporter) -} diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index f627699597..ab814b617d 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -15,6 +15,9 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * * Accumulates and displays warnings and errors, can drop to interactive mode (if supported). * The latter can be useful to study the typechecker or to debug complex macros. + * + * [[scala.tools.reflect]] provides two predefined front ends that can be created using + * [[scala.tools.reflect.mkSilentFrontEnd]] and [[scala.tools.reflect.mkConsoleFrontEnd]]. */ def frontEnd: FrontEnd diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 17d69cf94b..95135b84e0 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -334,7 +334,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val errorFn: String => Unit = msg => frontEnd.log(scala.reflect.internal.util.NoPosition, msg, frontEnd.ERROR) val command = new CompilerCommand(arguments.toList, errorFn) command.settings.outputDirs setSingleOutput virtualDirectory - val instance = new ToolBoxGlobal(command.settings, new FrontEndToReporterProxy(frontEnd) { val settings = command.settings }) + val instance = new ToolBoxGlobal(command.settings, frontEndToReporter(frontEnd, command.settings)) if (frontEnd.hasErrors) { var msg = "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL msg += frontEnd.infos map (_.msg) mkString EOL diff --git a/src/compiler/scala/tools/reflect/package.scala b/src/compiler/scala/tools/reflect/package.scala index 901071d91a..8a1e3628e2 100644 --- a/src/compiler/scala/tools/reflect/package.scala +++ b/src/compiler/scala/tools/reflect/package.scala @@ -6,9 +6,12 @@ package scala.tools import scala.reflect.api.JavaUniverse +import scala.reflect.internal.util.Position import scala.language.implicitConversions +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings -package object reflect extends FrontEnds { +package object reflect { // [todo: can we generalize this? import scala.reflect.runtime.{universe => ru} implicit def ToolBox(mirror0: ru.Mirror): ToolBoxFactory[ru.type] = @@ -17,9 +20,92 @@ package object reflect extends FrontEnds { } // todo. replace this with an implicit class, once the pesky warning is gone + // we don't provide `Eval` for trees, because it's unclear where to get an evaluation mirror from implicit def Eval[T](expr: JavaUniverse # Expr[T]): Eval[T] = new Eval[T](expr) - // we don't provide `Eval` for trees, because it's unclear where to get an evaluation mirror from + /** Creates a UI-less reporter that simply accumulates all the messages + */ + def mkSilentFrontEnd(): FrontEnd = new FrontEnd { + def display(info: Info) {} + def interactive() {} + } + + /** Creates a reporter that prints messages to the console according to the settings. + * + * ``minSeverity'' determines minimum severity of the messages to be printed. + * 0 stands for INFO, 1 stands for WARNING and 2 stands for ERROR. + */ + // todo. untangle warningsAsErrors from Reporters. I don't feel like moving this flag here! + def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd = { + val settings = new Settings() + if (minSeverity <= 0) settings.verbose.value = true + if (minSeverity > 1) settings.nowarn.value = true + reporterToFrontEnd(new ConsoleReporter(settings)) + } + + private[reflect] def reporterToFrontEnd(reporter: Reporter): FrontEnd = new FrontEnd { + val API_INFO = INFO + val API_WARNING = WARNING + val API_ERROR = ERROR + + override def hasErrors = reporter.hasErrors + override def hasWarnings = reporter.hasWarnings + + def display(info: Info): Unit = info.severity match { + case API_INFO => reporter.info(info.pos, info.msg, false) + case API_WARNING => reporter.warning(info.pos, info.msg) + case API_ERROR => reporter.error(info.pos, info.msg) + } + + def interactive(): Unit = reporter match { + case reporter: AbstractReporter => reporter.displayPrompt() + case _ => // do nothing + } + + override def flush(): Unit = { + super.flush() + reporter.flush() + } + + override def reset(): Unit = { + super.reset() + reporter.reset() + } + } + + private[reflect] def frontEndToReporter(frontEnd: FrontEnd, settings0: Settings): Reporter = new AbstractReporter { + val settings = settings0 + + import frontEnd.{Severity => ApiSeverity} + val API_INFO = frontEnd.INFO + val API_WARNING = frontEnd.WARNING + val API_ERROR = frontEnd.ERROR + + type NscSeverity = Severity + val NSC_INFO = INFO + val NSC_WARNING = WARNING + val NSC_ERROR = ERROR + + def display(pos: Position, msg: String, nscSeverity: NscSeverity): Unit = + frontEnd.log(pos, msg, nscSeverity match { + case NSC_INFO => API_INFO + case NSC_WARNING => API_WARNING + case NSC_ERROR => API_ERROR + }) + + def displayPrompt(): Unit = + frontEnd.interactive() + + override def flush(): Unit = { + super.flush() + frontEnd.flush() + } + + override def reset(): Unit = { + super.reset() + frontEnd.reset() + } + } } package reflect { diff --git a/src/reflect/scala/reflect/api/FrontEnds.scala b/src/reflect/scala/reflect/api/FrontEnds.scala deleted file mode 100644 index 61ea227c47..0000000000 --- a/src/reflect/scala/reflect/api/FrontEnds.scala +++ /dev/null @@ -1,70 +0,0 @@ -package scala.reflect -package api - -trait FrontEnds { - - type Position >: Null - - trait FrontEnd { - object severity extends Enumeration - class Severity(val id: Int) extends severity.Value { - var count: Int = 0 - override def toString() = this match { - case INFO => "INFO" - case WARNING => "WARNING" - case ERROR => "ERROR" - case _ => "<unknown>" - } - } - val INFO = new Severity(0) - val WARNING = new Severity(1) - val ERROR = new Severity(2) - - def hasErrors = ERROR.count > 0 - def hasWarnings = WARNING.count > 0 - - case class Info(val pos: Position, val msg: String, val severity: Severity) - val infos = new scala.collection.mutable.LinkedHashSet[Info] - - /** Handles incoming info */ - def log(pos: Position, msg: String, severity: Severity) { - infos += new Info(pos, msg, severity) - severity.count += 1 - display(infos.last) - } - - /** Displays incoming info */ - def display(info: Info): Unit - - /** Services a request to drop into interactive mode */ - def interactive(): Unit - - /** Refreshes the UI */ - def flush(): Unit = {} - - /** Resets the reporter */ - def reset(): Unit = { - INFO.count = 0 - WARNING.count = 0 - ERROR.count = 0 - infos.clear() - } - } - - class SilentFrontEnd extends FrontEnd { - def display(info: Info) {} - def interactive() {} - } - - /** Creates a UI-less reporter that simply accumulates all the messages - */ - def mkSilentFrontEnd(): FrontEnd = new SilentFrontEnd() - - /** Creates a reporter that prints messages to the console according to the settings. - * - * ``minSeverity'' determines minimum severity of the messages to be printed. - * 0 stands for INFO, 1 stands for WARNING and 2 stands for ERROR. - */ - // todo. untangle warningsAsErrors from Reporters. I don't feel like moving this flag here! - def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd -} diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala index eff7f34b02..c026ab4d26 100644 --- a/src/reflect/scala/reflect/macros/Aliases.scala +++ b/src/reflect/scala/reflect/macros/Aliases.scala @@ -10,7 +10,7 @@ trait Aliases { type TermName = universe.TermName type TypeName = universe.TypeName type Tree = universe.Tree - // type Position = universe.Position + type Position = universe.Position type Scope = universe.Scope type Modifiers = universe.Modifiers diff --git a/src/reflect/scala/reflect/macros/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala index d15db0725f..e6b67cfc87 100644 --- a/src/reflect/scala/reflect/macros/FrontEnds.scala +++ b/src/reflect/scala/reflect/macros/FrontEnds.scala @@ -1,18 +1,9 @@ package scala.reflect package macros -trait FrontEnds extends scala.reflect.api.FrontEnds { +trait FrontEnds { self: Context => - import mirror._ - - type Position = universe.Position - - /** Exposes means to control the compiler UI */ - def frontEnd: FrontEnd - def setFrontEnd(frontEnd: FrontEnd): this.type - def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T - /** For sending a message which should not be labeled as a warning/error, * but also shouldn't require -verbose to be visible. * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''. @@ -36,7 +27,4 @@ trait FrontEnds extends scala.reflect.api.FrontEnds { * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''. */ def abort(pos: Position, msg: String): Nothing - - /** Drops into interactive mode if supported by the compiler UI */ - def interactive(): Unit }
\ No newline at end of file diff --git a/test/files/run/toolbox_console_reporter.check b/test/files/run/toolbox_console_reporter.check index e69de29bb2..1395c68740 100644 --- a/test/files/run/toolbox_console_reporter.check +++ b/test/files/run/toolbox_console_reporter.check @@ -0,0 +1,8 @@ +hello +============compiler console============= +warning: method foo in object Utils is deprecated: test + +========================================= +============compiler messages============ +Info(NoPosition,method foo in object Utils is deprecated: test,WARNING) +========================================= diff --git a/test/files/run/toolbox_console_reporter.scala b/test/files/run/toolbox_console_reporter.scala index a57dea38a8..d672ccb9cb 100644 --- a/test/files/run/toolbox_console_reporter.scala +++ b/test/files/run/toolbox_console_reporter.scala @@ -1,16 +1,29 @@ import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, mkConsoleFrontEnd} object Test extends App { - // todo. cannot test this unfortunately, because ConsoleFrontEnd grabs Console.out too early - // todo. and isn't affected by Console.setOut employed by partest to intercept output + val oldErr = Console.err; + val baos = new java.io.ByteArrayOutputStream(); + Console.setErr(new java.io.PrintStream(baos)); + try { + val toolbox = cm.mkToolBox(frontEnd = mkConsoleFrontEnd(), options = "-deprecation") + toolbox.eval(reify{ + object Utils { + @deprecated("test", "2.10.0") + def foo { println("hello") } + } - //val toolbox = mkToolBox(frontEnd = mkConsoleFrontEnd(), options = "-deprecation") - //toolbox.eval(reify{ - // object Utils { - // @deprecated("test", "2.10.0") - // def foo { println("hello") } - // } - // - // Utils.foo - //}) + Utils.foo + }.tree) + println("============compiler console=============") + println(baos.toString); + println("=========================================") + println("============compiler messages============") + toolbox.frontEnd.infos.foreach(println(_)) + println("=========================================") + } finally { + Console.setErr(oldErr); + } }
\ No newline at end of file diff --git a/test/files/run/toolbox_silent_reporter.scala b/test/files/run/toolbox_silent_reporter.scala index 15f559d605..03b1d6defa 100644 --- a/test/files/run/toolbox_silent_reporter.scala +++ b/test/files/run/toolbox_silent_reporter.scala @@ -1,10 +1,10 @@ import scala.reflect.runtime.universe._ import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{currentMirror => cm} -import scala.tools.reflect.ToolBox +import scala.tools.reflect.{ToolBox, mkSilentFrontEnd} object Test extends App { - val toolbox = cm.mkToolBox(options = "-deprecation") + val toolbox = cm.mkToolBox(options = "-deprecation", frontEnd = mkSilentFrontEnd()) toolbox.eval(reify{ object Utils { @deprecated("test", "2.10.0") |