diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 360564cfb..34133efe1 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -104,7 +104,6 @@ import sbt.SlashSyntax0._ import sbt.internal.inc.{ Analysis, AnalyzingCompiler, - Locate, ManagedLoggedReporter, MixedAnalyzingCompiler, ScalaInstance @@ -759,13 +758,11 @@ object Defaults extends BuildCommon { Vector("-Ypickle-java", "-Ypickle-write", converter.toPath(earlyOutput.value).toString) ++ old else old }, + persistJarClasspath :== true, + classpathDefinesClassCache := VirtualFileValueCache.definesClassCache(fileConverter.value), classpathEntryDefinesClassVF := { - val converter = fileConverter.value - val f = VirtualFileValueCache(converter)({ x: VirtualFile => - if (x.name.toString != "rt.jar") Locate.definesClass(x) - else ((_: String) => false): DefinesClass - }).get - f + (if (persistJarClasspath.value) classpathDefinesClassCache.value + else VirtualFileValueCache.definesClassCache(fileConverter.value)).get }, compileIncSetup := compileIncSetupTask.value, console := consoleTask.value, diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 504b69a74..060fe0286 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -231,6 +231,8 @@ object Keys { val compilerCache = taskKey[GlobalsCache]("Cache of scala.tools.nsc.Global instances. This should typically be cached so that it isn't recreated every task run.").withRank(DTask) val stateCompilerCache = AttributeKey[GlobalsCache]("stateCompilerCache", "Internal use: Global cache.") val classpathEntryDefinesClass = taskKey[File => DefinesClass]("Internal use: provides a function that determines whether the provided file contains a given class.").withRank(Invisible) + private[sbt] val classpathDefinesClassCache = settingKey[VirtualFileValueCache[DefinesClass]]("Internal use: a cache of jar classpath entries that persists across command evaluations.").withRank(Invisible) + val persistJarClasspath = settingKey[Boolean]("Toggles whether or not to cache jar classpath entries between command evaluations") val classpathEntryDefinesClassVF = taskKey[VirtualFile => DefinesClass]("Internal use: provides a function that determines whether the provided file contains a given class.").withRank(Invisible) val doc = taskKey[File]("Generates API documentation.").withRank(AMinusTask) val copyResources = taskKey[Seq[(File, File)]]("Copies resources to the output directory.").withRank(AMinusTask) diff --git a/main/src/main/scala/sbt/internal/VirtualFileValueCache.scala b/main/src/main/scala/sbt/internal/VirtualFileValueCache.scala index 56ca6ad78..02d107e83 100644 --- a/main/src/main/scala/sbt/internal/VirtualFileValueCache.scala +++ b/main/src/main/scala/sbt/internal/VirtualFileValueCache.scala @@ -11,7 +11,9 @@ package internal import java.util.concurrent.ConcurrentHashMap import sbt.internal.inc.Stamper import xsbti.{ FileConverter, VirtualFile, VirtualFileRef } +import xsbti.compile.DefinesClass import xsbti.compile.analysis.{ Stamp => XStamp } +import sbt.internal.inc.Locate /** * Cache based on path and its stamp. @@ -22,6 +24,12 @@ sealed trait VirtualFileValueCache[A] { } object VirtualFileValueCache { + def definesClassCache(converter: FileConverter): VirtualFileValueCache[DefinesClass] = { + apply(converter) { x: VirtualFile => + if (x.name.toString != "rt.jar") Locate.definesClass(x) + else (_: String) => false + } + } def apply[A](converter: FileConverter)(f: VirtualFile => A): VirtualFileValueCache[A] = { import collection.mutable.{ HashMap, Map } val stampCache: Map[VirtualFileRef, (Long, XStamp)] = new HashMap