2010-06-27 15:18:35 +02:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2010 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package sbt
|
|
|
|
|
package inc
|
|
|
|
|
|
|
|
|
|
import xsbti.api.Source
|
|
|
|
|
import java.io.File
|
|
|
|
|
|
|
|
|
|
trait Analysis
|
|
|
|
|
{
|
|
|
|
|
val stamps: Stamps
|
|
|
|
|
val apis: APIs
|
|
|
|
|
val relations: Relations
|
2012-03-18 00:31:55 +01:00
|
|
|
val infos: SourceInfos
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
def ++(other: Analysis): Analysis
|
|
|
|
|
def -- (sources: Iterable[File]): Analysis
|
2012-03-18 00:31:55 +01:00
|
|
|
def copy(stamps: Stamps = stamps, apis: APIs = apis, relations: Relations = relations, infos: SourceInfos = infos): Analysis
|
2010-06-27 15:18:35 +02:00
|
|
|
|
2012-03-18 00:31:55 +01:00
|
|
|
def addSource(src: File, api: Source, stamp: Stamp, internalDeps: Iterable[File], info: SourceInfo): Analysis
|
2010-09-18 03:38:40 +02:00
|
|
|
def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis
|
2010-06-27 15:18:35 +02:00
|
|
|
def addExternalDep(src: File, dep: String, api: Source): Analysis
|
2011-07-18 23:14:22 +02:00
|
|
|
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis
|
2011-05-30 01:17:31 +02:00
|
|
|
|
2012-10-11 03:21:44 +02:00
|
|
|
def groupBy[K](f: (File => K)): Map[K, Analysis]
|
|
|
|
|
|
2011-05-30 01:17:31 +02:00
|
|
|
override lazy val toString = Analysis.summary(this)
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object Analysis
|
|
|
|
|
{
|
2012-03-18 00:31:55 +01:00
|
|
|
lazy val Empty: Analysis = new MAnalysis(Stamps.empty, APIs.empty, Relations.empty, SourceInfos.empty)
|
2011-05-30 01:17:31 +02:00
|
|
|
def summary(a: Analysis): String =
|
|
|
|
|
{
|
|
|
|
|
val (j, s) = a.apis.allInternalSources.partition(_.getName.endsWith(".java"))
|
|
|
|
|
val c = a.stamps.allProducts
|
|
|
|
|
val ext = a.apis.allExternals
|
|
|
|
|
val jars = a.relations.allBinaryDeps.filter(_.getName.endsWith(".jar"))
|
2012-03-18 00:31:55 +01:00
|
|
|
val unreportedCount = a.infos.allInfos.values.map(_.unreportedProblems.size).sum
|
2011-05-30 01:17:31 +02:00
|
|
|
val sections =
|
|
|
|
|
counted("Scala source", "", "s", s.size) ++
|
|
|
|
|
counted("Java source", "", "s", j.size) ++
|
|
|
|
|
counted("class", "", "es", c.size) ++
|
|
|
|
|
counted("external source dependenc", "y", "ies", ext.size) ++
|
2012-03-18 00:31:55 +01:00
|
|
|
counted("binary dependenc", "y", "ies", jars.size) ++
|
|
|
|
|
counted("unreported warning", "", "s", unreportedCount)
|
2011-05-30 01:17:31 +02:00
|
|
|
sections.mkString("Analysis: ", ", ", "")
|
|
|
|
|
}
|
2012-07-10 18:51:34 +02:00
|
|
|
|
|
|
|
|
def counted(prefix: String, single: String, plural: String, count: Int): Option[String] =
|
|
|
|
|
count match
|
|
|
|
|
{
|
|
|
|
|
case 0 => None
|
|
|
|
|
case 1 => Some("1 " + prefix + single)
|
|
|
|
|
case x => Some(x.toString + " " + prefix + plural)
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
2012-03-18 00:31:55 +01:00
|
|
|
private class MAnalysis(val stamps: Stamps, val apis: APIs, val relations: Relations, val infos: SourceInfos) extends Analysis
|
2010-06-27 15:18:35 +02:00
|
|
|
{
|
2012-03-18 00:31:55 +01:00
|
|
|
def ++ (o: Analysis): Analysis = new MAnalysis(stamps ++ o.stamps, apis ++ o.apis, relations ++ o.relations, infos ++ o.infos)
|
2010-06-27 15:18:35 +02:00
|
|
|
def -- (sources: Iterable[File]): Analysis =
|
|
|
|
|
{
|
|
|
|
|
val newRelations = relations -- sources
|
2012-10-11 03:21:44 +02:00
|
|
|
def keep[T](f: (Relations, T) => Set[_]): T => Boolean = keepFor(newRelations)(f)
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
val newAPIs = apis.removeInternal(sources).filterExt( keep(_ usesExternal _) )
|
|
|
|
|
val newStamps = stamps.filter( keep(_ produced _), sources, keep(_ usesBinary _))
|
2012-03-18 00:31:55 +01:00
|
|
|
val newInfos = infos -- sources
|
|
|
|
|
new MAnalysis(newStamps, newAPIs, newRelations, newInfos)
|
2010-06-27 15:18:35 +02:00
|
|
|
}
|
2012-03-18 00:31:55 +01:00
|
|
|
def copy(stamps: Stamps, apis: APIs, relations: Relations, infos: SourceInfos): Analysis = new MAnalysis(stamps, apis, relations, infos)
|
2010-06-27 15:18:35 +02:00
|
|
|
|
2012-03-18 00:31:55 +01:00
|
|
|
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) )
|
2010-06-27 15:18:35 +02:00
|
|
|
|
2010-09-18 03:38:40 +02:00
|
|
|
def addBinaryDep(src: File, dep: File, className: String, stamp: Stamp): Analysis =
|
2012-03-18 00:31:55 +01:00
|
|
|
copy( stamps.markBinary(dep, className, stamp), apis, relations.addBinaryDep(src, dep), infos )
|
2010-06-27 15:18:35 +02:00
|
|
|
|
|
|
|
|
def addExternalDep(src: File, dep: String, depAPI: Source): Analysis =
|
2012-03-18 00:31:55 +01:00
|
|
|
copy( stamps, apis.markExternalAPI(dep, depAPI), relations.addExternalDep(src, dep), infos )
|
2010-06-27 15:18:35 +02:00
|
|
|
|
2011-07-18 23:14:22 +02:00
|
|
|
def addProduct(src: File, product: File, stamp: Stamp, name: String): Analysis =
|
2012-03-18 00:31:55 +01:00
|
|
|
copy( stamps.markProduct(product, stamp), apis, relations.addProduct(src, product, name), infos )
|
2012-10-11 03:21:44 +02:00
|
|
|
|
|
|
|
|
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
|
2012-07-10 18:51:34 +02:00
|
|
|
}
|