mirror of https://github.com/sbt/sbt.git
Record and persist public inheritance dependencies.
Includes placeholders for adding public inherited dependencies for Java classes.
This commit is contained in:
parent
c355bef200
commit
4dc75343ae
|
|
@ -11,6 +11,7 @@ trait Analysis
|
|||
{
|
||||
val stamps: Stamps
|
||||
val apis: APIs
|
||||
/** Mappings between sources, classes, and binaries. */
|
||||
val relations: Relations
|
||||
val infos: SourceInfos
|
||||
/** Information about compiler runs accumulated since `clean` command has been run. */
|
||||
|
|
@ -21,9 +22,9 @@ trait 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 addSource(src: File, api: Source, stamp: Stamp, directInternal: Iterable[File], inheritedInternal: Iterable[File], info: SourceInfo): Analysis
|
||||
def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis
|
||||
def addExternalDep(src: File, dep: String, api: Source): Analysis
|
||||
def addExternalDep(src: File, dep: String, api: Source, inherited: Boolean): Analysis
|
||||
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis
|
||||
|
||||
def groupBy[K](f: (File => K)): Map[K, Analysis]
|
||||
|
|
@ -60,8 +61,7 @@ object Analysis
|
|||
}
|
||||
|
||||
}
|
||||
private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relations, val infos: SourceInfos,
|
||||
val compilations: Compilations) 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, compilations ++ o.compilations)
|
||||
|
|
@ -78,14 +78,14 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat
|
|||
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) )
|
||||
def addSource(src: File, api: Source, stamp: Stamp, directInternal: Iterable[File], inheritedInternal: Iterable[File], info: SourceInfo): Analysis =
|
||||
copy( stamps.markInternalSource(src, stamp), apis.markInternalSource(src, api), relations.addInternalSrcDeps(src, directInternal, inheritedInternal), infos.add(src, info) )
|
||||
|
||||
def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis =
|
||||
copy( stamps.markBinary(dep, className, stamp), apis, relations.addBinaryDep(src, dep), infos )
|
||||
|
||||
def addExternalDep(src: File, dep: String, depAPI: Source): Analysis =
|
||||
copy( stamps, apis.markExternalAPI(dep, depAPI), relations.addExternalDep(src, dep), infos )
|
||||
def addExternalDep(src: File, dep: String, depAPI: Source, inherited: Boolean): Analysis =
|
||||
copy( stamps, apis.markExternalAPI(dep, depAPI), relations.addExternalDep(src, dep, inherited), infos )
|
||||
|
||||
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis =
|
||||
copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos )
|
||||
|
|
|
|||
|
|
@ -62,12 +62,17 @@ private final class AnalysisCallback(internalMap: File => Option[File], external
|
|||
private[this] val unreporteds = new HashMap[File, ListBuffer[Problem]]
|
||||
private[this] val reporteds = new HashMap[File, ListBuffer[Problem]]
|
||||
private[this] val binaryDeps = new HashMap[File, Set[File]]
|
||||
// source file to set of generated (class file, class name)
|
||||
// source file to set of generated (class file, class name)
|
||||
private[this] val classes = new HashMap[File, Set[(File, String)]]
|
||||
// generated class file to its source file
|
||||
// generated class file to its source file
|
||||
private[this] val classToSource = new HashMap[File, File]
|
||||
// all internal source depenencies, including direct and inherited
|
||||
private[this] val sourceDeps = new HashMap[File, Set[File]]
|
||||
private[this] val extSrcDeps = new ListBuffer[(File, String, Source)]
|
||||
// inherited internal source dependencies
|
||||
private[this] val inheritedSourceDeps = new HashMap[File, Set[File]]
|
||||
// external source dependencies:
|
||||
// (internal source, external source depended on, API of external dependency, true if an inheritance dependency)
|
||||
private[this] val extSrcDeps = new ListBuffer[(File, String, Source, Boolean)]
|
||||
private[this] val binaryClassName = new HashMap[File, String]
|
||||
// source files containing a macro def.
|
||||
private[this] val macroSources = Set[File]()
|
||||
|
|
@ -83,41 +88,45 @@ private final class AnalysisCallback(internalMap: File => Option[File], external
|
|||
}
|
||||
}
|
||||
|
||||
def sourceDependency(dependsOn: File, source: File) = if(source != dependsOn) add(sourceDeps, source, dependsOn)
|
||||
def externalBinaryDependency(binary: File, className: String, source: File)
|
||||
def sourceDependency(dependsOn: File, source: File, inherited: Boolean) =
|
||||
if(source != dependsOn) {
|
||||
add(sourceDeps, source, dependsOn)
|
||||
if(inherited) add(inheritedSourceDeps, source, dependsOn)
|
||||
}
|
||||
def externalBinaryDependency(binary: File, className: String, source: File, inherited: Boolean)
|
||||
{
|
||||
binaryClassName.put(binary, className)
|
||||
add(binaryDeps, source, binary)
|
||||
}
|
||||
def externalSourceDependency(triple: (File, String, Source)) = extSrcDeps += triple
|
||||
def externalSourceDependency(t4: (File, String, Source, Boolean)) = extSrcDeps += t4
|
||||
|
||||
def binaryDependency(classFile: File, name: String, source: File) =
|
||||
def binaryDependency(classFile: File, name: String, source: File, inherited: Boolean) =
|
||||
internalMap(classFile) match
|
||||
{
|
||||
case Some(dependsOn) =>
|
||||
// dependency is a product of a source not included in this compilation
|
||||
sourceDependency(dependsOn, source)
|
||||
sourceDependency(dependsOn, source, inherited)
|
||||
case None =>
|
||||
classToSource.get(classFile) match
|
||||
{
|
||||
case Some(dependsOn) =>
|
||||
// dependency is a product of a source in this compilation step,
|
||||
// but not in the same compiler run (as in javac v. scalac)
|
||||
sourceDependency(dependsOn, source)
|
||||
sourceDependency(dependsOn, source, inherited)
|
||||
case None =>
|
||||
externalDependency(classFile, name, source)
|
||||
externalDependency(classFile, name, source, inherited)
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def externalDependency(classFile: File, name: String, source: File): Unit =
|
||||
private[this] def externalDependency(classFile: File, name: String, source: File, inherited: Boolean): Unit =
|
||||
externalAPI(classFile, name) match
|
||||
{
|
||||
case Some(api) =>
|
||||
// dependency is a product of a source in another project
|
||||
externalSourceDependency( (source, name, api) )
|
||||
externalSourceDependency( (source, name, api, inherited) )
|
||||
case None =>
|
||||
// dependency is some other binary on the classpath
|
||||
externalBinaryDependency(classFile, name, source)
|
||||
externalBinaryDependency(classFile, name, source, inherited)
|
||||
}
|
||||
|
||||
def generatedClass(source: File, module: File, name: String) =
|
||||
|
|
@ -148,10 +157,12 @@ private final class AnalysisCallback(internalMap: File => Option[File], external
|
|||
val hasMacro: Boolean = macroSources.contains(src)
|
||||
val s = new xsbti.api.Source(compilation, hash, api._2, api._1, hasMacro)
|
||||
val info = SourceInfos.makeInfo(getOrNil(reporteds, src), getOrNil(unreporteds, src))
|
||||
a.addSource(src, s, stamp, sourceDeps.getOrElse(src, Nil: Iterable[File]), info)
|
||||
val direct = sourceDeps.getOrElse(src, Nil: Iterable[File])
|
||||
val publicInherited = inheritedSourceDeps.getOrElse(src, Nil: Iterable[File])
|
||||
a.addSource(src, s, stamp, direct, publicInherited, info)
|
||||
}
|
||||
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 addExternals(base: Analysis): Analysis = (base /: extSrcDeps) { case (a, (source, name, api, inherited)) => a.addExternalDep(source, name, api, inherited) }
|
||||
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 =
|
||||
|
|
|
|||
|
|
@ -6,55 +6,133 @@ package inc
|
|||
|
||||
import xsbti.api.Source
|
||||
import java.io.File
|
||||
import Relations.{Source => RSource}
|
||||
|
||||
|
||||
/** Provides mappings between source files, generated classes (products), and binaries.
|
||||
* Dependencies that are tracked include internal: a dependency on a source in the same compilation group (project),
|
||||
* external: a dependency on a source in another compilation group (tracked as the name of the class),
|
||||
* binary: a dependency on a class or jar file not generated by a source file in any tracked compilation group,
|
||||
* inherited: a dependency that resulted from a public template inheriting,
|
||||
* direct: any type of dependency, including inheritance. */
|
||||
trait Relations
|
||||
{
|
||||
/** All sources _with at least one product_ . */
|
||||
def allSources: collection.Set[File]
|
||||
|
||||
/** All products associates with sources. */
|
||||
def allProducts: collection.Set[File]
|
||||
|
||||
/** All files that are recorded as a binary dependency of a source file.*/
|
||||
def allBinaryDeps: collection.Set[File]
|
||||
|
||||
/** All files in this compilation group (project) that are recorded as a source dependency of a source file in this group.*/
|
||||
def allInternalSrcDeps: collection.Set[File]
|
||||
|
||||
/** All files in another compilation group (project) that are recorded as a source dependency of a source file in this group.*/
|
||||
def allExternalDeps: collection.Set[String]
|
||||
|
||||
/** Fully qualified names of classes defined in source file `src`. */
|
||||
def classNames(src: File): Set[String]
|
||||
|
||||
/** Names of classes defined in source file `src`. */
|
||||
def definesClass(name: String): Set[File]
|
||||
|
||||
/** The classes that were generated for source file `src`. */
|
||||
def products(src: File): Set[File]
|
||||
/** The source files that generated class file `prod`. This is typically a set containing a single file. */
|
||||
def produced(prod: File): Set[File]
|
||||
|
||||
/** The binary dependencies for the source file `src`. */
|
||||
def binaryDeps(src: File): Set[File]
|
||||
/** The source files that depend on binary file `dep`. */
|
||||
def usesBinary(dep: File): Set[File]
|
||||
|
||||
|
||||
/** Internal source dependencies for `src`. This includes both direct and inherited dependencies. */
|
||||
def internalSrcDeps(src: File): Set[File]
|
||||
/** Internal source files that depend on internal source `dep`. This includes both direct and inherited dependencies. */
|
||||
def usesInternalSrc(dep: File): Set[File]
|
||||
|
||||
/** External source dependencies that internal source file `src` depends on. This includes both direct and inherited dependencies. */
|
||||
def externalDeps(src: File): Set[String]
|
||||
/** Internal source dependencies that depend on external source file `dep`. This includes both direct and inherited dependencies. */
|
||||
def usesExternal(dep: String): Set[File]
|
||||
|
||||
/** Records internal source file `src` as generating class file `prod` with top-level class `name`. */
|
||||
def addProduct(src: File, prod: File, name: String): Relations
|
||||
def addExternalDep(src: File, dependsOn: String): Relations
|
||||
def addInternalSrcDeps(src: File, dependsOn: Iterable[File]): Relations
|
||||
|
||||
/** Records internal source file `src` as depending on class `dependsOn` in an external source file.
|
||||
* If `inherited` is true, this dependency is recorded as coming from a public template in `src` extending something in `dependsOn` (an inheritance dependency).
|
||||
* Whatever the value of `inherited`, the dependency is also recorded as a direct dependency. */
|
||||
def addExternalDep(src: File, dependsOn: String, inherited: Boolean): Relations
|
||||
|
||||
/** Records internal source file `src` depending on a dependency binary dependency `dependsOn`.*/
|
||||
def addBinaryDep(src: File, dependsOn: File): Relations
|
||||
|
||||
/** Records internal source file `src` as having direct dependencies on internal source files `directDependsOn`
|
||||
* and inheritance dependencies on `inheritedDependsOn`. Everything in `inheritedDependsOn` must be included in `directDependsOn`;
|
||||
* this method does not automatically record direct dependencies like `addExternalDep` does.*/
|
||||
def addInternalSrcDeps(src: File, directDependsOn: Iterable[File], inheritedDependsOn: Iterable[File]): Relations
|
||||
|
||||
def ++ (o: Relations): Relations
|
||||
|
||||
/** Drops all dependency mappings from `sources`. This will not remove mappings to them (that is, mappings where they are dependencies).*/
|
||||
def -- (sources: Iterable[File]): Relations
|
||||
|
||||
def groupBy[K](f: (File => K)): Map[K, Relations]
|
||||
|
||||
|
||||
/** The relation between internal sources and generated class files. */
|
||||
def srcProd: Relation[File, File]
|
||||
|
||||
/** The dependency relation between internal sources and binaries. */
|
||||
def binaryDep: Relation[File, File]
|
||||
|
||||
/** The dependency relation between internal sources. This includes both direct and inherited dependencies.*/
|
||||
def internalSrcDep: Relation[File, File]
|
||||
|
||||
/** The dependency relation between internal and external sources. This includes both direct and inherited dependencies.*/
|
||||
def externalDep: Relation[File, String]
|
||||
|
||||
/** The dependency relations between sources. These include both direct and inherited dependencies.*/
|
||||
def direct: RSource
|
||||
/** The inheritance dependency relations between sources.*/
|
||||
def publicInherited: RSource
|
||||
|
||||
/** The relation between a source file and names of classes generated from it.*/
|
||||
def classes: Relation[File, String]
|
||||
}
|
||||
|
||||
|
||||
object Relations
|
||||
{
|
||||
/** Tracks internal and external source dependencies for a specific dependency type, such as direct or inherited.*/
|
||||
final class Source private[sbt](val internal: Relation[File,File], val external: Relation[File,String]) {
|
||||
def addInternal(source: File, dependsOn: Iterable[File]): Source = new Source(internal + (source, dependsOn), external)
|
||||
def addExternal(source: File, dependsOn: String): Source = new Source(internal, external + (source, dependsOn))
|
||||
/** Drops all dependency mappings from `sources`. This will not remove mappings to them (that is, where they are dependencies).*/
|
||||
def --(sources: Iterable[File]): Source = new Source(internal -- sources, external -- sources)
|
||||
def ++(o: Source): Source = new Source(internal ++ o.internal, external ++ o.external)
|
||||
def groupBySource[K](f: File => K): Map[K, Source] = {
|
||||
val i = internal.groupBy { case (a,b) => f(a) }
|
||||
val e = external.groupBy { case (a,b) => f(a) }
|
||||
val pairs = for( k <- i.keySet ++ e.keySet ) yield
|
||||
(k, new Source( getOrEmpty(i, k), getOrEmpty(e, k) ))
|
||||
pairs.toMap
|
||||
}
|
||||
}
|
||||
|
||||
private[sbt] def getOrEmpty[A,B,K](m: Map[K, Relation[A,B]], k: K): Relation[A,B] = m.getOrElse(k, Relation.empty)
|
||||
|
||||
private[this] lazy val e = Relation.empty[File, File]
|
||||
private[this] lazy val es = Relation.empty[File, String]
|
||||
def empty: Relations = new MRelations(e, e, e, es, es)
|
||||
def make(srcProd: Relation[File, File], binaryDep: Relation[File, File], internalSrcDep: Relation[File, File], externalDep: Relation[File, String], classes: Relation[File, String]): Relations =
|
||||
new MRelations(srcProd, binaryDep, internalSrcDep, externalDep, classes)
|
||||
private[this] lazy val estr = Relation.empty[File, String]
|
||||
private[this] lazy val es = new Source(e, estr)
|
||||
|
||||
def emptySource: Source = es
|
||||
def empty: Relations = new MRelations(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 MRelations(srcProd, binaryDep, direct = direct, publicInherited = publicInherited, classes)
|
||||
def makeSource(internal: Relation[File,File], external: Relation[File,String]): Source = new Source(internal, external)
|
||||
}
|
||||
/**
|
||||
* `srcProd` is a relation between a source file and a product: (source, product).
|
||||
|
|
@ -64,23 +142,27 @@ object Relations
|
|||
* This only includes dependencies on classes and jars that do not have a corresponding source/API to track instead.
|
||||
* A class or jar with a corresponding source should only be tracked in one of the source dependency relations.
|
||||
*
|
||||
* `internalSrcDeps` is a relation between a source file and a source dependency in the same compilation group.
|
||||
* Dependencies on sources in other projects belong in external source dependencies.
|
||||
* `direct` defines relations for dependencies between internal and external source dependencies. It includes all types of
|
||||
* dependencies, including inheritance.
|
||||
*
|
||||
* `externalSrcDeps` is a relation between a source file and a source dependency in another compilation group.
|
||||
* Dependencies on sources in the same group belong in internal source dependencies.
|
||||
* `publicInherited` defines relations for internal and external source dependencies, only including dependencies
|
||||
* introduced by inheritance.
|
||||
*
|
||||
* `classes` is a relation between a source file and its generated class names.
|
||||
*/
|
||||
private class MRelations(val srcProd: Relation[File, File], val binaryDep: Relation[File, File],
|
||||
val internalSrcDep: Relation[File, File], val externalDep: Relation[File, String], val classes: Relation[File, String]) extends Relations
|
||||
// direct should include everything in inherited
|
||||
val direct: RSource, val publicInherited: RSource, val classes: Relation[File, String]) extends Relations
|
||||
{
|
||||
def internalSrcDep: Relation[File, File] = direct.internal
|
||||
def externalDep: Relation[File, String] = direct.external
|
||||
|
||||
def allSources: collection.Set[File] = srcProd._1s
|
||||
|
||||
def allProducts: collection.Set[File] = srcProd._2s
|
||||
def allBinaryDeps: collection.Set[File] = binaryDep._2s
|
||||
def allInternalSrcDeps: collection.Set[File] = internalSrcDep._2s
|
||||
def allExternalDeps: collection.Set[String] = externalDep._2s
|
||||
def allInternalSrcDeps: collection.Set[File] = direct.internal._2s
|
||||
def allExternalDeps: collection.Set[String] = direct.external._2s
|
||||
|
||||
def classNames(src: File): Set[String] = classes.forward(src)
|
||||
def definesClass(name: String): Set[File] = classes.reverse(name)
|
||||
|
|
@ -91,45 +173,52 @@ private class MRelations(val srcProd: Relation[File, File], val binaryDep: Relat
|
|||
def binaryDeps(src: File): Set[File] = binaryDep.forward(src)
|
||||
def usesBinary(dep: File): Set[File] = binaryDep.reverse(dep)
|
||||
|
||||
def internalSrcDeps(src: File): Set[File] = internalSrcDep.forward(src)
|
||||
def usesInternalSrc(dep: File): Set[File] = internalSrcDep.reverse(dep)
|
||||
def internalSrcDeps(src: File): Set[File] = direct.internal.forward(src)
|
||||
def usesInternalSrc(dep: File): Set[File] = direct.internal.reverse(dep)
|
||||
|
||||
def externalDeps(src: File): Set[String] = externalDep.forward(src)
|
||||
def usesExternal(dep: String): Set[File] = externalDep.reverse(dep)
|
||||
def externalDeps(src: File): Set[String] = direct.external.forward(src)
|
||||
def usesExternal(dep: String): Set[File] = direct.external.reverse(dep)
|
||||
|
||||
def addProduct(src: File, prod: File, name: String): Relations =
|
||||
new MRelations( srcProd + (src, prod), binaryDep, internalSrcDep, externalDep, classes + (src, name) )
|
||||
new MRelations( srcProd + (src, prod), binaryDep, direct = direct, publicInherited = publicInherited, classes + (src, name) )
|
||||
|
||||
def addExternalDep(src: File, dependsOn: String): Relations =
|
||||
new MRelations( srcProd, binaryDep, internalSrcDep, externalDep + (src, dependsOn), classes )
|
||||
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 MRelations( srcProd, binaryDep, direct = newD, publicInherited = newI, classes )
|
||||
}
|
||||
|
||||
def addInternalSrcDeps(src: File, dependsOn: Iterable[File]): Relations =
|
||||
new MRelations( srcProd, binaryDep, internalSrcDep + (src, dependsOn ), externalDep, 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 MRelations( srcProd, binaryDep, direct = newD, publicInherited = newI, classes )
|
||||
}
|
||||
|
||||
def addBinaryDep(src: File, dependsOn: File): Relations =
|
||||
new MRelations( srcProd, binaryDep + (src, dependsOn), internalSrcDep, externalDep, classes )
|
||||
new MRelations( srcProd, binaryDep + (src, dependsOn), direct = direct, publicInherited = publicInherited, classes )
|
||||
|
||||
def ++ (o: Relations): Relations =
|
||||
new MRelations(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, internalSrcDep ++ o.internalSrcDep, externalDep ++ o.externalDep, classes ++ o.classes)
|
||||
new MRelations(srcProd ++ o.srcProd, binaryDep ++ o.binaryDep, direct = direct ++ o.direct, publicInherited = publicInherited ++ o.publicInherited, classes ++ o.classes)
|
||||
def -- (sources: Iterable[File]) =
|
||||
new MRelations(srcProd -- sources, binaryDep -- sources, internalSrcDep -- sources, externalDep -- sources, classes -- sources)
|
||||
new MRelations(srcProd -- sources, binaryDep -- sources, direct = direct -- sources, publicInherited = publicInherited -- sources, classes -- sources)
|
||||
|
||||
def groupBy[K](f: File => K): Map[K, Relations] =
|
||||
{
|
||||
type MapRel[T] = Map[K, Relation[File, T]]
|
||||
def outerJoin(srcProdMap: MapRel[File], binaryDepMap: MapRel[File], internalSrcDepMap: MapRel[File],
|
||||
externalDepMap: MapRel[String], classesMap: MapRel[String]): Map[K, Relations] =
|
||||
def outerJoin(srcProdMap: MapRel[File], binaryDepMap: MapRel[File], direct: Map[K, RSource], inherited: Map[K, RSource],
|
||||
classesMap: MapRel[String]): Map[K, Relations] =
|
||||
{
|
||||
def kRelations(k: K): Relations = {
|
||||
def get[T](m: Map[K, Relation[File, T]]) = m.getOrElse(k, Relation.empty)
|
||||
new MRelations( get(srcProdMap), get(binaryDepMap), get(internalSrcDepMap), get(externalDepMap), get(classesMap) )
|
||||
def get[T](m: Map[K, Relation[File, T]]) = Relations.getOrEmpty(m, k)
|
||||
def getSrc(m: Map[K, RSource]): RSource = m.getOrElse(k, Relations.emptySource)
|
||||
new MRelations( get(srcProdMap), get(binaryDepMap), getSrc(direct), getSrc(inherited), get(classesMap) )
|
||||
}
|
||||
val keys = (srcProdMap.keySet ++ binaryDepMap.keySet ++ internalSrcDepMap.keySet ++ externalDepMap.keySet ++ classesMap.keySet).toList
|
||||
val keys = (srcProdMap.keySet ++ binaryDepMap.keySet ++ direct.keySet ++ inherited.keySet ++ classesMap.keySet).toList
|
||||
Map( keys.map( (k: K) => (k, kRelations(k)) ) : _*)
|
||||
}
|
||||
|
||||
def f1[B](item: (File, B)): K = f(item._1)
|
||||
outerJoin(srcProd.groupBy(f1), binaryDep.groupBy(f1), internalSrcDep.groupBy(f1), externalDep.groupBy(f1), classes.groupBy(f1))
|
||||
outerJoin(srcProd.groupBy(f1), binaryDep.groupBy(f1), direct.groupBySource(f), publicInherited.groupBySource(f), classes.groupBy(f1))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ final class Analyzer(val global: CallbackGlobal) extends Compat
|
|||
for(on <- inheritedDependencies.getOrElse(sourceFile, Nil: Iterable[Symbol])) processDependency(on, inherited=true)
|
||||
def processDependency(on: Symbol, inherited: Boolean)
|
||||
{
|
||||
def binaryDependency(file: File, className: String) = callback.binaryDependency(file, className, sourceFile /*, inherited*/)
|
||||
def binaryDependency(file: File, className: String) = callback.binaryDependency(file, className, sourceFile, inherited)
|
||||
val onSource = on.sourceFile
|
||||
if(onSource == null)
|
||||
{
|
||||
|
|
@ -55,7 +55,7 @@ final class Analyzer(val global: CallbackGlobal) extends Compat
|
|||
}
|
||||
}
|
||||
else
|
||||
callback.sourceDependency(onSource.file, sourceFile /*, inherited*/)
|
||||
callback.sourceDependency(onSource.file, sourceFile, inherited)
|
||||
}
|
||||
|
||||
// build list of generated classes
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ package inc
|
|||
import DefaultProtocol._
|
||||
import DefaultProtocol.tuple2Format
|
||||
import Logger.{m2o, position, problem}
|
||||
import Relations.{Source => RSource}
|
||||
|
||||
object AnalysisFormats
|
||||
{
|
||||
|
|
@ -97,8 +98,11 @@ object AnalysisFormats
|
|||
implicit def apisFormat(implicit internalF: Format[Map[File, Source]], externalF: Format[Map[String, Source]]): Format[APIs] =
|
||||
asProduct2( APIs.apply _)( as => (as.internal, as.external) )(internalF, externalF)
|
||||
|
||||
implicit def relationsFormat(implicit prodF: Format[RFF], binF: Format[RFF], intF: Format[RFF], extF: Format[RFS], csF: Format[RFS]): Format[Relations] =
|
||||
asProduct5[Relations, RFF, RFF, RFF, RFS, RFS]( (a,b,c,d,e) => Relations.make(a,b,c,d,e) )( rs => (rs.srcProd, rs.binaryDep, rs.internalSrcDep, rs.externalDep, rs.classes) )(prodF, binF, intF, extF, csF)
|
||||
implicit def relationsFormat(implicit prodF: Format[RFF], binF: Format[RFF], directF: Format[RSource], inheritedF: Format[RSource], csF: Format[RFS]): Format[Relations] =
|
||||
asProduct5[Relations, RFF, RFF, RSource, RSource, RFS]( (a,b,c,d,e) => Relations.make(a,b,c,d,e) )( rs => (rs.srcProd, rs.binaryDep, rs.direct, rs.publicInherited, rs.classes) )(prodF, binF, directF, inheritedF, csF)
|
||||
|
||||
implicit def relationsSourceFormat(implicit internalFormat: Format[Relation[File, File]], externalFormat: Format[Relation[File,String]]): Format[RSource] =
|
||||
asProduct2[RSource, RFF, RFS]( (a, b) => Relations.makeSource(a,b))( rs => (rs.internal, rs.external))
|
||||
|
||||
implicit def relationFormat[A,B](implicit af: Format[Map[A, Set[B]]], bf: Format[Map[B, Set[A]]]): Format[Relation[A,B]] =
|
||||
asProduct2[Relation[A,B], Map[A, Set[B]], Map[B, Set[A]]]( Relation.make _ )( r => (r.forwardMap, r.reverseMap) )(af, bf)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@ public interface AnalysisCallback
|
|||
/** Called to indicate that the source file <code>source</code> depends on the source file
|
||||
* <code>dependsOn</code>. Note that only source files included in the current compilation will
|
||||
* passed to this method. Dependencies on classes generated by sources not in the current compilation will
|
||||
* be passed as class dependencies to the classDependency method.*/
|
||||
public void sourceDependency(File dependsOn, File source);
|
||||
* be passed as class dependencies to the classDependency method.
|
||||
* If <code>publicInherited</code> is true, this dependency is a result of inheritance by a
|
||||
* template accessible outside of the source file. */
|
||||
public void sourceDependency(File dependsOn, File source, boolean publicInherited);
|
||||
/** Called to indicate that the source file <code>source</code> depends on the top-level
|
||||
* class named <code>name</code> from class or jar file <code>binary</code>. */
|
||||
public void binaryDependency(File binary, String name, File source);
|
||||
* class named <code>name</code> from class or jar file <code>binary</code>.
|
||||
* If <code>publicInherited</code> is true, this dependency is a result of inheritance by a
|
||||
* template accessible outside of the source file. */
|
||||
public void binaryDependency(File binary, String name, File source, boolean publicInherited);
|
||||
/** Called to indicate that the source file <code>source</code> produces a class file at
|
||||
* <code>module</code> contain class <code>name</code>.*/
|
||||
public void generatedClass(File source, File module, String name);
|
||||
|
|
|
|||
|
|
@ -49,14 +49,14 @@ private[sbt] object Analyze
|
|||
for (url <- Option(loader.getResource(tpe.replace('.', '/') + ClassExt)); file <- urlAsFile(url, log))
|
||||
{
|
||||
if(url.getProtocol == "jar")
|
||||
analysis.binaryDependency(file, tpe, source)
|
||||
analysis.binaryDependency(file, tpe, source, /*inherited = */ false) // TODO: properly handle inherited
|
||||
else
|
||||
{
|
||||
assume(url.getProtocol == "file")
|
||||
productToSource.get(file) match
|
||||
{
|
||||
case Some(dependsOn) => analysis.sourceDependency(dependsOn, source)
|
||||
case None => analysis.binaryDependency(file, tpe, source)
|
||||
case Some(dependsOn) => analysis.sourceDependency(dependsOn, source, /*inherited = */ false)
|
||||
case None => analysis.binaryDependency(file, tpe, source, /*inherited = */ false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue