mirror of https://github.com/sbt/sbt.git
Add `compilations` field to `Analysis`.
We store `Seq[xsbt.api.Compilation]` in `Analysis`. Compilation are being appended to sequence for every iteration of the incremental compiler. Note that `Compilation`s are never removed from the sequence unless you start from scratch with empty `Analysis`. You can do that by using sbt's `clean` command. The main use-case for using `compilations` field is to determine how many iterations it took to compilen give code. The `Compilation` object are also stored in `Source` objects so there's an indirect way to recover information about files being recompiled in every iteration. Since `Analysis` is persisted you can use this mechanism to track entire sessions spanning multiple `compile` commands.
This commit is contained in:
parent
532c72e60e
commit
78b0f485fa
|
|
@ -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)) ) :_*)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)) =>
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue