mirror of https://github.com/sbt/sbt.git
Handle cycles while rendering json dependency tree to json
This commit is contained in:
parent
c2cd9a0a71
commit
fcd7a3bef2
|
|
@ -10,14 +10,17 @@ package internal
|
|||
package graph
|
||||
package rendering
|
||||
|
||||
import java.io.{ OutputStream, InputStream, FileOutputStream, File }
|
||||
import java.net.URI
|
||||
|
||||
import graph.{ Module, ModuleGraph }
|
||||
import sbt.io.IO
|
||||
|
||||
import scala.annotation.{ nowarn, tailrec }
|
||||
import scala.util.parsing.json.{ JSONArray, JSONObject }
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.URI
|
||||
import scala.annotation.nowarn
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.parsing.json.JSONArray
|
||||
import scala.util.parsing.json.JSONObject
|
||||
|
||||
@nowarn object TreeView {
|
||||
def createJson(graph: ModuleGraph): String = {
|
||||
|
|
@ -36,18 +39,27 @@ import scala.util.parsing.json.{ JSONArray, JSONObject }
|
|||
new URI(graphHTML.toURI.toString)
|
||||
}
|
||||
|
||||
private def processSubtree(graph: ModuleGraph, module: Module): JSONObject = {
|
||||
val children = graph.dependencyMap
|
||||
.getOrElse(module.id, List())
|
||||
.map(module => processSubtree(graph, module))
|
||||
.toList
|
||||
moduleAsJson(module, children)
|
||||
private[rendering] def processSubtree(
|
||||
graph: ModuleGraph,
|
||||
module: Module,
|
||||
parents: Set[GraphModuleId] = Set()
|
||||
): JSONObject = {
|
||||
val cycle = parents.contains(module.id)
|
||||
val dependencies = if (cycle) List() else graph.dependencyMap.getOrElse(module.id, List())
|
||||
val children =
|
||||
dependencies.map(dependency => processSubtree(graph, dependency, parents + module.id)).toList
|
||||
moduleAsJson(module, cycle, children)
|
||||
}
|
||||
|
||||
private def moduleAsJson(module: Module, children: List[JSONObject]): JSONObject = {
|
||||
private def moduleAsJson(
|
||||
module: Module,
|
||||
isCycle: Boolean,
|
||||
children: List[JSONObject]
|
||||
): JSONObject = {
|
||||
val eviction = module.evictedByVersion.map(version => s" (evicted by $version)").getOrElse("")
|
||||
val cycle = if (isCycle) " (cycle)" else ""
|
||||
val error = module.error.map(err => s" (errors: $err)").getOrElse("")
|
||||
val text = module.id.idString + eviction + error
|
||||
val text = module.id.idString + eviction + error + cycle
|
||||
JSONObject(Map("text" -> text, "children" -> JSONArray(children)))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package internal
|
||||
package graph
|
||||
package rendering
|
||||
|
||||
import org.scalatest.DiagrammedAssertions
|
||||
import org.scalatest.FunSuite
|
||||
|
||||
import scala.annotation.nowarn
|
||||
import scala.util.parsing.json.JSONArray
|
||||
import scala.util.parsing.json.JSONObject
|
||||
|
||||
@nowarn("msg=class JSONObject in package json is deprecated")
|
||||
class TreeViewTest extends FunSuite with DiagrammedAssertions {
|
||||
|
||||
val modA = GraphModuleId("orgA", "nameA", "1.0")
|
||||
val modB = GraphModuleId("orgB", "nameB", "2.0")
|
||||
|
||||
val graph = ModuleGraph(
|
||||
nodes = Seq(Module(modA), Module(modB)),
|
||||
edges = Seq(
|
||||
modA -> modA,
|
||||
modA -> modB,
|
||||
)
|
||||
)
|
||||
|
||||
test("TreeView should detect cycles and truncate") {
|
||||
val json = TreeView.processSubtree(graph, Module(modA))
|
||||
val (rootText, children) = parseTree(json)
|
||||
assert(rootText == modA.idString)
|
||||
|
||||
val childrenText = children.map(parseTree).map(_._1)
|
||||
val expected = List(s"${modA.idString} (cycle)", modB.idString)
|
||||
assert(childrenText == expected)
|
||||
}
|
||||
|
||||
@nowarn("cat=unchecked")
|
||||
def parseTree(json: JSONObject): (String, List[JSONObject]) = {
|
||||
(json.obj.get("text"), json.obj.get("children")) match {
|
||||
case (Some(text: String), Some(JSONArray(children: List[JSONObject])))
|
||||
if children.forall(_.isInstanceOf[JSONObject]) =>
|
||||
text -> children
|
||||
case _ =>
|
||||
fail("a string field 'text' and an array of objects in 'children' field were expected!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue