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. */
def merge(analyses: Traversable[Analysis]): Analysis = {
if (analyses.exists(_.relations.memberRefAndInheritanceDeps))
if (analyses.exists(_.relations.nameHashing))
throw new IllegalArgumentException("Merging of Analyses that have" +
"`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 )
def groupBy[K](discriminator: File => K): Map[K, Analysis] = {
if (relations.memberRefAndInheritanceDeps)
if (relations.nameHashing)
throw new UnsupportedOperationException("Grouping of Analyses that have" +
"`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)
}
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 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]
/**
* Flag which indicates whether the new style (based on `memberRef` and `inheritance` source dependencies)
* 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.
* Flag which indicates whether given Relations object supports operations needed by name hashing algorithm.
*
* Conversely, when `memberRefAndInheritanceDeps` flag is disabled access to `memberRef` and `inheritance`
* relations is illegal and will cause runtime exception being thrown.
* At the moment the list includes the following operations:
*
* The name of this flag is ugly but it's private to incremental compiler and it's temporary measure during
* our migration to the new dependency tracking.
* - memberRef: SourceDependencies
* - 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
private[inc] lazy val emptySourceDependencies: SourceDependencies = new SourceDependencies(e, estr)
def empty: Relations = empty(memberRefAndInheritanceDeps = false)
def empty(memberRefAndInheritanceDeps: Boolean): Relations =
if (memberRefAndInheritanceDeps)
new MRelationsMemberRefAndInheritance(e, e, emptySourceDependencies, emptySourceDependencies, estr)
def empty: Relations = empty(nameHashing = false)
def empty(nameHashing: Boolean): Relations =
if (nameHashing)
new MRelationsNameHashing(e, e, emptySourceDependencies, emptySourceDependencies, estr)
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 =
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],
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)
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.
*
*/
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
val direct: Source, val publicInherited: Source,
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 externalDep: Relation[File, String] = direct.external
def memberRefAndInheritanceDeps: Boolean = false
def nameHashing: Boolean = false
def memberRef: SourceDependencies =
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 =
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 =
new MRelationsDirectAndPublicInherited(srcProd + (src, prod), binaryDep, direct = direct,
new MRelationsDefaultImpl(srcProd + (src, prod), binaryDep, direct = direct,
publicInherited = publicInherited, classes + (src, name))
def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = {
val newI = if(inherited) publicInherited.addExternal(src, dependsOn) else publicInherited
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 =
{
val newI = publicInherited.addInternal(src, inherited)
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 =
new MRelationsDirectAndPublicInherited( srcProd, binaryDep + (src, dependsOn), direct = direct,
new MRelationsDefaultImpl( srcProd, binaryDep + (src, dependsOn), direct = direct,
publicInherited = publicInherited, classes)
def ++ (o: Relations): Relations = {
if (memberRefAndInheritanceDeps != o.memberRefAndInheritanceDeps)
if (nameHashing != o.nameHashing)
throw new UnsupportedOperationException("The `++` operation is not supported for relations " +
"with different values of `memberRefAndInheritanceDeps` flag.")
new MRelationsDirectAndPublicInherited(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, direct ++ o.direct,
"with different values of `nameHashing` flag.")
new MRelationsDefaultImpl(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, direct ++ o.direct,
publicInherited ++ o.publicInherited, classes ++ o.classes)
}
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)
@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 getSrcDeps(m: Map[K, SourceDependencies]): SourceDependencies =
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))
}
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 {
case o: MRelationsDirectAndPublicInherited =>
case o: MRelationsDefaultImpl =>
srcProd == o.srcProd && binaryDep == o.binaryDep && direct == o.direct &&
publicInherited == o.publicInherited && classes == o.classes
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
* 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
val memberRef: SourceDependencies, val inheritance: SourceDependencies,
classes: Relation[File, String]) extends MRelationsCommon(srcProd, binaryDep, classes)
{
def direct: Source =
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 =
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 externalDep: Relation[File, String] = memberRef.external
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))
def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations = {
val newIH = if(inherited) inheritance.addExternal(src, dependsOn) else inheritance
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 = {
val newIH = inheritance.addInternal(src, inherited)
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 =
new MRelationsMemberRefAndInheritance(srcProd, binaryDep + (src, dependsOn), memberRef = memberRef,
new MRelationsNameHashing(srcProd, binaryDep + (src, dependsOn), memberRef = memberRef,
inheritance = inheritance, classes)
def ++ (o: Relations): Relations = {
if (!o.memberRefAndInheritanceDeps)
if (!o.nameHashing)
throw new UnsupportedOperationException("The `++` operation is not supported for relations " +
"with different values of `memberRefAndInheritanceDeps` flag.")
new MRelationsMemberRefAndInheritance(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep,
"with different values of `nameHashing` flag.")
new MRelationsNameHashing(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep,
memberRef = memberRef ++ o.memberRef, inheritance = inheritance ++ o.inheritance,
classes ++ o.classes)
}
def -- (sources: Iterable[File]) =
new MRelationsMemberRefAndInheritance(srcProd -- sources, binaryDep -- sources,
new MRelationsNameHashing(srcProd -- sources, binaryDep -- sources,
memberRef = memberRef -- sources, inheritance = inheritance -- sources, classes -- sources)
def groupBy[K](f: File => K): Map[K, Relations] = {
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 {
case o: MRelationsMemberRefAndInheritance =>
case o: MRelationsNameHashing =>
srcProd == o.srcProd && binaryDep == o.binaryDep && memberRef == o.memberRef &&
inheritance == o.inheritance && classes == o.classes
case _ => false

View File

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

View File

@ -80,7 +80,7 @@ class DependencySpecification extends Specification {
// E verifies the core type gets pulled out
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,
'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH)
sourceDependencies
@ -92,7 +92,7 @@ class DependencySpecification extends Specification {
val srcC = "class C { private class Inner1 extends A }"
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 =
compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
sourceDependencies
@ -104,7 +104,7 @@ class DependencySpecification extends Specification {
val srcC = "trait C extends B"
val srcD = "class D extends C"
val compilerForTesting = new ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps = true)
val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
val sourceDependencies =
compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
sourceDependencies

View File

@ -19,7 +19,7 @@ import ScalaCompilerForUnitTesting.ExtractedSourceDependencies
* Provides common functionality needed for unit tests that require compiling
* 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
@ -76,7 +76,7 @@ class ScalaCompilerForUnitTesting(memberRefAndInheritanceDeps: Boolean = false)
*/
private def compileSrcs(srcs: String*): (Seq[File], TestCallback) = {
withTemporaryDirectory { temp =>
val analysisCallback = new TestCallback(memberRefAndInheritanceDeps)
val analysisCallback = new TestCallback(nameHashing)
val classesDir = new File(temp, "classes")
classesDir.mkdir()
val compiler = prepareCompiler(classesDir, analysisCallback)

View File

@ -103,21 +103,21 @@ object AnalysisFormats
{
def makeRelation(srcProd: RFF, binaryDep: RFF, direct: RSource, publicInherited: RSource,
memberRef: SourceDependencies, inheritance: SourceDependencies, classes: RFS,
memberRefAndInheritanceDeps: Boolean): Relations = if (memberRefAndInheritanceDeps) {
nameHashing: Boolean): Relations = if (nameHashing) {
def isEmpty(sourceDependencies: RSource): Boolean =
sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty
// 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)
} else {
def isEmpty(sourceDependencies: SourceDependencies): Boolean =
sourceDependencies.internal.all.isEmpty && sourceDependencies.external.all.isEmpty
// 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)
}
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]])
}

View File

@ -134,17 +134,17 @@ object TextAnalysisFormat {
}
}
val memberRefAndInheritanceDeps = relations.memberRefAndInheritanceDeps
val nameHashing = relations.nameHashing
writeRelation(Headers.srcProd, relations.srcProd)
writeRelation(Headers.binaryDep, relations.binaryDep)
val direct = if (memberRefAndInheritanceDeps) Relations.emptySource else relations.direct
val publicInherited = if (memberRefAndInheritanceDeps)
val direct = if (nameHashing) Relations.emptySource else relations.direct
val publicInherited = if (nameHashing)
Relations.emptySource else relations.publicInherited
val memberRef = if (memberRefAndInheritanceDeps)
val memberRef = if (nameHashing)
relations.memberRef else Relations.emptySourceDependencies
val inheritance = if (memberRefAndInheritanceDeps)
val inheritance = if (nameHashing)
relations.inheritance else Relations.emptySourceDependencies
writeRelation(Headers.directSrcDep, direct.internal)
@ -213,10 +213,10 @@ object TextAnalysisFormat {
// 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 memberRefAndInheritanceDeps = memberRefSrcDeps != emptySourceDependencies
val nameHashing = memberRefSrcDeps != emptySourceDependencies
val classes = readStringRelation(Headers.classes)
if (memberRefAndInheritanceDeps)
if (nameHashing)
Relations.make(srcProd, binaryDep, memberRefSrcDeps, inheritanceSrcDeps, classes)
else
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. */
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
* run.
* Determines whether method calls through this interface should be interpreted as serving
* 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
* 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.
* 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 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 binaryDependencies = new ArrayBuffer[(File, String, File, Boolean)]