mirror of https://github.com/sbt/sbt.git
Analysis.groupBy implementation.
This commit is contained in:
parent
9bf5405621
commit
657d842238
|
|
@ -24,10 +24,11 @@ trait APIs
|
|||
|
||||
def markInternalSource(src: File, api: Source): APIs
|
||||
def markExternalAPI(ext: String, api: Source): APIs
|
||||
|
||||
|
||||
def removeInternal(remove: Iterable[File]): APIs
|
||||
def filterExt(keep: String => Boolean): APIs
|
||||
|
||||
def groupBy[K](internal: (File) => K, keepExternal: Map[K, String => Boolean]): Map[K, APIs]
|
||||
|
||||
def internal: Map[File, Source]
|
||||
def external: Map[String, Source]
|
||||
}
|
||||
|
|
@ -58,6 +59,9 @@ private class MAPIs(val internal: Map[File, Source], val external: Map[String, S
|
|||
def removeInternal(remove: Iterable[File]): APIs = new MAPIs(internal -- remove, external)
|
||||
def filterExt(keep: String => Boolean): APIs = new MAPIs(internal, external.filterKeys(keep))
|
||||
|
||||
def groupBy[K](f: (File) => K, keepExternal: Map[K, String => Boolean]): Map[K, APIs] =
|
||||
internal.groupBy(item => f(item._1)) map { group => (group._1, new MAPIs(group._2, external).filterExt(keepExternal.getOrElse(group._1, _ => false)))}
|
||||
|
||||
def internalAPI(src: File) = getAPI(internal, src)
|
||||
def externalAPI(ext: String) = getAPI(external, ext)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ trait Analysis
|
|||
def addExternalDep(src: File, dep: String, api: Source): Analysis
|
||||
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis
|
||||
|
||||
def groupBy[K](f: (File => K)): Map[K, Analysis]
|
||||
|
||||
override lazy val toString = Analysis.summary(this)
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +63,7 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat
|
|||
def -- (sources: Iterable[File]): Analysis =
|
||||
{
|
||||
val newRelations = relations -- sources
|
||||
def keep[T](f: (Relations, T) => Set[_]): T => Boolean = file => !f(newRelations, file).isEmpty
|
||||
def keep[T](f: (Relations, T) => Set[_]): T => Boolean = keepFor(newRelations)(f)
|
||||
|
||||
val newAPIs = apis.removeInternal(sources).filterExt( keep(_ usesExternal _) )
|
||||
val newStamps = stamps.filter( keep(_ produced _), sources, keep(_ usesBinary _))
|
||||
|
|
@ -81,4 +83,31 @@ private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relat
|
|||
|
||||
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis =
|
||||
copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos )
|
||||
|
||||
def groupBy[K](f: File => K): Map[K, Analysis] =
|
||||
{
|
||||
def outerJoin(stampsMap: Map[K, Stamps], apisMap: Map[K, APIs], relationsMap: Map[K, Relations], infosMap: Map[K, SourceInfos]): Map[K, Analysis] =
|
||||
{
|
||||
def kAnalysis(k: K): Analysis =
|
||||
new MAnalysis(
|
||||
stampsMap.getOrElse(k, Stamps.empty),
|
||||
apisMap.getOrElse(k, APIs.empty),
|
||||
relationsMap.getOrElse(k, Relations.empty),
|
||||
infosMap.getOrElse(k, SourceInfos.empty)
|
||||
)
|
||||
val keys = (stampsMap.keySet ++ apisMap.keySet ++ relationsMap.keySet ++ infosMap.keySet).toList
|
||||
Map( keys map( (k: K) => (k, kAnalysis(k)) ) :_*)
|
||||
}
|
||||
|
||||
val relationsMap: Map[K, Relations] = relations.groupBy(f)
|
||||
def keepMap[T](f: (Relations, T) => Set[_]): Map[K, T => Boolean] =
|
||||
relationsMap map { item => (item._1, keepFor(item._2)(f) ) }
|
||||
|
||||
val keepExternal: Map[K, String => Boolean] = keepMap(_ usesExternal _)
|
||||
val keepProduced: Map[K, File => Boolean] = keepMap(_ produced _)
|
||||
val keepBinary: Map[K, File => Boolean] = keepMap(_ usesBinary _)
|
||||
outerJoin(stamps.groupBy(keepProduced, f, keepBinary), apis.groupBy(f, keepExternal), relationsMap, infos.groupBy(f))
|
||||
}
|
||||
|
||||
private def keepFor[T](newRelations: Relations)(f: (Relations, T) => Set[_]): T => Boolean = file => !f(newRelations, file).isEmpty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ trait Relations
|
|||
|
||||
def ++ (o: Relations): Relations
|
||||
def -- (sources: Iterable[File]): Relations
|
||||
def groupBy[K](f: (File => K)): Map[K, Relations]
|
||||
|
||||
def srcProd: Relation[File, File]
|
||||
def binaryDep: Relation[File, File]
|
||||
|
|
@ -113,6 +114,25 @@ private class MRelations(val srcProd: Relation[File, File], val binaryDep: Relat
|
|||
def -- (sources: Iterable[File]) =
|
||||
new MRelations(srcProd -- sources, binaryDep -- sources, internalSrcDep -- sources, externalDep -- 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 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) )
|
||||
}
|
||||
val keys = (srcProdMap.keySet ++ binaryDepMap.keySet ++ internalSrcDepMap.keySet ++ externalDepMap.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))
|
||||
}
|
||||
|
||||
|
||||
/** Making large Relations a little readable. */
|
||||
private val userDir = sys.props("user.dir").stripSuffix("/") + "/"
|
||||
private def nocwd(s: String) = s stripPrefix userDir
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ trait SourceInfos
|
|||
def ++(o: SourceInfos): SourceInfos
|
||||
def add(file: File, info: SourceInfo): SourceInfos
|
||||
def --(files: Iterable[File]): SourceInfos
|
||||
def groupBy[K](f: (File) => K): Map[K, SourceInfos]
|
||||
def get(file: File): SourceInfo
|
||||
def allInfos: Map[File, SourceInfo]
|
||||
}
|
||||
|
|
@ -31,6 +32,7 @@ private final class MSourceInfos(val allInfos: Map[File, SourceInfo]) extends So
|
|||
{
|
||||
def ++(o: SourceInfos) = new MSourceInfos(allInfos ++ o.allInfos)
|
||||
def --(sources: Iterable[File]) = new MSourceInfos(allInfos -- sources)
|
||||
def groupBy[K](f: (File) => K): Map[K, SourceInfos] = allInfos.groupBy(item => f(item._1)) map { group => (group._1, new MSourceInfos(group._2)) }
|
||||
def add(file: File, info: SourceInfo) = new MSourceInfos(allInfos + ((file, info)))
|
||||
def get(file:File) = allInfos.getOrElse(file, SourceInfos.emptyInfo)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ trait Stamps extends ReadStamps
|
|||
def filter(prod: File => Boolean, removeSources: Iterable[File], bin: File => Boolean): Stamps
|
||||
|
||||
def ++ (o: Stamps): Stamps
|
||||
def groupBy[K](prod: Map[K, File => Boolean], sourcesGrouping: File => K, bin: Map[K, File => Boolean]): Map[K, Stamps]
|
||||
}
|
||||
|
||||
sealed trait Stamp
|
||||
|
|
@ -111,6 +112,22 @@ private class MStamps(val products: Map[File, Stamp], val sources: Map[File, Sta
|
|||
def filter(prod: File => Boolean, removeSources: Iterable[File], bin: File => Boolean): Stamps =
|
||||
new MStamps(products.filterKeys(prod), sources -- removeSources, binaries.filterKeys(bin), classNames.filterKeys(bin))
|
||||
|
||||
def groupBy[K](prod: Map[K, File => Boolean], sourcesGrouping: File => K, bin: Map[K, File => Boolean]): Map[K, Stamps] =
|
||||
{
|
||||
val sourcesMap: Map[K, Map[File, Stamp]] = sources.groupBy(item => sourcesGrouping(item._1))
|
||||
|
||||
val constFalse = (f: File) => false
|
||||
def kStamps(k: K): Stamps = new MStamps(
|
||||
products.filterKeys(prod.getOrElse(k, constFalse)),
|
||||
sourcesMap.getOrElse(k, Map.empty[File,Stamp]),
|
||||
binaries.filterKeys(bin.getOrElse(k, constFalse)),
|
||||
classNames.filterKeys(bin.getOrElse(k, constFalse))
|
||||
)
|
||||
|
||||
val keys = (prod.keySet ++ sourcesMap.keySet ++ bin.keySet).toList
|
||||
Map( keys.map( (k: K) => (k, kStamps(k)) ) : _*)
|
||||
}
|
||||
|
||||
def product(prod: File) = getStamp(products, prod)
|
||||
def internalSource(src: File) = getStamp(sources, src)
|
||||
def binary(bin: File) = getStamp(binaries, bin)
|
||||
|
|
|
|||
|
|
@ -72,10 +72,13 @@ trait Relation[A,B]
|
|||
def contains(a: A, b: B): Boolean
|
||||
/** Returns a relation with only pairs (a,b) for which f(a,b) is true.*/
|
||||
def filter(f: (A,B) => Boolean): Relation[A,B]
|
||||
|
||||
|
||||
/** Partitions this relation into a map of relations according to some discriminator function. */
|
||||
def groupBy[K](f: ((A,B)) => K): Map[K, Relation[A,B]]
|
||||
|
||||
/** Returns all pairs in this relation.*/
|
||||
def all: Traversable[(A,B)]
|
||||
|
||||
|
||||
def forwardMap: Map[A, Set[B]]
|
||||
def reverseMap: Map[B, Set[A]]
|
||||
}
|
||||
|
|
@ -93,7 +96,7 @@ private final class MRelation[A,B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]]) ext
|
|||
def size = fwd.size
|
||||
|
||||
def all: Traversable[(A,B)] = fwd.iterator.flatMap { case (a, bs) => bs.iterator.map( b => (a,b) ) }.toTraversable
|
||||
|
||||
|
||||
def +(pair: (A,B)) = this + (pair._1, Set(pair._2))
|
||||
def +(from: A, to: B) = this + (from, to :: Nil)
|
||||
def +(from: A, to: Traversable[B]) =
|
||||
|
|
@ -116,6 +119,8 @@ private final class MRelation[A,B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]]) ext
|
|||
|
||||
def filter(f: (A,B) => Boolean): Relation[A,B] = Relation.empty[A,B] ++ all.filter(f.tupled)
|
||||
|
||||
def groupBy[K](f: ((A,B)) => K): Map[K, Relation[A,B]] = all.groupBy(f) mapValues { Relation.empty[A,B] ++ _ }
|
||||
|
||||
def contains(a: A, b: B): Boolean = forward(a)(b)
|
||||
|
||||
override def toString = all.map { case (a,b) => a + " -> " + b }.mkString("Relation [", ", ", "]")
|
||||
|
|
|
|||
Loading…
Reference in New Issue