mirror of https://github.com/sbt/sbt.git
Merge pull request #1122 from gkossakowski/compile-setup-nameHashing
Include value of `nameHashing` flag in `CompileSetup`.
This commit is contained in:
commit
ef907b8c1d
|
|
@ -11,7 +11,8 @@ package sbt
|
|||
// because complexity(Equiv[Seq[String]]) > complexity(Equiv[CompileSetup])
|
||||
// (6 > 4)
|
||||
final class CompileOptions(val options: Seq[String], val javacOptions: Seq[String])
|
||||
final class CompileSetup(val output: APIOutput, val options: CompileOptions, val compilerVersion: String, val order: CompileOrder)
|
||||
final class CompileSetup(val output: APIOutput, val options: CompileOptions, val compilerVersion: String,
|
||||
val order: CompileOrder, val nameHashing: Boolean)
|
||||
|
||||
object CompileSetup
|
||||
{
|
||||
|
|
@ -21,7 +22,8 @@ object CompileSetup
|
|||
equivOutput.equiv(a.output, b.output) &&
|
||||
equivOpts.equiv(a.options, b.options) &&
|
||||
equivComp.equiv(a.compilerVersion, b.compilerVersion) &&
|
||||
a.order == b.order // equivOrder.equiv(a.order, b.order)
|
||||
a.order == b.order && // equivOrder.equiv(a.order, b.order)
|
||||
a.nameHashing == b.nameHashing
|
||||
}
|
||||
implicit val equivFile: Equiv[File] = new Equiv[File] {
|
||||
def equiv(a: File, b: File) = a.getAbsoluteFile == b.getAbsoluteFile
|
||||
|
|
@ -32,7 +34,7 @@ object CompileSetup
|
|||
case (m1: MultipleOutput, m2: MultipleOutput) =>
|
||||
(m1.outputGroups.length == m2.outputGroups.length) &&
|
||||
(m1.outputGroups.sorted zip m2.outputGroups.sorted forall {
|
||||
case (a,b) =>
|
||||
case (a,b) =>
|
||||
equivFile.equiv(a.sourceDirectory, b.sourceDirectory) && equivFile.equiv(a.outputDirectory, b.outputDirectory)
|
||||
})
|
||||
case (s1: SingleOutput, s2: SingleOutput) => equivFile.equiv(s1.outputDirectory, s2.outputDirectory)
|
||||
|
|
@ -42,12 +44,12 @@ object CompileSetup
|
|||
implicit val equivOpts: Equiv[CompileOptions] = new Equiv[CompileOptions] {
|
||||
def equiv(a: CompileOptions, b: CompileOptions) =
|
||||
(a.options sameElements b.options) &&
|
||||
(a.javacOptions sameElements b.javacOptions)
|
||||
(a.javacOptions sameElements b.javacOptions)
|
||||
}
|
||||
implicit val equivCompilerVersion: Equiv[String] = new Equiv[String] {
|
||||
def equiv(a: String, b: String) = a == b
|
||||
}
|
||||
|
||||
|
||||
implicit val equivOrder: Equiv[CompileOrder] = new Equiv[CompileOrder] {
|
||||
def equiv(a: CompileOrder, b: CompileOrder) = a == b
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ class AggressiveCompile(cacheFile: File)
|
|||
skip: Boolean = false,
|
||||
incrementalCompilerOptions: IncOptions)(implicit log: Logger): Analysis =
|
||||
{
|
||||
val setup = new CompileSetup(output, new CompileOptions(options, javacOptions), compiler.scalaInstance.actualVersion, compileOrder)
|
||||
val setup = new CompileSetup(output, new CompileOptions(options, javacOptions),
|
||||
compiler.scalaInstance.actualVersion, compileOrder, incrementalCompilerOptions.nameHashing)
|
||||
compile1(sources, classpath, setup, progress, store, analysisMap, definesClass,
|
||||
compiler, javac, reporter, skip, cache, incrementalCompilerOptions)
|
||||
}
|
||||
|
|
@ -144,6 +145,12 @@ class AggressiveCompile(cacheFile: File)
|
|||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ object AnalysisFormats
|
|||
wrap[Severity, Byte]( _.ordinal.toByte, b => Severity.values.apply(b.toInt) )
|
||||
|
||||
|
||||
implicit def setupFormat(implicit outputF: Format[APIOutput], optionF: Format[CompileOptions], compilerVersion: Format[String], orderF: Format[CompileOrder]): Format[CompileSetup] =
|
||||
asProduct4[CompileSetup, APIOutput, CompileOptions, String, CompileOrder]( (a,b,c,d) => new CompileSetup(a,b,c,d) )(s => (s.output, s.options, s.compilerVersion, s.order))(outputF, optionF, compilerVersion, orderF)
|
||||
implicit def setupFormat(implicit outputF: Format[APIOutput], optionF: Format[CompileOptions], compilerVersion: Format[String], orderF: Format[CompileOrder], nameHashingF: Format[Boolean]): Format[CompileSetup] =
|
||||
asProduct5[CompileSetup, APIOutput, CompileOptions, String, CompileOrder, Boolean]( (a,b,c,d,e) => new CompileSetup(a,b,c,d,e) )(s => (s.output, s.options, s.compilerVersion, s.order, s.nameHashing))(outputF, optionF, compilerVersion, orderF, nameHashingF)
|
||||
|
||||
implicit val outputGroupFormat: Format[OutputGroup] =
|
||||
asProduct2((a: File,b: File) => new OutputGroup{def sourceDirectory = a; def outputDirectory = b}) { out => (out.sourceDirectory, out.outputDirectory) }(fileFormat, fileFormat)
|
||||
|
|
|
|||
|
|
@ -57,31 +57,33 @@ object TextAnalysisFormat {
|
|||
|
||||
def write(out: Writer, analysis: Analysis, setup: CompileSetup) {
|
||||
VersionF.write(out)
|
||||
// We start with relations because that's the part of greatest interest to external readers,
|
||||
// We start with writing compile setup which contains value of the `nameHashing`
|
||||
// flag that is needed to properly deserialize relations
|
||||
FormatTimer.time("write setup") { CompileSetupF.write(out, setup) }
|
||||
// Next we write relations because that's the part of greatest interest to external readers,
|
||||
// who can abort reading early once they're read them.
|
||||
FormatTimer.time("write relations") { RelationsF.write(out, analysis.relations) }
|
||||
FormatTimer.time("write stamps") { StampsF.write(out, analysis.stamps) }
|
||||
FormatTimer.time("write apis") { APIsF.write(out, analysis.apis) }
|
||||
FormatTimer.time("write sourceinfos") { SourceInfosF.write(out, analysis.infos) }
|
||||
FormatTimer.time("write compilations") { CompilationsF.write(out, analysis.compilations) }
|
||||
FormatTimer.time("write setup") { CompileSetupF.write(out, setup) }
|
||||
out.flush()
|
||||
}
|
||||
|
||||
def read(in: BufferedReader): (Analysis, CompileSetup) = {
|
||||
VersionF.read(in)
|
||||
val relations = FormatTimer.time("read relations") { RelationsF.read(in) }
|
||||
val setup = FormatTimer.time("read setup") { CompileSetupF.read(in) }
|
||||
val relations = FormatTimer.time("read relations") { RelationsF.read(in, setup.nameHashing) }
|
||||
val stamps = FormatTimer.time("read stamps") { StampsF.read(in) }
|
||||
val apis = FormatTimer.time("read apis") { APIsF.read(in) }
|
||||
val infos = FormatTimer.time("read sourceinfos") { SourceInfosF.read(in) }
|
||||
val compilations = FormatTimer.time("read compilations") { CompilationsF.read(in) }
|
||||
val setup = FormatTimer.time("read setup") { CompileSetupF.read(in) }
|
||||
|
||||
(Analysis.Empty.copy(stamps, apis, relations, infos, compilations), setup)
|
||||
}
|
||||
|
||||
private[this] object VersionF {
|
||||
val currentVersion = "4"
|
||||
val currentVersion = "5"
|
||||
|
||||
def write(out: Writer) {
|
||||
out.write("format version: %s\n".format(currentVersion))
|
||||
|
|
@ -165,7 +167,7 @@ object TextAnalysisFormat {
|
|||
writeRelation(Headers.usedNames, names)
|
||||
}
|
||||
|
||||
def read(in: BufferedReader): Relations = {
|
||||
def read(in: BufferedReader, nameHashing: Boolean): Relations = {
|
||||
def readRelation[T](expectedHeader: String, s2t: String => T): Relation[File, T] = {
|
||||
val items = readPairs(in)(expectedHeader, new File(_), s2t).toIterator
|
||||
// Reconstruct the forward map. This is more efficient than Relation.empty ++ items.
|
||||
|
|
@ -216,9 +218,10 @@ object TextAnalysisFormat {
|
|||
}
|
||||
// we don't check for emptiness of publicInherited/inheritance relations because
|
||||
// we assume that invariant that says they are subsets of direct/memberRef holds
|
||||
assert((directSrcDeps == emptySource) || (memberRefSrcDeps == emptySourceDependencies),
|
||||
"One mechanism is supported for tracking source dependencies at the time")
|
||||
val nameHashing = memberRefSrcDeps != emptySourceDependencies
|
||||
assert(nameHashing || (memberRefSrcDeps == emptySourceDependencies),
|
||||
"When name hashing is disabled the `memberRef` relation should be empty.")
|
||||
assert(!nameHashing || (directSrcDeps == emptySource),
|
||||
"When name hashing is enabled the `direct` relation should be empty.")
|
||||
val classes = readStringRelation(Headers.classes)
|
||||
val names = readStringRelation(Headers.usedNames)
|
||||
|
||||
|
|
@ -322,6 +325,7 @@ object TextAnalysisFormat {
|
|||
val javacOptions = "javac options"
|
||||
val compilerVersion = "compiler version"
|
||||
val compileOrder = "compile order"
|
||||
val nameHashing = "name hashing"
|
||||
}
|
||||
|
||||
private[this] val singleOutputMode = "single"
|
||||
|
|
@ -340,16 +344,19 @@ object TextAnalysisFormat {
|
|||
writeSeq(out)(Headers.javacOptions, setup.options.javacOptions, identity[String])
|
||||
writeSeq(out)(Headers.compilerVersion, setup.compilerVersion :: Nil, identity[String])
|
||||
writeSeq(out)(Headers.compileOrder, setup.order.name :: Nil, identity[String])
|
||||
writeSeq(out)(Headers.nameHashing, setup.nameHashing :: Nil, (b: Boolean) => b.toString)
|
||||
}
|
||||
|
||||
def read(in: BufferedReader): CompileSetup = {
|
||||
def s2f(s: String) = new File(s)
|
||||
def s2b(s: String): Boolean = s.toBoolean
|
||||
val outputDirMode = readSeq(in)(Headers.outputMode, identity[String]).headOption
|
||||
val outputAsMap = readMap(in)(Headers.outputDir, s2f, s2f)
|
||||
val compileOptions = readSeq(in)(Headers.compileOptions, identity[String])
|
||||
val javacOptions = readSeq(in)(Headers.javacOptions, identity[String])
|
||||
val compilerVersion = readSeq(in)(Headers.compilerVersion, identity[String]).head
|
||||
val compileOrder = readSeq(in)(Headers.compileOrder, identity[String]).head
|
||||
val nameHashing = readSeq(in)(Headers.nameHashing, s2b).head
|
||||
|
||||
val output = outputDirMode match {
|
||||
case Some(s) => s match {
|
||||
|
|
@ -370,7 +377,7 @@ object TextAnalysisFormat {
|
|||
}
|
||||
|
||||
new CompileSetup(output, new CompileOptions(compileOptions, javacOptions), compilerVersion,
|
||||
xsbti.compile.CompileOrder.valueOf(compileOrder))
|
||||
xsbti.compile.CompileOrder.valueOf(compileOrder), nameHashing)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue