Rename Relations.{memberRefAndInheritanceDeps => nameHashing}

The previous name of the flag was rather specific: it indicated
whether the new source dependency tracking is supported by given Relations
object. However, there will be more functionality added to Relations that
is specific to name hashing algorithm. Therefore it makes sense to name
the flag as just `nameHashing`.

I decided to rename Relations implementation classes to be more
consistent with the name of the flag and with the purpose they serve.

The flag in AnalysisCallback (and classes implementing it) has been
renamed as well.
This commit is contained in:
Grzegorz Kossakowski 2013-11-28 13:42:39 +01:00
parent 4b0123f9ec
commit 2a3a3d0d7a
10 changed files with 75 additions and 67 deletions

View File

@ -59,7 +59,7 @@ object Analysis
/** Merge multiple analysis objects into one. Deps will be internalized as needed. */ /** Merge multiple analysis objects into one. Deps will be internalized as needed. */
def merge(analyses: Traversable[Analysis]): Analysis = { def merge(analyses: Traversable[Analysis]): Analysis = {
if (analyses.exists(_.relations.memberRefAndInheritanceDeps)) if (analyses.exists(_.relations.nameHashing))
throw new IllegalArgumentException("Merging of Analyses that have" + throw new IllegalArgumentException("Merging of Analyses that have" +
"`relations.memberRefAndInheritanceDeps` set to `true` is not supported.") "`relations.memberRefAndInheritanceDeps` set to `true` is not supported.")
@ -160,7 +160,7 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat
copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos ) copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos )
def groupBy[K](discriminator: File => K): Map[K, Analysis] = { def groupBy[K](discriminator: File => K): Map[K, Analysis] = {
if (relations.memberRefAndInheritanceDeps) if (relations.nameHashing)
throw new UnsupportedOperationException("Grouping of Analyses that have" + throw new UnsupportedOperationException("Grouping of Analyses that have" +
"`relations.memberRefAndInheritanceDeps` set to `true` is not supported.") "`relations.memberRefAndInheritanceDeps` set to `true` is not supported.")

View File

@ -151,7 +151,7 @@ private final class AnalysisCallback(internalMap: File => Option[File], external
apis(sourceFile) = (HashAPI(source), savedSource) apis(sourceFile) = (HashAPI(source), savedSource)
} }
def memberRefAndInheritanceDeps: Boolean = false // TODO: define the flag in IncOptions which controls this def nameHashing: Boolean = false // TODO: define the flag in IncOptions which controls this
def get: Analysis = addCompilation( 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 addProducts(base: Analysis): Analysis = addAll(base, classes) { case (a, src, (prod, name)) => a.addProduct(src, prod, current product prod, name ) }

View File

@ -147,17 +147,22 @@ trait Relations
def classes: Relation[File, String] def classes: Relation[File, String]
/** /**
* Flag which indicates whether the new style (based on `memberRef` and `inheritance` source dependencies) * Flag which indicates whether given Relations object supports operations needed by name hashing algorithm.
* of dependency tracking is enabled. When this flag is enabled access to `direct` and `publicInherited`
* relations is illegal and will cause runtime exception being thrown.
* *
* Conversely, when `memberRefAndInheritanceDeps` flag is disabled access to `memberRef` and `inheritance` * At the moment the list includes the following operations:
* relations is illegal and will cause runtime exception being thrown.
* *
* The name of this flag is ugly but it's private to incremental compiler and it's temporary measure during * - memberRef: SourceDependencies
* our migration to the new dependency tracking. * - inheritance: SourceDependencies
*
* The `memberRef` and `inheritance` implement a new style source dependency tracking. When this flag is
* enabled access to `direct` and `publicInherited` relations is illegal and will cause runtime exception
* being thrown. That is done as an optimization that prevents from storing two overlapping sets of
* dependencies.
*
* Conversely, when `nameHashing` flag is disabled access to `memberRef` and `inheritance`
* relations is illegal and will cause runtime exception being thrown.
*/ */
private[inc] def memberRefAndInheritanceDeps: Boolean private[inc] def nameHashing: Boolean
} }
@ -213,19 +218,19 @@ object Relations
def emptySource: Source = es def emptySource: Source = es
private[inc] lazy val emptySourceDependencies: SourceDependencies = new SourceDependencies(e, estr) private[inc] lazy val emptySourceDependencies: SourceDependencies = new SourceDependencies(e, estr)
def empty: Relations = empty(memberRefAndInheritanceDeps = false) def empty: Relations = empty(nameHashing = false)
def empty(memberRefAndInheritanceDeps: Boolean): Relations = def empty(nameHashing: Boolean): Relations =
if (memberRefAndInheritanceDeps) if (nameHashing)
new MRelationsMemberRefAndInheritance(e, e, emptySourceDependencies, emptySourceDependencies, estr) new MRelationsNameHashing(e, e, emptySourceDependencies, emptySourceDependencies, estr)
else else
new MRelationsDirectAndPublicInherited(e, e, es, es, estr) new MRelationsDefaultImpl(e, e, es, es, estr)
def make(srcProd: Relation[File, File], binaryDep: Relation[File, File], direct: Source, publicInherited: Source, classes: Relation[File, String]): Relations = def make(srcProd: Relation[File, File], binaryDep: Relation[File, File], direct: Source, publicInherited: Source, classes: Relation[File, String]): Relations =
new MRelationsDirectAndPublicInherited(srcProd, binaryDep, direct = direct, publicInherited = publicInherited, classes) new MRelationsDefaultImpl(srcProd, binaryDep, direct = direct, publicInherited = publicInherited, classes)
private[inc] def make(srcProd: Relation[File, File], binaryDep: Relation[File, File], private[inc] def make(srcProd: Relation[File, File], binaryDep: Relation[File, File],
memberRef: SourceDependencies, inheritance: SourceDependencies, classes: Relation[File, String]): Relations = memberRef: SourceDependencies, inheritance: SourceDependencies, classes: Relation[File, String]): Relations =
new MRelationsMemberRefAndInheritance(srcProd, binaryDep, memberRef = memberRef, inheritance = inheritance, classes) new MRelationsNameHashing(srcProd, binaryDep, memberRef = memberRef, inheritance = inheritance, classes)
def makeSource(internal: Relation[File,File], external: Relation[File,String]): Source = new Source(internal, external) def makeSource(internal: Relation[File,File], external: Relation[File,String]): Source = new Source(internal, external)
private[inc] def makeSourceDependencies(internal: Relation[File,File], external: Relation[File,String]): SourceDependencies = new SourceDependencies(internal, external) private[inc] def makeSourceDependencies(internal: Relation[File,File], external: Relation[File,String]): SourceDependencies = new SourceDependencies(internal, external)
} }
@ -309,7 +314,7 @@ private abstract class MRelationsCommon(val srcProd: Relation[File, File], val b
* introduced by inheritance. * introduced by inheritance.
* *
*/ */
private class MRelationsDirectAndPublicInherited(srcProd: Relation[File, File], binaryDep: Relation[File, File], private class MRelationsDefaultImpl(srcProd: Relation[File, File], binaryDep: Relation[File, File],
// direct should include everything in inherited // direct should include everything in inherited
val direct: Source, val publicInherited: Source, val direct: Source, val publicInherited: Source,
classes: Relation[File, String]) extends MRelationsCommon(srcProd, binaryDep, classes) classes: Relation[File, String]) extends MRelationsCommon(srcProd, binaryDep, classes)
@ -317,45 +322,45 @@ private class MRelationsDirectAndPublicInherited(srcProd: Relation[File, File],
def internalSrcDep: Relation[File, File] = direct.internal def internalSrcDep: Relation[File, File] = direct.internal
def externalDep: Relation[File, String] = direct.external def externalDep: Relation[File, String] = direct.external
def memberRefAndInheritanceDeps: Boolean = false def nameHashing: Boolean = false
def memberRef: SourceDependencies = def memberRef: SourceDependencies =
throw new UnsupportedOperationException("The `memberRef` source dependencies relation is not supported " + throw new UnsupportedOperationException("The `memberRef` source dependencies relation is not supported " +
"when `memberRefAndInheritanceDeps` is disabled. Do you have name hashing algorithm disabled?") "when `nameHashing` flag is disabled.")
def inheritance: SourceDependencies = def inheritance: SourceDependencies =
throw new UnsupportedOperationException("The `memberRef` source dependencies relation is not supported " + throw new UnsupportedOperationException("The `memberRef` source dependencies relation is not supported " +
"when `memberRefAndInheritanceDeps` is disabled. Do you have name hashing algorithm disabled?") "when `nameHashing` flag is disabled.")
def addProduct(src: File, prod: File, name: String): Relations = def addProduct(src: File, prod: File, name: String): Relations =
new MRelationsDirectAndPublicInherited(srcProd + (src, prod), binaryDep, direct = direct, new MRelationsDefaultImpl(srcProd + (src, prod), binaryDep, direct = direct,
publicInherited = publicInherited, classes + (src, name)) publicInherited = publicInherited, classes + (src, name))
def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = { def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = {
val newI = if(inherited) publicInherited.addExternal(src, dependsOn) else publicInherited val newI = if(inherited) publicInherited.addExternal(src, dependsOn) else publicInherited
val newD = direct.addExternal(src, dependsOn) val newD = direct.addExternal(src, dependsOn)
new MRelationsDirectAndPublicInherited( srcProd, binaryDep, direct = newD, publicInherited = newI, classes) new MRelationsDefaultImpl( srcProd, binaryDep, direct = newD, publicInherited = newI, classes)
} }
def addInternalSrcDeps(src: File, dependsOn: Iterable[File], inherited: Iterable[File]): Relations = def addInternalSrcDeps(src: File, dependsOn: Iterable[File], inherited: Iterable[File]): Relations =
{ {
val newI = publicInherited.addInternal(src, inherited) val newI = publicInherited.addInternal(src, inherited)
val newD = direct.addInternal(src, dependsOn) val newD = direct.addInternal(src, dependsOn)
new MRelationsDirectAndPublicInherited( srcProd, binaryDep, direct = newD, publicInherited = newI, classes) new MRelationsDefaultImpl( srcProd, binaryDep, direct = newD, publicInherited = newI, classes)
} }
def addBinaryDep(src: File, dependsOn: File): Relations = def addBinaryDep(src: File, dependsOn: File): Relations =
new MRelationsDirectAndPublicInherited( srcProd, binaryDep + (src, dependsOn), direct = direct, new MRelationsDefaultImpl( srcProd, binaryDep + (src, dependsOn), direct = direct,
publicInherited = publicInherited, classes) publicInherited = publicInherited, classes)
def ++ (o: Relations): Relations = { def ++ (o: Relations): Relations = {
if (memberRefAndInheritanceDeps != o.memberRefAndInheritanceDeps) if (nameHashing != o.nameHashing)
throw new UnsupportedOperationException("The `++` operation is not supported for relations " + throw new UnsupportedOperationException("The `++` operation is not supported for relations " +
"with different values of `memberRefAndInheritanceDeps` flag.") "with different values of `nameHashing` flag.")
new MRelationsDirectAndPublicInherited(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, direct ++ o.direct, new MRelationsDefaultImpl(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, direct ++ o.direct,
publicInherited ++ o.publicInherited, classes ++ o.classes) publicInherited ++ o.publicInherited, classes ++ o.classes)
} }
def -- (sources: Iterable[File]) = def -- (sources: Iterable[File]) =
new MRelationsDirectAndPublicInherited(srcProd -- sources, binaryDep -- sources, direct = direct -- sources, new MRelationsDefaultImpl(srcProd -- sources, binaryDep -- sources, direct = direct -- sources,
publicInherited = publicInherited -- sources, classes -- sources) publicInherited = publicInherited -- sources, classes -- sources)
@deprecated("Broken implementation. OK to remove in 0.14", "0.13.1") @deprecated("Broken implementation. OK to remove in 0.14", "0.13.1")
@ -370,7 +375,7 @@ private class MRelationsDirectAndPublicInherited(srcProd: Relation[File, File],
def getSrc(m: Map[K, Source]): Source = m.getOrElse(k, Relations.emptySource) def getSrc(m: Map[K, Source]): Source = m.getOrElse(k, Relations.emptySource)
def getSrcDeps(m: Map[K, SourceDependencies]): SourceDependencies = def getSrcDeps(m: Map[K, SourceDependencies]): SourceDependencies =
m.getOrElse(k, Relations.emptySourceDependencies) m.getOrElse(k, Relations.emptySourceDependencies)
new MRelationsDirectAndPublicInherited( get(srcProdMap), get(binaryDepMap), getSrc(direct), getSrc(inherited), new MRelationsDefaultImpl( get(srcProdMap), get(binaryDepMap), getSrc(direct), getSrc(inherited),
get(classesMap)) get(classesMap))
} }
val keys = (srcProdMap.keySet ++ binaryDepMap.keySet ++ direct.keySet ++ inherited.keySet ++ classesMap.keySet).toList val keys = (srcProdMap.keySet ++ binaryDepMap.keySet ++ direct.keySet ++ inherited.keySet ++ classesMap.keySet).toList
@ -384,7 +389,7 @@ private class MRelationsDirectAndPublicInherited(srcProd: Relation[File, File],
} }
override def equals(other: Any) = other match { override def equals(other: Any) = other match {
case o: MRelationsDirectAndPublicInherited => case o: MRelationsDefaultImpl =>
srcProd == o.srcProd && binaryDep == o.binaryDep && direct == o.direct && srcProd == o.srcProd && binaryDep == o.binaryDep && direct == o.direct &&
publicInherited == o.publicInherited && classes == o.classes publicInherited == o.publicInherited && classes == o.classes
case _ => false case _ => false
@ -417,62 +422,62 @@ private class MRelationsDirectAndPublicInherited(srcProd: Relation[File, File],
* dependencies. Therefore this class implements the new (compared to sbt 0.13.0) dependency tracking logic * dependencies. Therefore this class implements the new (compared to sbt 0.13.0) dependency tracking logic
* needed by the name hashing invalidation algorithm. * needed by the name hashing invalidation algorithm.
*/ */
private class MRelationsMemberRefAndInheritance(srcProd: Relation[File, File], binaryDep: Relation[File, File], private class MRelationsNameHashing(srcProd: Relation[File, File], binaryDep: Relation[File, File],
// memberRef should include everything in inherited // memberRef should include everything in inherited
val memberRef: SourceDependencies, val inheritance: SourceDependencies, val memberRef: SourceDependencies, val inheritance: SourceDependencies,
classes: Relation[File, String]) extends MRelationsCommon(srcProd, binaryDep, classes) classes: Relation[File, String]) extends MRelationsCommon(srcProd, binaryDep, classes)
{ {
def direct: Source = def direct: Source =
throw new UnsupportedOperationException("The `direct` source dependencies relation is not supported " + throw new UnsupportedOperationException("The `direct` source dependencies relation is not supported " +
"when `memberRefAndInheritanceDeps` is disabled. Do you have name hashing algorithm disabled?") "when `nameHashing` flag is disabled.")
def publicInherited: Source = def publicInherited: Source =
throw new UnsupportedOperationException("The `publicInherited` source dependencies relation is not supported " + throw new UnsupportedOperationException("The `publicInherited` source dependencies relation is not supported " +
"when `memberRefAndInheritanceDeps` is disabled. Do you have name hashing algorithm disabled?") "when `nameHashing` flag is disabled.")
val memberRefAndInheritanceDeps: Boolean = true val nameHashing: Boolean = true
def internalSrcDep: Relation[File, File] = memberRef.internal def internalSrcDep: Relation[File, File] = memberRef.internal
def externalDep: Relation[File, String] = memberRef.external def externalDep: Relation[File, String] = memberRef.external
def addProduct(src: File, prod: File, name: String): Relations = def addProduct(src: File, prod: File, name: String): Relations =
new MRelationsMemberRefAndInheritance(srcProd + (src, prod), binaryDep, memberRef = memberRef, new MRelationsNameHashing(srcProd + (src, prod), binaryDep, memberRef = memberRef,
inheritance = inheritance, classes + (src, name)) inheritance = inheritance, classes + (src, name))
def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = { def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = {
val newIH = if(inherited) inheritance.addExternal(src, dependsOn) else inheritance val newIH = if(inherited) inheritance.addExternal(src, dependsOn) else inheritance
val newMR = memberRef.addExternal(src, dependsOn) val newMR = memberRef.addExternal(src, dependsOn)
new MRelationsMemberRefAndInheritance( srcProd, binaryDep, memberRef = newMR, inheritance = newIH, classes) new MRelationsNameHashing( srcProd, binaryDep, memberRef = newMR, inheritance = newIH, classes)
} }
def addInternalSrcDeps(src: File, dependsOn: Iterable[File], inherited: Iterable[File]): Relations = { def addInternalSrcDeps(src: File, dependsOn: Iterable[File], inherited: Iterable[File]): Relations = {
val newIH = inheritance.addInternal(src, inherited) val newIH = inheritance.addInternal(src, inherited)
val newMR = memberRef.addInternal(src, dependsOn) val newMR = memberRef.addInternal(src, dependsOn)
new MRelationsMemberRefAndInheritance( srcProd, binaryDep, memberRef = newMR, inheritance = newIH, classes) new MRelationsNameHashing( srcProd, binaryDep, memberRef = newMR, inheritance = newIH, classes)
} }
def addBinaryDep(src: File, dependsOn: File): Relations = def addBinaryDep(src: File, dependsOn: File): Relations =
new MRelationsMemberRefAndInheritance(srcProd, binaryDep + (src, dependsOn), memberRef = memberRef, new MRelationsNameHashing(srcProd, binaryDep + (src, dependsOn), memberRef = memberRef,
inheritance = inheritance, classes) inheritance = inheritance, classes)
def ++ (o: Relations): Relations = { def ++ (o: Relations): Relations = {
if (!o.memberRefAndInheritanceDeps) if (!o.nameHashing)
throw new UnsupportedOperationException("The `++` operation is not supported for relations " + throw new UnsupportedOperationException("The `++` operation is not supported for relations " +
"with different values of `memberRefAndInheritanceDeps` flag.") "with different values of `nameHashing` flag.")
new MRelationsMemberRefAndInheritance(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, new MRelationsNameHashing(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep,
memberRef = memberRef ++ o.memberRef, inheritance = inheritance ++ o.inheritance, memberRef = memberRef ++ o.memberRef, inheritance = inheritance ++ o.inheritance,
classes ++ o.classes) classes ++ o.classes)
} }
def -- (sources: Iterable[File]) = def -- (sources: Iterable[File]) =
new MRelationsMemberRefAndInheritance(srcProd -- sources, binaryDep -- sources, new MRelationsNameHashing(srcProd -- sources, binaryDep -- sources,
memberRef = memberRef -- sources, inheritance = inheritance -- sources, classes -- sources) memberRef = memberRef -- sources, inheritance = inheritance -- sources, classes -- sources)
def groupBy[K](f: File => K): Map[K, Relations] = { def groupBy[K](f: File => K): Map[K, Relations] = {
throw new UnsupportedOperationException("Merging of Analyses that have" + throw new UnsupportedOperationException("Merging of Analyses that have" +
"`relations.memberRefAndInheritanceDeps` set to `true` is not supported.") "`relations.nameHashing` set to `true` is not supported.")
} }
override def equals(other: Any) = other match { override def equals(other: Any) = other match {
case o: MRelationsMemberRefAndInheritance => case o: MRelationsNameHashing =>
srcProd == o.srcProd && binaryDep == o.binaryDep && memberRef == o.memberRef && srcProd == o.srcProd && binaryDep == o.binaryDep && memberRef == o.memberRef &&
inheritance == o.inheritance && classes == o.classes inheritance == o.inheritance && classes == o.classes
case _ => false case _ => false

View File

@ -43,7 +43,7 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile
{ {
// build dependencies structure // build dependencies structure
val sourceFile = unit.source.file.file val sourceFile = unit.source.file.file
if (global.callback.memberRefAndInheritanceDeps) { if (global.callback.nameHashing) {
val dependenciesByMemberRef = extractDependenciesByMemberRef(unit) val dependenciesByMemberRef = extractDependenciesByMemberRef(unit)
for(on <- dependenciesByMemberRef) for(on <- dependenciesByMemberRef)
processDependency(on, inherited=false) processDependency(on, inherited=false)

View File

@ -80,7 +80,7 @@ class DependencySpecification extends Specification {
// E verifies the core type gets pulled out // E verifies the core type gets pulled out
val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)" val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)"
val compilerForTesting = new ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps = true) val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC,
'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH) 'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH)
sourceDependencies sourceDependencies
@ -92,7 +92,7 @@ class DependencySpecification extends Specification {
val srcC = "class C { private class Inner1 extends A }" val srcC = "class C { private class Inner1 extends A }"
val srcD = "class D { def foo: Unit = { class Inner2 extends B } }" val srcD = "class D { def foo: Unit = { class Inner2 extends B } }"
val compilerForTesting = new ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps = true) val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
val sourceDependencies = val sourceDependencies =
compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
sourceDependencies sourceDependencies
@ -104,7 +104,7 @@ class DependencySpecification extends Specification {
val srcC = "trait C extends B" val srcC = "trait C extends B"
val srcD = "class D extends C" val srcD = "class D extends C"
val compilerForTesting = new ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps = true) val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
val sourceDependencies = val sourceDependencies =
compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
sourceDependencies sourceDependencies

View File

@ -19,7 +19,7 @@ import ScalaCompilerForUnitTesting.ExtractedSourceDependencies
* Provides common functionality needed for unit tests that require compiling * Provides common functionality needed for unit tests that require compiling
* source code using Scala compiler. * source code using Scala compiler.
*/ */
class ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps: Boolean = false) { class ScalaCompilerForUnitTesting(nameHashing: Boolean = false) {
/** /**
* Compiles given source code using Scala compiler and returns API representation * Compiles given source code using Scala compiler and returns API representation
@ -76,7 +76,7 @@ class ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps: Boolean = false)
*/ */
private def compileSrcs(srcs: String*): (Seq[File], TestCallback) = { private def compileSrcs(srcs: String*): (Seq[File], TestCallback) = {
withTemporaryDirectory { temp => withTemporaryDirectory { temp =>
val analysisCallback = new TestCallback(memberRefAndInheritanceDeps) val analysisCallback = new TestCallback(nameHashing)
val classesDir = new File(temp, "classes") val classesDir = new File(temp, "classes")
classesDir.mkdir() classesDir.mkdir()
val compiler = prepareCompiler(classesDir, analysisCallback) val compiler = prepareCompiler(classesDir, analysisCallback)

View File

@ -103,21 +103,21 @@ object AnalysisFormats
{ {
def makeRelation(srcProd: RFF, binaryDep: RFF, direct: RSource, publicInherited: RSource, def makeRelation(srcProd: RFF, binaryDep: RFF, direct: RSource, publicInherited: RSource,
memberRef: SourceDependencies, inheritance: SourceDependencies, classes: RFS, memberRef: SourceDependencies, inheritance: SourceDependencies, classes: RFS,
memberRefAndInheritanceDeps: Boolean): Relations = if (memberRefAndInheritanceDeps) { nameHashing: Boolean): Relations = if (nameHashing) {
def isEmpty(sourceDependencies: RSource): Boolean = def isEmpty(sourceDependencies: RSource): Boolean =
sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty
// we check direct dependencies only because publicInherited dependencies are subset of direct // we check direct dependencies only because publicInherited dependencies are subset of direct
assert(isEmpty(direct), "Direct dependencies are not empty but `memberRefAndInheritanceDeps` flag is enabled.") assert(isEmpty(direct), "Direct dependencies are not empty but `nameHashing` flag is enabled.")
Relations.make(srcProd, binaryDep, memberRef, inheritance, classes) Relations.make(srcProd, binaryDep, memberRef, inheritance, classes)
} else { } else {
def isEmpty(sourceDependencies: SourceDependencies): Boolean = def isEmpty(sourceDependencies: SourceDependencies): Boolean =
sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty
// we check memberRef dependencies only because inheritance dependencies are subset of memberRef // we check memberRef dependencies only because inheritance dependencies are subset of memberRef
assert(isEmpty(memberRef), "Direct dependencies are not empty but `memberRefAndInheritanceDeps` flag is enabled.") assert(isEmpty(memberRef), "Direct dependencies are not empty but `nameHashing` flag is enabled.")
Relations.make(srcProd, binaryDep, direct, publicInherited, classes) Relations.make(srcProd, binaryDep, direct, publicInherited, classes)
} }
asProduct8[Relations, RFF, RFF, RSource, RSource, SourceDependencies, SourceDependencies, RFS, Boolean]( (a,b,c,d,e,f,g,h) =>makeRelation(a,b,c,d,e,f,g,h) )( asProduct8[Relations, RFF, RFF, RSource, RSource, SourceDependencies, SourceDependencies, RFS, Boolean]( (a,b,c,d,e,f,g,h) =>makeRelation(a,b,c,d,e,f,g,h) )(
rs => (rs.srcProd, rs.binaryDep, rs.direct, rs.publicInherited, rs.memberRef, rs.inheritance, rs.classes, rs.memberRefAndInheritanceDeps) )( rs => (rs.srcProd, rs.binaryDep, rs.direct, rs.publicInherited, rs.memberRef, rs.inheritance, rs.classes, rs.nameHashing) )(
prodF, binF, directF, inheritedF, memberRefF, inheritanceF, csF, implicitly[Format[Boolean]]) prodF, binF, directF, inheritedF, memberRefF, inheritanceF, csF, implicitly[Format[Boolean]])
} }

View File

@ -134,17 +134,17 @@ object TextAnalysisFormat {
} }
} }
val memberRefAndInheritanceDeps = relations.memberRefAndInheritanceDeps val nameHashing = relations.nameHashing
writeRelation(Headers.srcProd, relations.srcProd) writeRelation(Headers.srcProd, relations.srcProd)
writeRelation(Headers.binaryDep, relations.binaryDep) writeRelation(Headers.binaryDep, relations.binaryDep)
val direct = if (memberRefAndInheritanceDeps) Relations.emptySource else relations.direct val direct = if (nameHashing) Relations.emptySource else relations.direct
val publicInherited = if (memberRefAndInheritanceDeps) val publicInherited = if (nameHashing)
Relations.emptySource else relations.publicInherited Relations.emptySource else relations.publicInherited
val memberRef = if (memberRefAndInheritanceDeps) val memberRef = if (nameHashing)
relations.memberRef else Relations.emptySourceDependencies relations.memberRef else Relations.emptySourceDependencies
val inheritance = if (memberRefAndInheritanceDeps) val inheritance = if (nameHashing)
relations.inheritance else Relations.emptySourceDependencies relations.inheritance else Relations.emptySourceDependencies
writeRelation(Headers.directSrcDep, direct.internal) writeRelation(Headers.directSrcDep, direct.internal)
@ -213,10 +213,10 @@ object TextAnalysisFormat {
// we assume that invariant that says they are subsets of direct/memberRef holds // we assume that invariant that says they are subsets of direct/memberRef holds
assert((directSrcDeps == emptySource) || (memberRefSrcDeps == emptySourceDependencies), assert((directSrcDeps == emptySource) || (memberRefSrcDeps == emptySourceDependencies),
"One mechanism is supported for tracking source dependencies at the time") "One mechanism is supported for tracking source dependencies at the time")
val memberRefAndInheritanceDeps = memberRefSrcDeps != emptySourceDependencies val nameHashing = memberRefSrcDeps != emptySourceDependencies
val classes = readStringRelation(Headers.classes) val classes = readStringRelation(Headers.classes)
if (memberRefAndInheritanceDeps) if (nameHashing)
Relations.make(srcProd, binaryDep, memberRefSrcDeps, inheritanceSrcDeps, classes) Relations.make(srcProd, binaryDep, memberRefSrcDeps, inheritanceSrcDeps, classes)
else else
Relations.make(srcProd, binaryDep, directSrcDeps, publicInheritedSrcDeps, classes) Relations.make(srcProd, binaryDep, directSrcDeps, publicInheritedSrcDeps, classes)

View File

@ -28,8 +28,11 @@ public interface AnalysisCallback
* Unreported problems are usually unreported because reporting was not enabled via a command line switch. */ * Unreported problems are usually unreported because reporting was not enabled via a command line switch. */
public void problem(String what, Position pos, String msg, Severity severity, boolean reported); public void problem(String what, Position pos, String msg, Severity severity, boolean reported);
/** /**
* Determines whether member reference and inheritance dependencies should be extracted in given compiler * Determines whether method calls through this interface should be interpreted as serving
* run. * name hashing algorithm needs in given compiler run.
*
* In particular, it indicates whether member reference and inheritance dependencies should be
* extracted.
* *
* As the signature suggests, this method's implementation is meant to be side-effect free. It's added * As the signature suggests, this method's implementation is meant to be side-effect free. It's added
* to AnalysisCallback because it indicates how other callback calls should be interpreted by both * to AnalysisCallback because it indicates how other callback calls should be interpreted by both
@ -38,5 +41,5 @@ public interface AnalysisCallback
* NOTE: This method is an implementation detail and can be removed at any point without deprecation. * NOTE: This method is an implementation detail and can be removed at any point without deprecation.
* Do not depend on it, please. * Do not depend on it, please.
*/ */
public boolean memberRefAndInheritanceDeps(); public boolean nameHashing();
} }

View File

@ -4,7 +4,7 @@ import java.io.File
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
import xsbti.api.SourceAPI import xsbti.api.SourceAPI
class TestCallback(override val memberRefAndInheritanceDeps: Boolean = false) extends AnalysisCallback class TestCallback(override val nameHashing: Boolean = false) extends AnalysisCallback
{ {
val sourceDependencies = new ArrayBuffer[(File, File, Boolean)] val sourceDependencies = new ArrayBuffer[(File, File, Boolean)]
val binaryDependencies = new ArrayBuffer[(File, String, File, Boolean)] val binaryDependencies = new ArrayBuffer[(File, String, File, Boolean)]