mirror of https://github.com/sbt/sbt.git
Merge pull request #6699 from Nirvikalpa108/fix-#6676
Migrates Treeview.scala to use Contraband
This commit is contained in:
commit
be76165054
|
|
@ -10,24 +10,20 @@ package internal
|
|||
package graph
|
||||
package rendering
|
||||
|
||||
import sbt.internal.graph.codec.JsonProtocol.ModuleModelFormat
|
||||
import sbt.io.IO
|
||||
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.{ File, FileOutputStream, InputStream, 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
|
||||
import scala.annotation.{ nowarn, tailrec }
|
||||
|
||||
@nowarn object TreeView {
|
||||
def createJson(graph: ModuleGraph): String = {
|
||||
val trees = graph.roots
|
||||
val moduleModels = graph.roots
|
||||
.map(module => processSubtree(graph, module))
|
||||
.toList
|
||||
JSONArray(trees).toString
|
||||
val js = moduleModels.map(Converter.toJsonUnsafe(_))
|
||||
js.map(CompactPrinter).mkString("[", ",", "]")
|
||||
}
|
||||
|
||||
def createLink(graphJson: String, targetDirectory: File): URI = {
|
||||
|
|
@ -43,24 +39,26 @@ import scala.util.parsing.json.JSONObject
|
|||
graph: ModuleGraph,
|
||||
module: Module,
|
||||
parents: Set[GraphModuleId] = Set()
|
||||
): JSONObject = {
|
||||
): ModuleModel = {
|
||||
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)
|
||||
dependencies
|
||||
.map(dependency => processSubtree(graph, dependency, parents + module.id))
|
||||
.toVector
|
||||
moduleAsModuleAgain(module, cycle, children)
|
||||
}
|
||||
|
||||
private def moduleAsJson(
|
||||
private def moduleAsModuleAgain(
|
||||
module: Module,
|
||||
isCycle: Boolean,
|
||||
children: List[JSONObject]
|
||||
): JSONObject = {
|
||||
children: Vector[ModuleModel]
|
||||
): ModuleModel = {
|
||||
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 + cycle
|
||||
JSONObject(Map("text" -> text, "children" -> JSONArray(children)))
|
||||
ModuleModel(text, children)
|
||||
}
|
||||
|
||||
def saveResource(resourcePath: String, to: File): Unit = {
|
||||
|
|
|
|||
|
|
@ -5,51 +5,48 @@
|
|||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package internal
|
||||
package graph
|
||||
package rendering
|
||||
package sbt.internal.graph.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 {
|
||||
import org.scalatest.{ FlatSpec, Matchers }
|
||||
import sbt.internal.graph.rendering.TreeView.createJson
|
||||
import sbt.internal.graph.{ GraphModuleId, Module, ModuleGraph, ModuleModel }
|
||||
|
||||
class TreeViewTest extends FlatSpec with Matchers {
|
||||
val modA = GraphModuleId("orgA", "nameA", "1.0")
|
||||
val modB = GraphModuleId("orgB", "nameB", "2.0")
|
||||
val modC = GraphModuleId("orgC", "nameC", "3.0")
|
||||
|
||||
val graph = ModuleGraph(
|
||||
nodes = Seq(Module(modA), Module(modB)),
|
||||
nodes = Seq(Module(modA), Module(modB), Module(modC)),
|
||||
edges = Seq(
|
||||
modA -> modA,
|
||||
modA -> modB,
|
||||
modC -> modA,
|
||||
)
|
||||
)
|
||||
|
||||
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)
|
||||
"createJson" should "convert ModuleGraph into JSON correctly" in {
|
||||
val expected =
|
||||
"[{\"text\":\"orgC:nameC:3.0\",\"children\":[{\"text\":\"orgA:nameA:1.0\",\"children\":[{\"text\":\"orgA:nameA:1.0 (cycle)\",\"children\":[]},{\"text\":\"orgB:nameB:2.0\",\"children\":[]}]}]}]"
|
||||
Predef.assert(
|
||||
createJson(graph) == expected,
|
||||
s"Expected $expected, but got ${createJson(graph)}"
|
||||
)
|
||||
}
|
||||
|
||||
@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!")
|
||||
}
|
||||
"processSubtree" should "detect cycles and truncate" in {
|
||||
val expected = ModuleModel(
|
||||
"orgC:nameC:3.0",
|
||||
Vector(
|
||||
ModuleModel(
|
||||
"orgA:nameA:1.0",
|
||||
Vector(
|
||||
ModuleModel("orgA:nameA:1.0 (cycle)", Vector()),
|
||||
ModuleModel("orgB:nameB:2.0", Vector())
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
assert(TreeView.processSubtree(graph, Module(modC), Set()) == expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ addSbtPlugin("com.lightbend" % "sbt-whitesource" % "0.1.14")
|
|||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")
|
||||
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.8.1")
|
||||
addSbtPlugin("com.swoval" % "sbt-java-format" % "0.3.1")
|
||||
addDependencyTreePlugin
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.graph
|
||||
final class ModuleModel private (
|
||||
val text: String,
|
||||
val children: Vector[sbt.internal.graph.ModuleModel]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: ModuleModel => (this.text == x.text) && (this.children == x.children)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.graph.ModuleModel".##) + text.##) + children.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"ModuleModel(" + text + ", " + children + ")"
|
||||
}
|
||||
private[this] def copy(text: String = text, children: Vector[sbt.internal.graph.ModuleModel] = children): ModuleModel = {
|
||||
new ModuleModel(text, children)
|
||||
}
|
||||
def withText(text: String): ModuleModel = {
|
||||
copy(text = text)
|
||||
}
|
||||
def withChildren(children: Vector[sbt.internal.graph.ModuleModel]): ModuleModel = {
|
||||
copy(children = children)
|
||||
}
|
||||
}
|
||||
object ModuleModel {
|
||||
|
||||
def apply(text: String, children: Vector[sbt.internal.graph.ModuleModel]): ModuleModel = new ModuleModel(text, children)
|
||||
}
|
||||
9
protocol/src/main/contraband-scala/sbt/internal/graph/codec/JsonProtocol.scala
generated
Normal file
9
protocol/src/main/contraband-scala/sbt/internal/graph/codec/JsonProtocol.scala
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.graph.codec
|
||||
trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
||||
with sbt.internal.graph.codec.ModuleModelFormats
|
||||
object JsonProtocol extends JsonProtocol
|
||||
29
protocol/src/main/contraband-scala/sbt/internal/graph/codec/ModuleModelFormats.scala
generated
Normal file
29
protocol/src/main/contraband-scala/sbt/internal/graph/codec/ModuleModelFormats.scala
generated
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.graph.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait ModuleModelFormats { self: sbt.internal.graph.codec.ModuleModelFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val ModuleModelFormat: JsonFormat[sbt.internal.graph.ModuleModel] = new JsonFormat[sbt.internal.graph.ModuleModel] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.graph.ModuleModel = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val text = unbuilder.readField[String]("text")
|
||||
val children = unbuilder.readField[Vector[sbt.internal.graph.ModuleModel]]("children")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.graph.ModuleModel(text, children)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.graph.ModuleModel, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("text", obj.text)
|
||||
builder.addField("children", obj.children)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package sbt.internal.graph
|
||||
@target(Scala)
|
||||
@codecPackage("sbt.internal.graph.codec")
|
||||
@fullCodec("JsonProtocol")
|
||||
|
||||
type ModuleModel {
|
||||
text: String!
|
||||
children: [sbt.internal.graph.ModuleModel]
|
||||
}
|
||||
Loading…
Reference in New Issue