Skip to content

Commit

Permalink
Moved prev jar path generation and resolving to AnalysisCallback
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszwawrzyk committed Oct 1, 2018
1 parent 596d58c commit 31484ad
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,11 @@ sealed class ZincCompiler(settings: Settings, dreporter: DelegatingReporter, out
this.computePhaseDescriptors
}

private final val classesInJarFromPrevCompilation =
perRunCaches.recordCache(new JarUtils.PrevJarCache(settings.classpath.value))
private final lazy val classesInJarFromPrevCompilation = {
val prevJarOptional = callback.previousJar()
val prevJar = if (prevJarOptional.isPresent) Some(prevJarOptional.get) else None
perRunCaches.recordCache(new JarUtils.PrevJarCache(prevJar))
}

private final val fqnsToAssociatedFiles = perRunCaches.newMap[String, (AbstractFile, Boolean)]()

Expand Down
22 changes: 2 additions & 20 deletions internal/compiler-bridge/src/main/scala/xsbt/JarUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,11 @@ final class JarUtils(outputDirs: Iterable[File]) {

/**
* Class that holds cached list of paths located within previous jar for quick lookup.
* See [[sbt.internal.inc.JarUtils#withPreviousJar]] for details on what previous jar is.
* The previous jar is located using the classpath (if it exists it is a first entry
* and has a special prefix.
*
* @param rawClasspath the classpath in a single string (entries separated with [[File.pathSeparator]])
* @see sbt.internal.inc.JarUtils#withPreviousJar for details on what previous jar is
*/
class PrevJarCache(rawClasspath: String) extends scala.collection.generic.Clearable {
class PrevJarCache(prevJar: Option[File]) extends scala.collection.generic.Clearable {
private var cache: Set[ClassInJar] = _

private lazy val prevJar = {
val classpath = rawClasspath.split(File.pathSeparator)
findPrevJar(classpath)
}

def contains(classInJar: ClassInJar): Boolean = {
if (cache == null) {
cache = loadEntriesFromPrevJar()
Expand All @@ -98,13 +89,4 @@ final class JarUtils(outputDirs: Iterable[File]) {
}
}

private def findPrevJar(classpath: Seq[String]): Option[File] = {
classpath.headOption.map(new File(_)).filter { path =>
val fileName = path.getName
fileName.startsWith(prevJarPrefix) && fileName.endsWith(".jar")
}
}

private val prevJarPrefix: String = "prev-jar"

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import xsbti.api.DependencyContext;
import java.io.File;
import java.util.EnumSet;
import java.util.Optional;

public interface AnalysisCallback {
/**
Expand Down Expand Up @@ -172,4 +173,13 @@ void problem(String what,
* phase defined by <code>xsbt-analyzer</code> should be added.
*/
boolean enabled();

/**
* Returns path to a jar generated in previous compilation if it exists
* and compilation to jar is enabled.
*
* @see sbt.internal.inc.JarUtils#withPreviousJar for more information.
*/
Optional<File> previousJar();

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package xsbti

import java.io.File
import java.util
import java.util.Optional

import xsbti.api.{ ClassLike, DependencyContext }
import xsbti.api.{ DependencyContext, ClassLike }

import scala.collection.mutable.ArrayBuffer

Expand Down Expand Up @@ -77,6 +78,9 @@ class TestCallback extends AnalysisCallback {
override def dependencyPhaseCompleted(): Unit = {}

override def apiPhaseCompleted(): Unit = {}

override def previousJar(): Optional[File] = Optional.empty[File]

}

object TestCallback {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import java.io.File
import java.util.UUID

import scala.collection.JavaConverters._

import sbt.io.syntax.URL
import xsbti.AnalysisCallback
import xsbti.compile.{ Output, SingleOutput }
import sbt.util.InterfaceUtil.toOption

/**
* This is a utility class that provides a set of functions that
Expand Down Expand Up @@ -183,35 +184,36 @@ object JarUtils {
* compilation.
*
* @param output output for scalac compilation
* @param callback analysis callback used to set previus jar
* @param compile function that given extra classpath for compiler runs the compilation
*/
def withPreviousJar[A](output: Output)(compile: /*extra classpath: */ Seq[File] => A): A = {
getOutputJar(output)
.filter(_.exists())
.map { outputJar =>
val prevJar = createPrevJarPath()
IO.move(outputJar, prevJar)

val result = try {
compile(Seq(prevJar))
} catch {
case e: Exception =>
IO.move(prevJar, outputJar)
throw e
}

if (outputJar.exists()) {
JarUtils.mergeJars(into = prevJar, from = outputJar)
}
IO.move(prevJar, outputJar)
result
def withPreviousJar[A](output: Output, callback: AnalysisCallback)(
compile: /*extra classpath: */ Seq[File] => A): A = {
(for {
outputJar <- getOutputJar(output)
prevJar <- toOption(callback.previousJar())
} yield {
IO.move(outputJar, prevJar)

val result = try {
compile(Seq(prevJar))
} catch {
case e: Exception =>
IO.move(prevJar, outputJar)
throw e
}
.getOrElse {
compile(Nil)

if (outputJar.exists()) {
JarUtils.mergeJars(into = prevJar, from = outputJar)
}
IO.move(prevJar, outputJar)
result
}).getOrElse {
compile(Nil)
}
}

private def createPrevJarPath(): File = {
def createPrevJarPath(): File = {
val tempDir =
sys.props.get("zinc.compile-to-jar.tmp-dir").map(new File(_)).getOrElse(IO.temporaryDirectory)
val prevJarName = s"$prevJarPrefix-${UUID.randomUUID()}.jar"
Expand Down
17 changes: 12 additions & 5 deletions internal/zinc-core/src/main/scala/sbt/internal/inc/Compile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ package internal
package inc

import sbt.internal.inc.Analysis.{ LocalProduct, NonLocalProduct }
import xsbt.api.{ APIUtil, HashAPI, NameHashing }
import xsbt.api.{ APIUtil, NameHashing, HashAPI }
import xsbti.api._
import xsbti.compile.{
ClassFileManager => XClassFileManager,
Expand All @@ -23,15 +23,13 @@ import xsbti.{ Position, Problem, Severity, UseScope }
import sbt.util.Logger
import sbt.util.InterfaceUtil.jo2o
import java.io.File
import java.net.URL
import java.util
import java.util.Optional
import sbt.internal.inc.JavaInterfaceUtil.EnrichOption

import sbt.io.IO
import xsbti.api.DependencyContext
import xsbti.compile.analysis.ReadStamps

import scala.util.Try

/**
* Helper methods for running incremental compilation. All this is responsible for is
* adapting any xsbti.AnalysisCallback into one compatible with the [[sbt.internal.inc.Incremental]] class.
Expand Down Expand Up @@ -176,6 +174,12 @@ private final class AnalysisCallback(
private[this] val binaryClassName = new HashMap[File, String]
// source files containing a macro def.
private[this] val macroClasses = Set[String]()
private[this] val prevJar = {
JarUtils
.getOutputJar(output)
.filter(_.exists())
.map(_ => JarUtils.createPrevJarPath())
}

private def add[A, B](map: Map[A, Set[B]], a: A, b: B): Unit = {
map.getOrElseUpdate(a, new HashSet[B]) += b
Expand Down Expand Up @@ -409,4 +413,7 @@ private final class AnalysisCallback(
override def dependencyPhaseCompleted(): Unit = {}

override def apiPhaseCompleted(): Unit = {}

override def previousJar(): Optional[File] = prevJar.toOptional

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ final class MixedAnalyzingCompiler(
/** Compile Scala sources. */
def compileScala(): Unit =
if (scalaSrcs.nonEmpty) {
JarUtils.withPreviousJar(output) { extraClasspath =>
JarUtils.withPreviousJar(output, callback) { extraClasspath =>
val sources = if (config.currentSetup.order == Mixed) incSrc else scalaSrcs
val arguments = cArgs(Nil,
toAbsolute(extraClasspath) ++ absClasspath,
Expand Down

0 comments on commit 31484ad

Please sign in to comment.