From 3fa6b8731992a7a0d1f319eb666e8d1a592ff710 Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Wed, 13 Aug 2014 23:32:14 +0200 Subject: [PATCH] Set currentRun and currentUnit in Eval First of all, we revert changes to Eval made in a9cdd96152e08a1fb21e815eabe8fd1d27ef9b97. That was a work-around for problem with broken positions set on some trees. The rest of the commit describes a fix. Scala compiler's Global has `currentRun` method which is supposed to return an instance of Run currently in use. Sbt's Eval which wraps Global would create an instance of Run but not register it in Global. Similarly, Eval would create an instance of `CompilationUnit` but not set it in Run. This would result in some silent failures like assigning broken positions to parsed trees even if parser *has* received an instance of compilation unit. See https://issues.scala-lang.org/browse/SI-8794 for details. We fix the issue by subclassing Global and making it possible to set current Run instance externally. Then we use this capability to set a run instance right before we call compiler phases. We also make sure that current run has current compilation assigned to it. Fixes #1181 Fixes #1501 Fixes #1523 --- .../src/main/scala/sbt/compiler/Eval.scala | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/main/actions/src/main/scala/sbt/compiler/Eval.scala b/main/actions/src/main/scala/sbt/compiler/Eval.scala index f41fb9dbe..e530850db 100644 --- a/main/actions/src/main/scala/sbt/compiler/Eval.scala +++ b/main/actions/src/main/scala/sbt/compiler/Eval.scala @@ -58,7 +58,15 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se s } lazy val reporter = mkReporter(settings) - lazy val global: Global = new Global(settings, reporter) + /** + * Subclass of Global which allows us to mutate currentRun from outside. + * See for rationale https://issues.scala-lang.org/browse/SI-8794 + */ + final class EvalGlobal(settings: Settings, reporter: Reporter) extends Global(settings, reporter) { + override def currentRun: Run = curRun + var curRun: Run = null + } + lazy val global: EvalGlobal = new EvalGlobal(settings, reporter) import global._ import definitions._ @@ -143,6 +151,8 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se private[this] def cacheFile(base: File, moduleName: String): File = new File(base, moduleName + ".cache") private[this] def compileAndLoad[T](run: Run, unit: CompilationUnit, imports: EvalImports, backing: Option[File], moduleName: String, ev: EvalType[T]): (T, ClassLoader => ClassLoader) = { + global.curRun = run + run.currentUnit = unit val dir = outputDirectory(backing) settings.outputDirs setSingleOutput dir @@ -348,21 +358,8 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se val DefaultStartLine = 0 private[this] def makeModuleName(hash: String): String = "$" + Hash.halve(hash) - private[sbt] def noImports = new EvalImports(Nil, "") - private[sbt] def mkUnit(srcName: String, firstLine: Int, s: String) = new CompilationUnit(new EvalSourceFile(srcName, firstLine, s)) { - // This is overridden as a workaround for #1181/#1501, - // When the compiler reports an error back, the position sometimes comes back with source set to NoSourceFile. - override def error(pos0: Position, msg: String) = { - import scala.reflect.internal.util._ - val pos = pos0 match { - case op: OffsetPosition if op.point >= 0 => - if (op.source eq source) op - else new OffsetPosition(source, op.point) - case _ => pos0 - } - super.error(pos, msg) - } - } + private[this] def noImports = new EvalImports(Nil, "") + private[this] def mkUnit(srcName: String, firstLine: Int, s: String) = new CompilationUnit(new EvalSourceFile(srcName, firstLine, s)) private[this] def checkError(label: String) = if (reporter.hasErrors) throw new EvalException(label) private[this] final class EvalSourceFile(name: String, startLine: Int, contents: String) extends BatchSourceFile(name, contents) {