diff options
-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") |