Protect against missing edges in graph by using map get vs apply

This commit is contained in:
frosforever 2022-07-19 09:55:45 -04:00
parent a2060c9ba0
commit 1b21ecb1ce
4 changed files with 12 additions and 14 deletions

View File

@ -32,7 +32,7 @@ object GraphTransformations {
val nodes = val nodes =
edges edges
.foldLeft(Set.empty[GraphModuleId])((set, edge) => set + edge._1 + edge._2) .foldLeft(Set.empty[GraphModuleId])((set, edge) => set + edge._1 + edge._2)
.map(graph.module) .flatMap(graph.module)
ModuleGraph(nodes.toSeq, edges) ModuleGraph(nodes.toSeq, edges)
} }

View File

@ -67,7 +67,7 @@ private[sbt] case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) {
lazy val modules: Map[GraphModuleId, Module] = lazy val modules: Map[GraphModuleId, Module] =
nodes.map(n => (n.id, n)).toMap nodes.map(n => (n.id, n)).toMap
def module(id: GraphModuleId): Module = modules(id) def module(id: GraphModuleId): Option[Module] = modules.get(id)
lazy val dependencyMap: Map[GraphModuleId, Seq[Module]] = lazy val dependencyMap: Map[GraphModuleId, Seq[Module]] =
createMap(identity) createMap(identity)
@ -81,7 +81,7 @@ private[sbt] case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) {
val m = new HashMap[GraphModuleId, Set[Module]] with MultiMap[GraphModuleId, Module] val m = new HashMap[GraphModuleId, Set[Module]] with MultiMap[GraphModuleId, Module]
edges.foreach { entry => edges.foreach { entry =>
val (f, t) = bindingFor(entry) val (f, t) = bindingFor(entry)
m.addBinding(f, module(t)) module(t).foreach(m.addBinding(f, _))
} }
m.toMap.mapValues(_.toSeq.sortBy(_.id.idString)).toMap.withDefaultValue(Nil) m.toMap.mapValues(_.toSeq.sortBy(_.id.idString)).toMap.withDefaultValue(Nil)
} }

View File

@ -31,8 +31,8 @@ object DOT {
} }
}.sorted.mkString("\n") }.sorted.mkString("\n")
def originWasEvicted(edge: Edge): Boolean = graph.module(edge._1).isEvicted def originWasEvicted(edge: Edge): Boolean = graph.module(edge._1).exists(_.isEvicted)
def targetWasEvicted(edge: Edge): Boolean = graph.module(edge._2).isEvicted def targetWasEvicted(edge: Edge): Boolean = graph.module(edge._2).exists(_.isEvicted)
// add extra edges from evicted to evicted-by module // add extra edges from evicted to evicted-by module
val evictedByEdges: Seq[Edge] = val evictedByEdges: Seq[Edge] =
@ -43,13 +43,11 @@ object DOT {
// remove edges to new evicted-by module which is now replaced by a chain // remove edges to new evicted-by module which is now replaced by a chain
// dependend -> [evicted] -> dependee // dependend -> [evicted] -> dependee
val evictionTargetEdges = val evictionTargetEdges =
graph.edges graph.edges.collect {
.filter(targetWasEvicted) case edge @ (from, evicted) if targetWasEvicted(edge) =>
.map { // Can safely call `get` as `targetWasEvicted` already proves evicted exists in the graph
case (from, evicted) => (from, evicted.copy(version = graph.module(evicted).flatMap(_.evictedByVersion).get))
(from, evicted.copy(version = graph.module(evicted).evictedByVersion.get)) }.toSet
}
.toSet
val filteredEdges = val filteredEdges =
graph.edges graph.edges
@ -58,7 +56,7 @@ object DOT {
val edges = { val edges = {
for (e <- filteredEdges) yield { for (e <- filteredEdges) yield {
val extra = val extra =
if (graph.module(e._1).isEvicted) if (graph.module(e._1).exists(_.isEvicted))
s""" [label="Evicted By" style="$EvictedStyle"]""" s""" [label="Evicted By" style="$EvictedStyle"]"""
else "" else ""
""" "%s" -> "%s"%s""".format(e._1.idString, e._2.idString, extra) """ "%s" -> "%s"%s""".format(e._1.idString, e._2.idString, extra)

View File

@ -28,7 +28,7 @@ object Statistics {
val directDependencies = graph.dependencyMap(moduleId).filterNot(_.isEvicted).map(_.id) val directDependencies = graph.dependencyMap(moduleId).filterNot(_.isEvicted).map(_.id)
val dependencyStats = val dependencyStats =
directDependencies.map(statsFor).flatMap(_.transitiveStatsWithSelf).toMap directDependencies.map(statsFor).flatMap(_.transitiveStatsWithSelf).toMap
val selfSize = graph.module(moduleId).jarFile.filter(_.exists).map(_.length) val selfSize = graph.module(moduleId).flatMap(_.jarFile).filter(_.exists).map(_.length)
val numDirectDependencies = directDependencies.size val numDirectDependencies = directDependencies.size
val numTransitiveDependencies = dependencyStats.size val numTransitiveDependencies = dependencyStats.size
val transitiveSize = selfSize.getOrElse(0L) + dependencyStats val transitiveSize = selfSize.getOrElse(0L) + dependencyStats