Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Analysis.groupBy implementation.

  • Loading branch information...
commit 657d842238974d4ebfc2ffa098c5cdd15f505bd6 1 parent 9bf5405
Benjy authored committed
View
8 compile/inc/APIs.scala
@@ -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)
View
31 compile/inc/Analysis.scala
@@ -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
}
View
20 compile/inc/Relations.scala
@@ -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
View
2  compile/inc/SourceInfo.scala
@@ -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)
}
View
17 compile/inc/Stamp.scala
@@ -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)
View
11 util/relation/Relation.scala
@@ -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 [", ", ", "]")
Please sign in to comment.
Something went wrong with that request. Please try again.