diff --git a/compile/inc/src/main/scala/sbt/inc/Analysis.scala b/compile/inc/src/main/scala/sbt/inc/Analysis.scala index c3cf3f1ab..3443aeeda 100644 --- a/compile/inc/src/main/scala/sbt/inc/Analysis.scala +++ b/compile/inc/src/main/scala/sbt/inc/Analysis.scala @@ -13,10 +13,13 @@ trait Analysis val apis: APIs val relations: Relations val infos: SourceInfos + /** Information about compiler runs accumulated since `clean` command has been run. */ + val compilations: Compilations def ++(other: Analysis): Analysis def -- (sources: Iterable[File]): Analysis - def copy(stamps: Stamps = stamps, apis: APIs = apis, relations: Relations = relations, infos: SourceInfos = infos): Analysis + def copy(stamps: Stamps = stamps, apis: APIs = apis, relations: Relations = relations, infos: SourceInfos = infos, + compilations: Compilations = compilations): Analysis def addSource(src: File, api: Source, stamp: Stamp, internalDeps: Iterable[File], info: SourceInfo): Analysis def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis @@ -30,7 +33,7 @@ trait Analysis object Analysis { - lazy val Empty: Analysis = new MAnalysis(Stamps.empty, APIs.empty, Relations.empty, SourceInfos.empty) + lazy val Empty: Analysis = new MAnalysis(Stamps.empty, APIs.empty, Relations.empty, SourceInfos.empty, Compilations.empty) def summary(a: Analysis): String = { val (j, s) = a.apis.allInternalSources.partition(_.getName.endsWith(".java")) @@ -57,9 +60,11 @@ object Analysis } } -private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relations, val infos: SourceInfos) extends Analysis +private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relations, val infos: SourceInfos, + val compilations: Compilations) extends Analysis { - def ++ (o: Analysis): Analysis = new MAnalysis(stamps ++ o.stamps, apis ++ o.apis, relations ++ o.relations, infos ++ o.infos) + def ++ (o: Analysis): Analysis = new MAnalysis(stamps ++ o.stamps, apis ++ o.apis, relations ++ o.relations, + infos ++ o.infos, compilations ++ o.compilations) def -- (sources: Iterable[File]): Analysis = { val newRelations = relations -- sources @@ -68,9 +73,10 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat val newAPIs = apis.removeInternal(sources).filterExt( keep(_ usesExternal _) ) val newStamps = stamps.filter( keep(_ produced _), sources, keep(_ usesBinary _)) val newInfos = infos -- sources - new MAnalysis(newStamps, newAPIs, newRelations, newInfos) + new MAnalysis(newStamps, newAPIs, newRelations, newInfos, compilations) } - def copy(stamps: Stamps, apis: APIs, relations: Relations, infos: SourceInfos): Analysis = new MAnalysis(stamps, apis, relations, infos) + def copy(stamps: Stamps, apis: APIs, relations: Relations, infos: SourceInfos, compilations: Compilations = compilations): Analysis = + new MAnalysis(stamps, apis, relations, infos, compilations) def addSource(src: File, api: Source, stamp: Stamp, internalDeps: Iterable[File], info: SourceInfo): Analysis = copy( stamps.markInternalSource(src, stamp), apis.markInternalSource(src, api), relations.addInternalSrcDeps(src, internalDeps), infos.add(src, info) ) @@ -93,7 +99,8 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat stampsMap.getOrElse(k, Stamps.empty), apisMap.getOrElse(k, APIs.empty), relationsMap.getOrElse(k, Relations.empty), - infosMap.getOrElse(k, SourceInfos.empty) + infosMap.getOrElse(k, SourceInfos.empty), + compilations ) val keys = (stampsMap.keySet ++ apisMap.keySet ++ relationsMap.keySet ++ infosMap.keySet).toList Map( keys map( (k: K) => (k, kAnalysis(k)) ) :_*) diff --git a/compile/inc/src/main/scala/sbt/inc/Compilations.scala b/compile/inc/src/main/scala/sbt/inc/Compilations.scala new file mode 100644 index 000000000..86ab145d2 --- /dev/null +++ b/compile/inc/src/main/scala/sbt/inc/Compilations.scala @@ -0,0 +1,20 @@ +package sbt.inc + +import xsbti.api.Compilation + +/** Information about compiler runs accumulated since `clean` command has been run. */ +trait Compilations { + def allCompilations: Seq[Compilation] + def ++(o: Compilations): Compilations + def add(c: Compilation): Compilations +} + +object Compilations { + val empty: Compilations = new MCompilations(Seq.empty) + def make(s: Seq[Compilation]): Compilations = new MCompilations(s) +} + +private final class MCompilations(val allCompilations: Seq[Compilation]) extends Compilations { + def ++(o: Compilations): Compilations = new MCompilations(allCompilations ++ o.allCompilations) + def add(c: Compilation): Compilations = new MCompilations(allCompilations :+ c) +} diff --git a/compile/inc/src/main/scala/sbt/inc/Compile.scala b/compile/inc/src/main/scala/sbt/inc/Compile.scala index 8572af8d9..714edc94e 100644 --- a/compile/inc/src/main/scala/sbt/inc/Compile.scala +++ b/compile/inc/src/main/scala/sbt/inc/Compile.scala @@ -129,7 +129,7 @@ private final class AnalysisCallback(internalMap: File => Option[File], external def endSource(sourcePath: File): Unit = assert(apis.contains(sourcePath)) - def get: Analysis = addExternals( addBinaries( addProducts( addSources(Analysis.Empty) ) ) ) + def get: Analysis = addCompilation( addExternals( addBinaries( addProducts( addSources(Analysis.Empty) ) ) ) ) def addProducts(base: Analysis): Analysis = addAll(base, classes) { case (a, src, (prod, name)) => a.addProduct(src, prod, current product prod, name ) } def addBinaries(base: Analysis): Analysis = addAll(base, binaryDeps)( (a, src, bin) => a.addBinaryDep(src, bin, binaryClassName(bin), current binary bin) ) def addSources(base: Analysis): Analysis = @@ -144,6 +144,7 @@ private final class AnalysisCallback(internalMap: File => Option[File], external } def getOrNil[A,B](m: collection.Map[A, Seq[B]], a: A): Seq[B] = m.get(a).toList.flatten def addExternals(base: Analysis): Analysis = (base /: extSrcDeps) { case (a, (source, name, api)) => a.addExternalDep(source, name, api) } + def addCompilation(base: Analysis): Analysis = base.copy(compilations = base.compilations.add(compilation)) def addAll[A,B](base: Analysis, m: Map[A, Set[B]])( f: (Analysis, A, B) => Analysis): Analysis = (base /: m) { case (outer, (a, bs)) => diff --git a/compile/persist/src/main/scala/sbt/inc/AnalysisFormats.scala b/compile/persist/src/main/scala/sbt/inc/AnalysisFormats.scala index a80e4fd45..7f37f0b6b 100644 --- a/compile/persist/src/main/scala/sbt/inc/AnalysisFormats.scala +++ b/compile/persist/src/main/scala/sbt/inc/AnalysisFormats.scala @@ -4,7 +4,7 @@ package sbt package inc - import xsbti.api.Source + import xsbti.api.{Source, Compilation} import xsbti.{Position,Problem,Severity} import xsbti.compile.{CompileOrder, Output => APIOutput, SingleOutput, MultipleOutput} import MultipleOutput.OutputGroup @@ -45,8 +45,9 @@ object AnalysisFormats } } - implicit def analysisFormat(implicit stampsF: Format[Stamps], apisF: Format[APIs], relationsF: Format[Relations], infosF: Format[SourceInfos]): Format[Analysis] = - asProduct4( Analysis.Empty.copy _)( a => (a.stamps, a.apis, a.relations, a.infos))(stampsF, apisF, relationsF, infosF) + implicit def analysisFormat(implicit stampsF: Format[Stamps], apisF: Format[APIs], relationsF: Format[Relations], + infosF: Format[SourceInfos], compilationsF: Format[Compilations]): Format[Analysis] = + asProduct5( Analysis.Empty.copy _)( a => (a.stamps, a.apis, a.relations, a.infos, a.compilations))(stampsF, apisF, relationsF, infosF, compilationsF) implicit def infosFormat(implicit infoF: Format[Map[File, SourceInfo]]): Format[SourceInfos] = wrap[SourceInfos, Map[File, SourceInfo]]( _.allInfos, SourceInfos.make _) @@ -56,6 +57,11 @@ object AnalysisFormats implicit def problemFormat: Format[Problem] = asProduct4(problem _)( p => (p.category, p.position, p.message, p.severity)) + implicit def compilationsFormat: Format[Compilations] = { + implicit val compilationSeqF = seqFormat(xsbt.api.CompilationFormat) + wrap[Compilations, Seq[Compilation]](_.allCompilations, Compilations.make _) + } + implicit def positionFormat: Format[Position] = asProduct7( position _ )( p => (m2o(p.line), p.lineContent, m2o(p.offset), m2o(p.pointer), m2o(p.pointerSpace), m2o(p.sourcePath), m2o(p.sourceFile))) diff --git a/compile/persist/src/main/scala/xsbt/api/CompilationFormat.scala b/compile/persist/src/main/scala/xsbt/api/CompilationFormat.scala new file mode 100644 index 000000000..ac469b470 --- /dev/null +++ b/compile/persist/src/main/scala/xsbt/api/CompilationFormat.scala @@ -0,0 +1,16 @@ +package xsbt.api + +import xsbti.api._ +import sbinary._ + +object CompilationFormat extends Format[Compilation] { + import java.io._ + def reads(in: Input): Compilation = { + val oin = new ObjectInputStream(new InputWrapperStream(in)) + try { oin.readObject.asInstanceOf[Compilation] } finally { oin.close() } + } + def writes(out: Output, src: Compilation) { + val oout = new ObjectOutputStream(new OutputWrapperStream(out)) + try { oout.writeObject(src) } finally { oout.close() } + } +}