Skip to content

Commit b837169

Browse files
committed
Introduce memberRef and inheritance relations.
Introduce an alternative source dependency tracking mechanism that is needed by upcoming name hashing algorithm. This new mechanism is implemented by introducing two new source dependency relations called `memberRef` and `inheritance`. Those relations are very similar to existing `direct` and `publicInherited` relations in some subtle ways. Those differences will be highlighted in the description below. Dependencies between source files are tracked in two distinct categories: * dependencies introduced by inheriting from a class/trait defined in other source file * dependencies introduced by referring (selecting) a member defined in other source file (that covers all other kinds of dependencies) Due to invalidation algorithm implementation details sbt would need to track inheritance dependencies of public classes only. Thus, we had relation called `publicInherited`. The name hashing algorithm which improves invalidation logic will need more precise information about dependencies introduced by inheritance including dependencies of non-public classes. That's one difference between `inheritance` and `publicInherited` relations. One surprising (to me) thing about `publicInherited` is that it includes all base classes of a given class and not just parents. In that sense `publicInherited` is transitive. This is a bit irregular because everything else in Relations doesn't include transitive dependencies. Since we are introducing new relations we have an excellent chance to make things more regular. Therefore `inheritance` relation is non-transitive and includes only extracted parent classes. The access to `direct`, `publicInherited`, `memberRef` and `inheritance` relations is dependent upon the value of `memberRefAndInheritanceDeps` flag. Check documentation of that flag for details. The two alternatives for source dependency tracking are implemented by introduction of two subclasses that implement Relations trait and one abstract class that contains some common logic shared between those two subclasses. The two new subclasses are needed for the time being when we are slowly migrating to the name hashing algorithm which requires subtle changes to dependency tracking as explained above. For some time we plan to keep both algorithms side-by-side and have a runtime switch which allows to pick one. So we need logic for both old and new dependency tracking to be available. That's exactly what two subclasses of MRelationsCommon implement. Once name hashing is proven to be stable and reliable we'll phase out the old algorithm and the old dependency tracking logic.
1 parent a9a1574 commit b837169

File tree

4 files changed

+374
-74
lines changed

4 files changed

+374
-74
lines changed

compile/inc/src/main/scala/sbt/inc/Analysis.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ trait Analysis
4141

4242
def copy(stamps: Stamps = stamps, apis: APIs = apis, relations: Relations = relations, infos: SourceInfos = infos,
4343
compilations: Compilations = compilations): Analysis
44-
44+
4545
def addSource(src: File, api: Source, stamp: Stamp, directInternal: Iterable[File], inheritedInternal: Iterable[File], info: SourceInfo): Analysis
4646
def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis
4747
def addExternalDep(src: File, dep: String, api: Source, inherited: Boolean): Analysis
@@ -59,6 +59,10 @@ object Analysis
5959

6060
/** Merge multiple analysis objects into one. Deps will be internalized as needed. */
6161
def merge(analyses: Traversable[Analysis]): Analysis = {
62+
if (analyses.exists(_.relations.memberRefAndInheritanceDeps))
63+
throw new IllegalArgumentException("Merging of Analyses that have" +
64+
"`relations.memberRefAndInheritanceDeps` set to `true` is not supported.")
65+
6266
// Merge the Relations, internalizing deps as needed.
6367
val mergedSrcProd = Relation.merge(analyses map { _.relations.srcProd })
6468
val mergedBinaryDep = Relation.merge(analyses map { _.relations.binaryDep })
@@ -156,6 +160,10 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat
156160
copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos )
157161

158162
def groupBy[K](discriminator: File => K): Map[K, Analysis] = {
163+
if (relations.memberRefAndInheritanceDeps)
164+
throw new UnsupportedOperationException("Grouping of Analyses that have" +
165+
"`relations.memberRefAndInheritanceDeps` set to `true` is not supported.")
166+
159167
def discriminator1(x: (File, _)) = discriminator(x._1) // Apply the discriminator to the first coordinate.
160168

161169
val kSrcProd = relations.srcProd.groupBy(discriminator1)

0 commit comments

Comments
 (0)