Deprecating old APIs and attempting to document behavior correctly.

* Removed as many binary incompatibilities as I could find.
* Deprecating old APIs
* Attempt to construct new nomenclature that fits the design of Incremental API.
* Add as much documentation as I was comfortable writing (from my understanding of things).
This commit is contained in:
Josh Suereth 2014-11-04 11:08:50 -05:00
parent 0f784ab101
commit 40bf599f4a
8 changed files with 334 additions and 42 deletions

View File

@ -20,11 +20,9 @@ import xsbti.api.Source
import xsbti.compile.{ CompileOrder, DependencyChanges, GlobalsCache, Output, SingleOutput, MultipleOutput, CompileProgress }
import CompileOrder.{ JavaThenScala, Mixed, ScalaThenJava }
final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File],
val previousAnalysis: Analysis, val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val progress: Option[CompileProgress], val getAnalysis: File => Option[Analysis], val definesClass: DefinesClass,
val reporter: Reporter, val compiler: AnalyzingCompiler, val javac: xsbti.compile.JavaCompiler, val cache: GlobalsCache, val incOptions: IncOptions)
class AggressiveCompile {
@deprecated("0.13.8", "Use MixedAnalyzingCompiler instead.")
class AggressiveCompile(cacheFile: File) {
@deprecated("0.13.8", "Use MixedAnalyzingCompiler.analyzingCompile instead.")
def apply(compiler: AnalyzingCompiler,
javac: xsbti.compile.JavaCompiler,
sources: Seq[File], classpath: Seq[File],
@ -33,20 +31,17 @@ class AggressiveCompile {
progress: Option[CompileProgress] = None,
options: Seq[String] = Nil,
javacOptions: Seq[String] = Nil,
previousAnalysis: Analysis,
previousSetup: Option[CompileSetup],
analysisMap: File => Option[Analysis] = { _ => None },
definesClass: DefinesClass = Locate.definesClass _,
reporter: Reporter,
compileOrder: CompileOrder = Mixed,
skip: Boolean = false,
incrementalCompilerOptions: IncOptions)(implicit log: Logger): (Analysis, CompileSetup, Boolean) =
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Analysis =
{
val setup = new CompileSetup(output, new CompileOptions(options, javacOptions),
compiler.scalaInstance.actualVersion, compileOrder, incrementalCompilerOptions.nameHashing)
val (analysis, modified) = compile1(sources, classpath, setup, progress, previousAnalysis, previousSetup, analysisMap, definesClass,
compile1(sources, classpath, setup, progress, store, analysisMap, definesClass,
compiler, javac, reporter, skip, cache, incrementalCompilerOptions)
(analysis, setup, modified)
}
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
@ -55,23 +50,25 @@ class AggressiveCompile {
def compile1(sources: Seq[File],
classpath: Seq[File],
setup: CompileSetup, progress: Option[CompileProgress],
previousAnalysis: Analysis,
previousSetup: Option[CompileSetup],
store: AnalysisStore,
analysis: File => Option[Analysis],
definesClass: DefinesClass,
compiler: AnalyzingCompiler,
javac: xsbti.compile.JavaCompiler,
reporter: Reporter, skip: Boolean,
cache: GlobalsCache,
incrementalCompilerOptions: IncOptions)(implicit log: Logger): (Analysis, Boolean) =
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Analysis =
{
val (previousAnalysis, previousSetup) = extract(store.get(), incrementalCompilerOptions)
if (skip)
(previousAnalysis, false)
previousAnalysis
else {
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup,
progress, analysis, definesClass, reporter, compiler, javac, cache, incrementalCompilerOptions)
val (modified, result) = compile2(config)
(result, modified)
if (modified)
store.set(result, setup)
result
}
}
def compile2(config: CompileConfiguration)(implicit log: Logger, equiv: Equiv[CompileSetup]): (Boolean, Analysis) =
@ -177,12 +174,20 @@ class AggressiveCompile {
if (!combined.isEmpty)
log.info(combined.mkString("Compiling ", " and ", " to " + outputDirs.map(_.getAbsolutePath).mkString(",") + "..."))
}
private def extract(previous: Option[(Analysis, CompileSetup)], incOptions: IncOptions): (Analysis, Option[CompileSetup]) =
previous match {
case Some((an, setup)) => (an, Some(setup))
case None => (Analysis.empty(nameHashing = incOptions.nameHashing), None)
}
def javaOnly(f: File) = f.getName.endsWith(".java")
private[this] def explicitBootClasspath(options: Seq[String]): Seq[File] =
options.dropWhile(_ != CompilerArguments.BootClasspathOption).drop(1).take(1).headOption.toList.flatMap(IO.parseClasspath)
val store = AggressiveCompile.staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
}
@deprecated("0.13.8", "Use MixedAnalyzingCompiler instead.")
object AggressiveCompile {
import collection.mutable
import java.lang.ref.{ Reference, SoftReference }

View File

@ -0,0 +1,41 @@
package sbt.compiler
import java.io.File
import sbt.CompileSetup
import sbt.inc.{ IncOptions, Analysis }
import sbt.inc.Locate._
import xsbti.Reporter
import xsbti.compile.{ GlobalsCache, CompileProgress }
/**
* Configuration used for running an analyzing compiler (a compiler which can extract dependencies between source files and JARs).
*
* @param sources
* @param classpath
* @param previousAnalysis
* @param previousSetup
* @param currentSetup
* @param progress
* @param getAnalysis
* @param definesClass
* @param reporter
* @param compiler
* @param javac
* @param cache
* @param incOptions
*/
final class CompileConfiguration(
val sources: Seq[File],
val classpath: Seq[File],
val previousAnalysis: Analysis,
val previousSetup: Option[CompileSetup],
val currentSetup: CompileSetup,
val progress: Option[CompileProgress],
val getAnalysis: File => Option[Analysis],
val definesClass: DefinesClass,
val reporter: Reporter,
val compiler: AnalyzingCompiler,
val javac: xsbti.compile.JavaCompiler,
val cache: GlobalsCache,
val incOptions: IncOptions)

View File

@ -6,31 +6,37 @@ import sbt.inc.{ Analysis, IncOptions, TextAnalysisFormat }
import xsbti.{ Logger, Maybe }
import xsbti.compile._
/**
* An implementation of the incremetnal compiler that can compile inputs and dump out source dependency analysis.
*/
object IC extends IncrementalCompiler[Analysis, AnalyzingCompiler] {
def compile(in: Inputs[Analysis, AnalyzingCompiler], log: Logger): Analysis =
{
val setup = in.setup; import setup._
val options = in.options; import options.{ options => scalacOptions, _ }
val compilers = in.compilers; import compilers._
val agg = new AggressiveCompile
val aMap = (f: File) => m2o(analysisMap(f))
val defClass = (f: File) => { val dc = definesClass(f); (name: String) => dc.apply(name) }
val incOptions = IncOptions.fromStringMap(incrementalCompilerOptions)
val (previousAnalysis, previousSetup) = {
AggressiveCompile.staticCachedStore(setup.cacheFile()).get().map {
MixedAnalyzingCompiler.staticCachedStore(setup.cacheFile()).get().map {
case (a, s) => (a, Some(s))
} getOrElse {
(Analysis.empty(nameHashing = incOptions.nameHashing), None)
}
}
agg(scalac, javac, sources, classpath, output, cache, m2o(progress), scalacOptions, javacOptions, previousAnalysis,
previousSetup, aMap, defClass, reporter, order, skip, incOptions)(log)._1
MixedAnalyzingCompiler.analyzingCompile(scalac, javac, sources, classpath, output, cache, m2o(progress), scalacOptions, javacOptions, previousAnalysis,
previousSetup, aMap, defClass, reporter, order, skip, incOptions)(log).analysis
}
private[this] def m2o[S](opt: Maybe[S]): Option[S] = if (opt.isEmpty) None else Some(opt.get)
@deprecated("0.13.8", "A constructor is no longer needed.")
def newScalaCompiler(instance: ScalaInstance, interfaceJar: File, options: ClasspathOptions, log: Logger): AnalyzingCompiler =
new AnalyzingCompiler(instance, CompilerInterfaceProvider.constant(interfaceJar), options, log)
new AnalyzingCompiler(instance, CompilerInterfaceProvider.constant(interfaceJar), options)
def newScalaCompiler(instance: ScalaInstance, interfaceJar: File, options: ClasspathOptions): AnalyzingCompiler =
new AnalyzingCompiler(instance, CompilerInterfaceProvider.constant(interfaceJar), options)
def compileInterfaceJar(label: String, sourceJar: File, targetJar: File, interfaceJar: File, instance: ScalaInstance, log: Logger) {
val raw = new RawCompiler(instance, sbt.ClasspathOptions.auto, log)

View File

@ -0,0 +1,229 @@
package sbt.compiler
import java.io.File
import java.lang.ref.{ SoftReference, Reference }
import sbt.classfile.Analyze
import sbt.classpath.ClasspathUtilities
import sbt.inc.Locate.DefinesClass
import sbt._
import sbt.inc._
import sbt.inc.Locate
import xsbti.{ AnalysisCallback, Reporter }
import xsbti.api.Source
import xsbti.compile.CompileOrder._
import xsbti.compile._
/**
* This is a compiler that mixes the `sbt.compiler.AnalyzingCompiler` for Scala incremental compilation
* with a `xsbti.JavaCompiler`, allowing cross-compilation of mixed Java/Scala projects with analysis output.
*/
object MixedAnalyzingCompiler {
/** The result of running the compilation. */
final case class Result(analysis: Analysis, setup: CompileSetup, hasModified: Boolean)
/**
* This will run a mixed-compilation of Java/Scala sources
* @param scalac An instances of the Scalac compiler which can also extract "Analysis" (dependencies)
* @param javac An instance of the Javac compiler.
* @param sources The set of sources to compile
* @param classpath The classpath to use when compiling.
* @param output Configuration for where to output .class files.
* @param cache The caching mechanism to use instead of insantiating new compiler instances.
* @param progress Progress listening for the compilation process. TODO - Feed this through the Javac Compiler!
* @param options Options for the Scala compiler
* @param javacOptions Options for the Java compiler
* @param previousAnalysis The previous dependency Analysis object/
* @param previousSetup The previous compilation setup (if any)
* @param analysisMap A map of file to the dependency analysis of that file.
* @param definesClass A mehcnaism of looking up whether or not a JAR defines a particular Class.
* @param reporter Where we sent all compilation error/warning events
* @param compileOrder The order we'd like to mix compilation. JavaThenScala, ScalaThenJava or Mixed.
* @param skip IF true, we skip compilation and just return the previous analysis file.
* @param incrementalCompilerOptions Options specific to incremental compilation.
* @param log The location where we write log messages.
* @return The full configuration used to instantiate this mixed-analyzing compiler, the set of extracted dependencies and
* whether or not any file were modified.
*/
def analyzingCompile(scalac: AnalyzingCompiler,
javac: xsbti.compile.JavaCompiler,
sources: Seq[File],
classpath: Seq[File],
output: Output,
cache: GlobalsCache,
progress: Option[CompileProgress] = None,
options: Seq[String] = Nil,
javacOptions: Seq[String] = Nil,
previousAnalysis: Analysis,
previousSetup: Option[CompileSetup],
analysisMap: File => Option[Analysis] = { _ => None },
definesClass: DefinesClass = Locate.definesClass _,
reporter: Reporter,
compileOrder: CompileOrder = Mixed,
skip: Boolean = false,
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Result =
{
val setup = new CompileSetup(output, new CompileOptions(options, javacOptions),
scalac.scalaInstance.actualVersion, compileOrder, incrementalCompilerOptions.nameHashing)
val (analysis, modified) = compile1(sources, classpath, setup, progress, previousAnalysis, previousSetup, analysisMap, definesClass,
scalac, javac, reporter, skip, cache, incrementalCompilerOptions)
Result(analysis, setup, modified)
}
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
args.bootClasspathFor(classpath) ++ args.extClasspath ++ args.finishClasspath(classpath)
/**
* The first level of compilation. This checks to see if we need to skip compiling because of the skip flag,
* IF we're not skipping, this setups up the `CompileConfiguration` and delegates to `compile2`
*/
private def compile1(sources: Seq[File],
classpath: Seq[File],
setup: CompileSetup, progress: Option[CompileProgress],
previousAnalysis: Analysis,
previousSetup: Option[CompileSetup],
analysis: File => Option[Analysis],
definesClass: DefinesClass,
compiler: AnalyzingCompiler,
javac: xsbti.compile.JavaCompiler,
reporter: Reporter, skip: Boolean,
cache: GlobalsCache,
incrementalCompilerOptions: IncOptions)(implicit log: Logger): (Analysis, Boolean) =
{
if (skip)
(previousAnalysis, false)
else {
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup,
progress, analysis, definesClass, reporter, compiler, javac, cache, incrementalCompilerOptions)
val (modified, result) = compile2(config)
(result, modified)
}
}
/**
* This runs the actual compilation of Java + Scala. There are two helper methods which
* actually perform the compilation of Java or Scala. This method uses the compile order to determine
* which files to pass to which compilers.
*/
private def compile2(config: CompileConfiguration)(implicit log: Logger, equiv: Equiv[CompileSetup]): (Boolean, Analysis) =
{
import config._
import currentSetup._
val absClasspath = classpath.map(_.getAbsoluteFile)
val apiOption = (api: Either[Boolean, Source]) => api.right.toOption
val cArgs = new CompilerArguments(compiler.scalaInstance, compiler.cp)
val searchClasspath = explicitBootClasspath(options.options) ++ withBootclasspath(cArgs, absClasspath)
val entry = Locate.entry(searchClasspath, definesClass)
val compile0 = (include: Set[File], changes: DependencyChanges, callback: AnalysisCallback) => {
val outputDirs = outputDirectories(output)
outputDirs foreach (IO.createDirectory)
val incSrc = sources.filter(include)
val (javaSrcs, scalaSrcs) = incSrc partition javaOnly
logInputs(log, javaSrcs.size, scalaSrcs.size, outputDirs)
def compileScala() =
if (!scalaSrcs.isEmpty) {
val sources = if (order == Mixed) incSrc else scalaSrcs
val arguments = cArgs(Nil, absClasspath, None, options.options)
timed("Scala compilation", log) {
compiler.compile(sources, changes, arguments, output, callback, reporter, config.cache, log, progress)
}
}
def compileJava() =
if (!javaSrcs.isEmpty) {
import Path._
@annotation.tailrec def ancestor(f1: File, f2: File): Boolean =
if (f2 eq null) false else if (f1 == f2) true else ancestor(f1, f2.getParentFile)
val chunks: Map[Option[File], Seq[File]] = output match {
case single: SingleOutput => Map(Some(single.outputDirectory) -> javaSrcs)
case multi: MultipleOutput =>
javaSrcs groupBy { src =>
multi.outputGroups find { out => ancestor(out.sourceDirectory, src) } map (_.outputDirectory)
}
}
chunks.get(None) foreach { srcs =>
log.error("No output directory mapped for: " + srcs.map(_.getAbsolutePath).mkString(","))
}
val memo = for ((Some(outputDirectory), srcs) <- chunks) yield {
val classesFinder = PathFinder(outputDirectory) ** "*.class"
(classesFinder, classesFinder.get, srcs)
}
val loader = ClasspathUtilities.toLoader(searchClasspath)
timed("Java compilation", log) {
try javac.compileWithReporter(javaSrcs.toArray, absClasspath.toArray, output, options.javacOptions.toArray, reporter, log)
catch {
// Handle older APIs
case _: NoSuchMethodError =>
javac.compile(javaSrcs.toArray, absClasspath.toArray, output, options.javacOptions.toArray, log)
}
}
def readAPI(source: File, classes: Seq[Class[_]]): Set[String] = {
val (api, inherits) = ClassToAPI.process(classes)
callback.api(source, api)
inherits.map(_.getName)
}
timed("Java analysis", log) {
for ((classesFinder, oldClasses, srcs) <- memo) {
val newClasses = Set(classesFinder.get: _*) -- oldClasses
Analyze(newClasses.toSeq, srcs, log)(callback, loader, readAPI)
}
}
}
if (order == JavaThenScala) { compileJava(); compileScala() } else { compileScala(); compileJava() }
}
val sourcesSet = sources.toSet
val analysis = previousSetup match {
case Some(previous) if previous.nameHashing != currentSetup.nameHashing =>
// if the value of `nameHashing` flag has changed we have to throw away
// previous Analysis completely and start with empty Analysis object
// that supports the particular value of the `nameHashing` flag.
// Otherwise we'll be getting UnsupportedOperationExceptions
Analysis.empty(currentSetup.nameHashing)
case Some(previous) if equiv.equiv(previous, currentSetup) => previousAnalysis
case _ => Incremental.prune(sourcesSet, previousAnalysis)
}
IncrementalCompile(sourcesSet, entry, compile0, analysis, getAnalysis, output, log, incOptions)
}
private[this] def outputDirectories(output: Output): Seq[File] = output match {
case single: SingleOutput => List(single.outputDirectory)
case mult: MultipleOutput => mult.outputGroups map (_.outputDirectory)
}
private[this] def timed[T](label: String, log: Logger)(t: => T): T =
{
val start = System.nanoTime
val result = t
val elapsed = System.nanoTime - start
log.debug(label + " took " + (elapsed / 1e9) + " s")
result
}
private[this] def logInputs(log: Logger, javaCount: Int, scalaCount: Int, outputDirs: Seq[File]) {
val scalaMsg = Analysis.counted("Scala source", "", "s", scalaCount)
val javaMsg = Analysis.counted("Java source", "", "s", javaCount)
val combined = scalaMsg ++ javaMsg
if (!combined.isEmpty)
log.info(combined.mkString("Compiling ", " and ", " to " + outputDirs.map(_.getAbsolutePath).mkString(",") + "..."))
}
/** Returns true if the file is java. */
def javaOnly(f: File) = f.getName.endsWith(".java")
private[this] def explicitBootClasspath(options: Seq[String]): Seq[File] =
options.dropWhile(_ != CompilerArguments.BootClasspathOption).drop(1).take(1).headOption.toList.flatMap(IO.parseClasspath)
private[this] val cache = new collection.mutable.HashMap[File, Reference[AnalysisStore]]
private def staticCache(file: File, backing: => AnalysisStore): AnalysisStore =
synchronized {
cache get file flatMap { ref => Option(ref.get) } getOrElse {
val b = backing
cache.put(file, new SoftReference(b))
b
}
}
/** Create a an analysis store cache at the desired location. */
def staticCachedStore(cacheFile: File) = staticCache(cacheFile, AnalysisStore.sync(AnalysisStore.cached(FileBasedStore(cacheFile))))
}

View File

@ -3,6 +3,9 @@ package xsbti.compile;
import xsbti.Logger;
import xsbti.Reporter;
/**
* An interface which lets us know how to retrieve cached compiler instances form the current JVM.
*/
public interface GlobalsCache
{
public CachedCompiler apply(String[] args, Output output, boolean forceNew, CachedCompilerProvider provider, Logger log, Reporter reporter);

View File

@ -18,10 +18,10 @@ object Compiler {
final case class Inputs(compilers: Compilers, config: Options, incSetup: IncSetup, previousAnalysis: PreviousAnalysis)
final case class Options(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String], javacOptions: Seq[String], maxErrors: Int, sourcePositionMapper: Position => Position, order: CompileOrder)
final case class IncSetup(analysisMap: File => Option[Analysis], definesClass: DefinesClass, skip: Boolean, cacheFile: File, cache: GlobalsCache, incOptions: IncOptions)
<<<<<<< HEAD
private[sbt] trait JavaToolWithNewInterface extends JavaTool {
def newJavac: IncrementalCompilerJavaTools
}
/** The instances of Scalac/Javac used to compile the current project. */
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaTool) {
final def newJavac: Option[IncrementalCompilerJavaTools] =
javac match {
@ -29,12 +29,9 @@ object Compiler {
case _ => None
}
}
final case class NewCompilers(scalac: AnalyzingCompiler, javac: JavaTools)
=======
final case class Compilers(scalac: AnalyzingCompiler, javac: JavaTool)
/** The previous source dependency analysis result from compilation. */
final case class PreviousAnalysis(analysis: Analysis, setup: Option[CompileSetup])
final case class AnalysisResult(analysis: Analysis, setup: CompileSetup, modified: Boolean)
>>>>>>> Allow bytecode enhancement to update analysis
type CompileResult = MixedAnalyzingCompiler.Result
def inputs(classpath: Seq[File], sources: Seq[File], classesDirectory: File, options: Seq[String],
javacOptions: Seq[String], maxErrors: Int, sourcePositionMappers: Seq[Position => Option[Position]],
@ -86,27 +83,37 @@ object Compiler {
val launcher = app.provider.scalaProvider.launcher
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, Option(launcher.ivyHome), log)
val provider = ComponentCompiler.interfaceProvider(componentManager)
new AnalyzingCompiler(instance, provider, cpOptions, log)
new AnalyzingCompiler(instance, provider, cpOptions)
}
def apply(in: Inputs, log: Logger): AnalysisResult =
@deprecated("0.13.8", "Use the `compile` method instead.")
def apply(in: Inputs, log: Logger): Analysis =
{
import in.compilers._
import in.config._
import in.incSetup._
apply(in, log, new LoggerReporter(maxErrors, log, sourcePositionMapper))
}
def apply(in: Inputs, log: Logger, reporter: xsbti.Reporter): AnalysisResult =
@deprecated("0.13.8", "Use the `compile` method instead.")
def apply(in: Inputs, log: Logger, reporter: xsbti.Reporter): Analysis = compile(in, log, reporter).analysis
def compile(in: Inputs, log: Logger): CompileResult =
{
import in.compilers._
import in.config._
import in.incSetup._
compile(in, log, new LoggerReporter(maxErrors, log, sourcePositionMapper))
}
def compile(in: Inputs, log: Logger, reporter: xsbti.Reporter): CompileResult =
{
import in.compilers._
import in.config._
import in.incSetup._
val agg = new AggressiveCompile(cacheFile)
// Here is some trickery to choose the more recent (reporter-using) java compiler rather
// than the previously defined versions.
// TODO - Remove this hackery in sbt 1.0.
val javacChosen: xsbti.compile.JavaCompiler =
in.compilers.newJavac.map(_.xsbtiCompiler).getOrElse(in.compilers.javac)
agg(scalac, javacChosen, sources, classpath, CompileOutput(classesDirectory), cache, None, options, javacOptions,
MixedAnalyzingCompiler.analyzingCompile(scalac, javacChosen, sources, classpath, CompileOutput(classesDirectory), cache, None, options, javacOptions,
in.previousAnalysis.analysis, in.previousAnalysis.setup, analysisMap, definesClass, reporter, order, skip, incOptions)(log)
}

View File

@ -15,7 +15,7 @@ import CrossVersion.{ binarySbtVersion, binaryScalaVersion, partialVersion }
import complete._
import std.TaskExtra._
import sbt.inc.{ Analysis, FileValueCache, IncOptions, Locate }
import sbt.compiler.AggressiveCompile
import sbt.compiler.{ MixedAnalyzingCompiler, AggressiveCompile }
import testing.{ Framework, Runner, AnnotatedFingerprint, SubclassFingerprint }
import sys.error
@ -650,7 +650,7 @@ object Defaults extends BuildCommon {
key in TaskGlobal <<= packageTask,
packageConfiguration <<= packageConfigurationTask,
mappings <<= mappingsTask,
packagedArtifact := (artifact.value, key.value),
packagedArtifact := (artifact.value -> key.value),
artifact <<= artifactSetting,
artifactPath <<= artifactPathSetting(artifact)
))
@ -784,14 +784,14 @@ object Defaults extends BuildCommon {
def compileIncrementalTask = Def.task {
compileIncrementalTaskImpl(streams.value, (compileInputs in compile).value, (compilerReporter in compile).value)
}
private[this] def compileIncrementalTaskImpl(s: TaskStreams, ci: Compiler.Inputs, reporter: Option[xsbti.Reporter]): Compiler.AnalysisResult =
private[this] def compileIncrementalTaskImpl(s: TaskStreams, ci: Compiler.Inputs, reporter: Option[xsbti.Reporter]): Compiler.CompileResult =
{
lazy val x = s.text(ExportStream)
def onArgs(cs: Compiler.Compilers) = cs.copy(scalac = cs.scalac.onArgs(exported(x, "scalac")), javac = cs.javac.onArgs(exported(x, "javac")))
val i = ci.copy(compilers = onArgs(ci.compilers))
try reporter match {
case Some(reporter) => Compiler(i, s.log, reporter)
case None => Compiler(i, s.log)
case Some(reporter) => Compiler.compile(i, s.log, reporter)
case None => Compiler.compile(i, s.log)
}
finally x.close() // workaround for #937
}
@ -823,9 +823,9 @@ object Defaults extends BuildCommon {
},
saveAnalysis := {
val setup: Compiler.IncSetup = compileIncSetup.value
val analysisResult: Compiler.AnalysisResult = compileIncremental.value
if (analysisResult.modified) {
val store = AggressiveCompile.staticCachedStore(setup.cacheFile)
val analysisResult: Compiler.CompileResult = compileIncremental.value
if (analysisResult.hasModified) {
val store = MixedAnalyzingCompiler.staticCachedStore(setup.cacheFile)
store.set(analysisResult.analysis, analysisResult.setup)
}
analysisResult.analysis
@ -1031,7 +1031,7 @@ object Classpaths {
packagedArtifacts :== Map.empty,
crossTarget := target.value,
makePom := { val config = makePomConfiguration.value; IvyActions.makePom(ivyModule.value, config, streams.value.log); config.file },
packagedArtifact in makePom := (artifact in makePom value, makePom value),
packagedArtifact in makePom := ((artifact in makePom).value -> makePom.value),
deliver <<= deliverTask(deliverConfiguration),
deliverLocal <<= deliverTask(deliverLocalConfiguration),
publish <<= publishTask(publishConfiguration, deliver),
@ -1510,7 +1510,7 @@ object Classpaths {
def visit(p: ProjectRef, c: Configuration) {
val applicableConfigs = allConfigs(c)
for (ac <- applicableConfigs) // add all configurations in this project
visited add (p, ac.name)
visited add (p -> ac.name)
val masterConfs = names(getConfigurations(projectRef, data))
for (ResolvedClasspathDependency(dep, confMapping) <- deps.classpath(p)) {

View File

@ -9,6 +9,7 @@ import Def.ScopedKey
import complete._
import inc.Analysis
import inc.Locate.DefinesClass
import sbt.compiler.MixedAnalyzingCompiler
import std.TaskExtra._
import xsbti.compile.{ CompileOrder, GlobalsCache }
import scala.xml.{ Node => XNode, NodeSeq }
@ -141,7 +142,7 @@ object Keys {
val consoleQuick = TaskKey[Unit]("console-quick", "Starts the Scala interpreter with the project dependencies on the classpath.", ATask, console)
val consoleProject = TaskKey[Unit]("console-project", "Starts the Scala interpreter with the sbt and the build definition on the classpath and useful imports.", AMinusTask)
val compile = TaskKey[Analysis]("compile", "Compiles sources.", APlusTask)
val compileIncremental = TaskKey[Compiler.AnalysisResult]("compileIncremental", "Actually runs the incremental compliation", DTask)
val compileIncremental = TaskKey[Compiler.CompileResult]("compileIncremental", "Actually runs the incremental compliation", DTask)
val readAnalysis = TaskKey[Compiler.PreviousAnalysis]("readAnalysis", "Read the incremental compiler analysis from disk", DTask)
val saveAnalysis = TaskKey[Analysis]("saveAnalysis", "Save the incremental compiler analysis to disk", DTask)
val compilers = TaskKey[Compiler.Compilers]("compilers", "Defines the Scala and Java compilers to use for compilation.", DTask)