Handle compilation cancellation properly. #821

Merged
merged 1 commit into from Jul 19, 2013
View
10 compile/inc/src/main/scala/sbt/inc/Compile.scala
@@ -22,7 +22,15 @@ object IncrementalCompile
val current = Stamps.initial(Stamp.exists, Stamp.hash, Stamp.lastModified)
val internalMap = (f: File) => previous.relations.produced(f).headOption
val externalAPI = getExternalAPI(entry, forEntry)
- Incremental.compile(sources, entry, previous, current, forEntry, doCompile(compile, internalMap, externalAPI, current, output, options), log, options)
+ try {
+ Incremental.compile(sources, entry, previous, current, forEntry, doCompile(compile, internalMap, externalAPI, current, output, options), log, options)
+ } catch {
+ case e: xsbti.CompileCancelled =>
+ log.info("Compilation has been cancelled")
+ // in case compilation got cancelled potential partial compilation results (e.g. produced classs files) got rolled back
+ // and we can report back as there was no change (false) and return a previous Analysis which is still up-to-date
+ (false, previous)
+ }
}
def doCompile(compile: (Set[File], DependencyChanges, xsbti.AnalysisCallback) => Unit, internalMap: File => Option[File], externalAPI: (File, String) => Option[Source], current: ReadStamps, output: Output, options: IncOptions) =
(srcs: Set[File], changes: DependencyChanges) => {
View
11 compile/interface/src/main/scala/xsbt/CompilerInterface.scala
@@ -50,6 +50,8 @@ sealed abstract class CallbackGlobal(settings: Settings, reporter: reporters.Rep
}
class InterfaceCompileFailed(val arguments: Array[String], val problems: Array[Problem], override val toString: String) extends xsbti.CompileFailed
+class InterfaceCompileCancelled(val arguments: Array[String], override val toString: String) extends xsbti.CompileCancelled
+
private final class WeakLog(private[this] var log: Logger, private[this] var delegate: Reporter)
{
def apply(message: String) {
@@ -124,12 +126,21 @@ private final class CachedCompiler0(args: Array[String], output: Output, initial
}
dreporter.printSummary()
if(!noErrors(dreporter)) handleErrors(dreporter, log)
+ // the case where we cancelled compilation _after_ some compilation errors got reported
+ // will be handled by line above so errors still will be reported properly just potentially not
+ // all of them (because we cancelled the compilation)
+ if (dreporter.cancelled) handleCompilationCancellation(dreporter, log)
}
def handleErrors(dreporter: DelegatingReporter, log: Logger): Nothing =
{
debug(log, "Compilation failed (CompilerInterface)")
throw new InterfaceCompileFailed(args, dreporter.problems, "Compilation failed")
}
+ def handleCompilationCancellation(dreporter: DelegatingReporter, log: Logger): Nothing = {
+ assert(dreporter.cancelled, "We should get here only if when compilation got cancelled")
+ debug(log, "Compilation cancelled (CompilerInterface)")
+ throw new InterfaceCompileCancelled(args, "Compilation has been cancelled")
+ }
def processUnreportedWarnings(run: compiler.Run)
{
// allConditionalWarnings and the ConditionalWarning class are only in 2.10+
View
9 interface/src/main/java/xsbti/CompileCancelled.java
@@ -0,0 +1,9 @@
+package xsbti;
+
+/**
+ * An exception thrown when compilation cancellation has been requested during
+ * Scala compiler run.
+ */
+public abstract class CompileCancelled extends RuntimeException {
+ public abstract String[] arguments();
+}