diff options
author | Simeon H.K. Fitch <fitch@datamininglab.com> | 2015-02-05 05:57:45 +0000 |
---|---|---|
committer | Christopher Vogt <oss.nsp@cvogt.org> | 2016-11-07 02:08:39 -0500 |
commit | 44b6e6845c931aff4a69f98a0b44c8c69128369b (patch) | |
tree | 58b95a9814b5f989d6a5b91c18809cbafe840a3b /libraries/eval/Eval.scala | |
parent | 623cfdd2a0b26ef2d1e0a78025b950f2958b67b7 (diff) | |
download | cbt-44b6e6845c931aff4a69f98a0b44c8c69128369b.tar.gz cbt-44b6e6845c931aff4a69f98a0b44c8c69128369b.tar.bz2 cbt-44b6e6845c931aff4a69f98a0b44c8c69128369b.zip |
Added ability to override `Reporter` used during compilation. See issue #89
Signed-off-by: Moses Nakamura <mnakamura@twitter.com>
RB_ID=572344
Diffstat (limited to 'libraries/eval/Eval.scala')
-rw-r--r-- | libraries/eval/Eval.scala | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/libraries/eval/Eval.scala b/libraries/eval/Eval.scala index e9c95fd..7e5fb71 100644 --- a/libraries/eval/Eval.scala +++ b/libraries/eval/Eval.scala @@ -27,7 +27,7 @@ import scala.collection.mutable import scala.io.Source import scala.tools.nsc.interpreter.AbstractFileClassLoader import scala.tools.nsc.io.{AbstractFile, VirtualDirectory} -import scala.tools.nsc.reporters.AbstractReporter +import scala.tools.nsc.reporters.{Reporter, AbstractReporter} import scala.tools.nsc.util.{BatchSourceFile, Position} import scala.tools.nsc.{Global, Settings} import scala.util.matching.Regex @@ -108,8 +108,14 @@ class Eval(target: Option[File]) { ) ) - private[this] val STYLE_INDENT = 2 - private[this] lazy val compiler = new StringCompiler(STYLE_INDENT, target) + // For derived classes to provide an alternate compiler message handler. + protected lazy val compilerMessageHandler: Option[Reporter] = None + + // For derived classes do customize or override the default compiler settings. + protected lazy val compilerSettings: Settings = new EvalSettings(target) + + // Primary encapsulation around native Scala compiler + private[this] lazy val compiler = new StringCompiler(codeWrapperLineOffset, target, compilerSettings, compilerMessageHandler) /** * run preprocessors on our string, returning a String that is the processed source @@ -290,9 +296,10 @@ class Eval(target: Option[File]) { } /* - * Wrap source code in a new class with an apply method. + * Wraps source code in a new class with an apply method. + * NB: If this method is changed, make sure `codeWrapperLineOffset` is correct. */ - private def wrapCodeInClass(className: String, code: String) = { + private[this] def wrapCodeInClass(className: String, code: String) = { "class " + className + " extends (() => Any) {\n" + " def apply() = {\n" + code + "\n" + @@ -301,6 +308,13 @@ class Eval(target: Option[File]) { } /* + * Defines the number of code lines that proceed evaluated code. + * Used to ensure compile error messages report line numbers aligned with user's code. + * NB: If `wrapCodeInClass(String,String)` is changed, make sure this remains correct. + */ + private[this] val codeWrapperLineOffset = 2 + + /* * For a given FQ classname, trick the resource finder into telling us the containing jar. */ private def classPathOfClass(className: String) = { @@ -429,27 +443,34 @@ class Eval(target: Option[File]) { } } + lazy val compilerOutputDir = target match { + case Some(dir) => AbstractFile.getDirectory(dir) + case None => new VirtualDirectory("(memory)", None) + } + + class EvalSettings(targetDir: Option[File]) extends Settings { + nowarnings.value = true // warnings are exceptions, so disable + outputDirs.setSingleOutput(compilerOutputDir) + private[this] val pathList = compilerPath ::: libPath + bootclasspath.value = pathList.mkString(File.pathSeparator) + classpath.value = (pathList ::: impliedClassPath).mkString(File.pathSeparator) + } + /** * Dynamic scala compiler. Lots of (slow) state is created, so it may be advantageous to keep * around one of these and reuse it. */ - private class StringCompiler(lineOffset: Int, targetDir: Option[File]) { - val target = targetDir match { - case Some(dir) => AbstractFile.getDirectory(dir) - case None => new VirtualDirectory("(memory)", None) - } + private class StringCompiler( + lineOffset: Int, targetDir: Option[File], settings: Settings, messageHandler: Option[Reporter]) { val cache = new mutable.HashMap[String, Class[_]]() + val target = compilerOutputDir - val settings = new Settings - settings.nowarnings.value = true // warnings are exceptions, so disable - settings.outputDirs.setSingleOutput(target) - - val pathList = compilerPath ::: libPath - settings.bootclasspath.value = pathList.mkString(File.pathSeparator) - settings.classpath.value = (pathList ::: impliedClassPath).mkString(File.pathSeparator) + trait MessageCollector { + val messages: Seq[List[String]] + } - val reporter = new AbstractReporter { + val reporter = messageHandler getOrElse new AbstractReporter with MessageCollector { val settings = StringCompiler.this.settings val messages = new mutable.ListBuffer[List[String]] @@ -509,7 +530,7 @@ class Eval(target: Option[File]) { } } cache.clear() - reporter.reset + reporter.reset() classLoader = new AbstractFileClassLoader(target, this.getClass.getClassLoader) } @@ -557,7 +578,13 @@ class Eval(target: Option[File]) { compiler.compileSources(sourceFiles) if (reporter.hasErrors || reporter.WARNING.count > 0) { - throw new CompilerException(reporter.messages.toList) + val msgs: List[List[String]] = reporter match { + case collector: MessageCollector => + collector.messages.toList + case _ => + List(List(reporter.toString)) + } + throw new CompilerException(msgs) } } |