From 6b7fbfe77961ab9d3fa7a9ea7f742f8b3935dde7 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 13 Mar 2013 12:40:03 -0400 Subject: [PATCH] Provided details of why external binaries are detected as modified in incremental compiler debug output. --- .../src/main/scala/sbt/inc/Incremental.scala | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/compile/inc/src/main/scala/sbt/inc/Incremental.scala b/compile/inc/src/main/scala/sbt/inc/Incremental.scala index e9722f294..ec6fbc1f7 100644 --- a/compile/inc/src/main/scala/sbt/inc/Incremental.scala +++ b/compile/inc/src/main/scala/sbt/inc/Incremental.scala @@ -21,14 +21,14 @@ object Incremental log: Logger, options: IncOptions)(implicit equivS: Equiv[Stamp]): (Boolean, Analysis) = { - val initialChanges = changedInitial(entry, sources, previous, current, forEntry, options) + val initialChanges = changedInitial(entry, sources, previous, current, forEntry, options, log) val binaryChanges = new DependencyChanges { val modifiedBinaries = initialChanges.binaryDeps.toArray val modifiedClasses = initialChanges.external.modified.toArray def isEmpty = modifiedBinaries.isEmpty && modifiedClasses.isEmpty } val initialInv = invalidateInitial(previous.relations, initialChanges, log) - log.debug("Initially invalidated: " + initialInv) + log.debug("All initially invalidated sources: " + initialInv + "\n") val analysis = manageClassfiles(options) { classfileManager => cycle(initialInv, sources, binaryChanges, previous, doCompile, classfileManager, 1, log, options) } @@ -125,14 +125,14 @@ object Incremental } def changedInitial(entry: String => Option[File], sources: Set[File], previousAnalysis: Analysis, current: ReadStamps, - forEntry: File => Option[Analysis], options: IncOptions)(implicit equivS: Equiv[Stamp]): InitialChanges = + forEntry: File => Option[Analysis], options: IncOptions, log: Logger)(implicit equivS: Equiv[Stamp]): InitialChanges = { val previous = previousAnalysis.stamps val previousAPIs = previousAnalysis.apis val srcChanges = changes(previous.allInternalSources.toSet, sources, f => !equivS.equiv( previous.internalSource(f), current.internalSource(f) ) ) val removedProducts = previous.allProducts.filter( p => !equivS.equiv( previous.product(p), current.product(p) ) ).toSet - val binaryDepChanges = previous.allBinaries.filter( externalBinaryModified(entry, forEntry, previous, current)).toSet + val binaryDepChanges = previous.allBinaries.filter( externalBinaryModified(entry, forEntry, previous, current, log)).toSet val extChanges = changedIncremental(previousAPIs.allExternals, previousAPIs.externalAPI _, currentExternalAPI(entry, forEntry), options) InitialChanges(srcChanges, removedProducts, binaryDepChanges, extChanges ) @@ -252,18 +252,38 @@ object Incremental previous -- invalidatedSrcs } - def externalBinaryModified(entry: String => Option[File], analysis: File => Option[Analysis], previous: Stamps, current: ReadStamps)(implicit equivS: Equiv[Stamp]): File => Boolean = + def externalBinaryModified(entry: String => Option[File], analysis: File => Option[Analysis], previous: Stamps, current: ReadStamps, log: Logger)(implicit equivS: Equiv[Stamp]): File => Boolean = dependsOn => - analysis(dependsOn).isEmpty && - orTrue( - for { - name <- previous.className(dependsOn) - e <- entry(name) - } yield { - val resolved = Locate.resolve(e, name) - (resolved.getCanonicalPath != dependsOn.getCanonicalPath) || !equivS.equiv(previous.binary(dependsOn), current.binary(resolved)) + { + def inv(reason: String): Boolean = { + log.debug("Invalidating " + dependsOn.getCanonicalPath + ": " + reason) + true + } + def entryModified(className: String, classpathEntry: File): Boolean = + { + val resolved = Locate.resolve(classpathEntry, className) + if(resolved.getCanonicalPath != dependsOn.getCanonicalPath) + inv("class " + className + " now provided by " + resolved.getCanonicalPath) + else { + val previousStamp = previous.binary(dependsOn) + val resolvedStamp = current.binary(resolved) + if(equivS.equiv(previousStamp, resolvedStamp)) + false + else + inv("stamp changed from " + previousStamp + " to " + resolvedStamp) } - ) + } + + analysis(dependsOn).isEmpty && { + previous.className(dependsOn) match { + case None => inv("no class name was mapped for it.") + case Some(name) => entry(name) match { + case None => inv("could not find class " + name + " on the classpath.") + case Some(e) => entryModified(name, e) + } + } + } + } def currentExternalAPI(entry: String => Option[File], forEntry: File => Option[Analysis]): String => Source = className =>