diff --git a/compile/inc/src/main/scala/sbt/inc/Compile.scala b/compile/inc/src/main/scala/sbt/inc/Compile.scala index 61a19d3dd..e5dae387c 100644 --- a/compile/inc/src/main/scala/sbt/inc/Compile.scala +++ b/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) => { diff --git a/compile/interface/src/main/scala/xsbt/CompilerInterface.scala b/compile/interface/src/main/scala/xsbt/CompilerInterface.scala index 3a02bd138..7f94d1dab 100644 --- a/compile/interface/src/main/scala/xsbt/CompilerInterface.scala +++ b/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+ diff --git a/interface/src/main/java/xsbti/CompileCancelled.java b/interface/src/main/java/xsbti/CompileCancelled.java new file mode 100644 index 000000000..bcd3695dd --- /dev/null +++ b/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(); +}