From 0c4bc73a64de7dcb6530bb7f32d94084bc0badc9 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 17 Nov 2015 17:32:02 +0100 Subject: [PATCH] enable Scalariform auto-formatting --- build.sbt | 2 + .../sbt/graph/DependencyGraphKeys.scala | 7 +- .../sbt/graph/DependencyGraphSettings.scala | 108 +++++++++--------- .../sbt/graph/GraphTransformations.scala | 10 +- .../net/virtualvoid/sbt/graph/Main.scala | 2 +- .../sbt/graph/frontend/IvyReport.scala | 16 +-- .../net/virtualvoid/sbt/graph/model.scala | 14 +-- .../sbt/graph/rendering/AsciiGraph.scala | 2 +- .../sbt/graph/rendering/AsciiTree.scala | 8 +- .../virtualvoid/sbt/graph/rendering/DOT.scala | 14 +-- .../sbt/graph/rendering/GraphML.scala | 26 ++--- .../sbt/graph/util/AsciiTreeLayout.scala | 78 ++++++------- .../sbt/graph/util/AsciiTreeLayoutSpecs.scala | 46 ++++---- 13 files changed, 164 insertions(+), 169 deletions(-) diff --git a/build.sbt b/build.sbt index 201ba01c7..4cec1065f 100644 --- a/build.sbt +++ b/build.sbt @@ -24,3 +24,5 @@ sbt.CrossBuilding.latestCompatibleVersionMapper ~= { case x => original(x) } } + +ScalariformSupport.formatSettings \ No newline at end of file diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala index a33f347f2..a5e8cf944 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala @@ -25,7 +25,7 @@ trait DependencyGraphKeys { "Creates a graphml file containing the dependency-graph for a project") val dependencyDotFile = SettingKey[File]("dependency-dot-file", "The location the dot file should be generated at") - val dependencyDotNodeLabel = SettingKey[(String,String,String) => String]("dependency-dot-node-label", + val dependencyDotNodeLabel = SettingKey[(String, String, String) ⇒ String]("dependency-dot-node-label", "Returns a formated string of a dependency. Takes organisation, name and version as parameters") val dependencyDotHeader = SettingKey[String]("dependency-dot-header", "The header of the dot file. (e.g. to set your preferred node shapes)") @@ -41,14 +41,13 @@ trait DependencyGraphKeys { "Returns a string containing an ascii tree representation of the dependency graph for a project") val dependencyTree = TaskKey[Unit]("dependency-tree", "Prints the ascii tree to the console") - val ivyReportFunction = TaskKey[String => File]("ivy-report-function", + val ivyReportFunction = TaskKey[String ⇒ File]("ivy-report-function", "A function which returns the file containing the ivy report from the ivy cache for a given configuration") val ivyReport = TaskKey[File]("ivy-report", "A task which returns the location of the ivy report file for a given configuration (default `compile`).") val ignoreMissingUpdate = Keys.update in ivyReport val filterScalaLibrary = SettingKey[Boolean]("filter-scala-library", - "Specifies if scala dependency should be filtered in dependency-* output" - ) + "Specifies if scala dependency should be filtered in dependency-* output") val licenseInfo = TaskKey[Unit]("dependency-license-info", "Aggregates and shows information about the licenses of dependencies") diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala index 9f8bffce5..ea8c9f681 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala @@ -31,29 +31,28 @@ object DependencyGraphSettings { import ModuleGraphProtocol._ def graphSettings = Seq( - ivyReportFunction <<= (sbtVersion, target, projectID, ivyModule, appConfiguration, streams) map { (sbtV, target, projectID, ivyModule, config, streams) => + ivyReportFunction <<= (sbtVersion, target, projectID, ivyModule, appConfiguration, streams) map { (sbtV, target, projectID, ivyModule, config, streams) ⇒ sbtV match { - case Version(0, min, fix, _) if min > 12 || (min == 12 && fix >= 3) => - (c: String) => file("%s/resolution-cache/reports/%s-%s-%s.xml".format(target, projectID.organization, crossName(ivyModule), c)) - case Version(0, min, fix, _) if min == 12 && fix >= 1 && fix < 3 => - ivyModule.withModule(streams.log) { (i, moduleDesc, _) => + case Version(0, min, fix, _) if min > 12 || (min == 12 && fix >= 3) ⇒ + (c: String) ⇒ file("%s/resolution-cache/reports/%s-%s-%s.xml".format(target, projectID.organization, crossName(ivyModule), c)) + case Version(0, min, fix, _) if min == 12 && fix >= 1 && fix < 3 ⇒ + ivyModule.withModule(streams.log) { (i, moduleDesc, _) ⇒ val id = ResolveOptions.getDefaultResolveId(moduleDesc) - (c: String) => file("%s/resolution-cache/reports/%s/%s-resolved.xml" format (target, id,c)) + (c: String) ⇒ file("%s/resolution-cache/reports/%s/%s-resolved.xml" format (target, id, c)) } - case _ => + case _ ⇒ val home = config.provider.scalaProvider.launcher.ivyHome - (c: String) => file("%s/cache/%s-%s-%s.xml" format (home, projectID.organization, crossName(ivyModule), c)) + (c: String) ⇒ file("%s/cache/%s-%s-%s.xml" format (home, projectID.organization, crossName(ivyModule), c)) } }, - updateConfiguration in ignoreMissingUpdate <<= updateConfiguration(config => new UpdateConfiguration(config.retrieve, true, config.logging)), + updateConfiguration in ignoreMissingUpdate <<= updateConfiguration(config ⇒ new UpdateConfiguration(config.retrieve, true, config.logging)), ignoreMissingUpdateT, - filterScalaLibrary in Global := true - ) ++ Seq(Compile, Test, Runtime, Provided, Optional).flatMap(ivyReportForConfig) + filterScalaLibrary in Global := true) ++ Seq(Compile, Test, Runtime, Provided, Optional).flatMap(ivyReportForConfig) def ivyReportForConfig(config: Configuration) = inConfig(config)(Seq( - ivyReport <<= ivyReportFunction map (_(config.toString)) dependsOn(ignoreMissingUpdate), + ivyReport <<= ivyReportFunction map (_(config.toString)) dependsOn (ignoreMissingUpdate), moduleGraph <<= ivyReport map (absoluteReportPath.andThen(frontend.IvyReport.fromReportFile)), - moduleGraph <<= (scalaVersion, moduleGraph, filterScalaLibrary) map { (scalaV, graph, filter) => + moduleGraph <<= (scalaVersion, moduleGraph, filterScalaLibrary) map { (scalaV, graph, filter) ⇒ if (filter) GraphTransformations.ignoreScalaLibrary(scalaV, graph) else @@ -61,8 +60,8 @@ object DependencyGraphSettings { }, moduleGraphStore <<= moduleGraph storeAs moduleGraphStore triggeredBy moduleGraph, asciiGraph <<= moduleGraph map rendering.AsciiGraph.asciiGraph, - dependencyGraph <<= InputTask(shouldForceParser) { force => - (force, moduleGraph, streams) map { (force, graph, streams) => + dependencyGraph <<= InputTask(shouldForceParser) { force ⇒ + (force, moduleGraph, streams) map { (force, graph, streams) ⇒ if (force || graph.nodes.size < 15) { streams.log.info(rendering.AsciiGraph.asciiGraph(graph)) streams.log.info("\n\n") @@ -91,35 +90,34 @@ object DependencyGraphSettings { | edge [ | arrowtail="none" | ]""".stripMargin, - dependencyDotNodeLabel := { (organisation: String, name: String, version: String) => + dependencyDotNodeLabel := { (organisation: String, name: String, version: String) ⇒ """<%s
%s
%s>""".format(organisation, name, version) }, - whatDependsOn <<= InputTask(artifactIdParser) { module => - (module, streams, moduleGraph) map { (module, streams, graph) => + whatDependsOn <<= InputTask(artifactIdParser) { module ⇒ + (module, streams, moduleGraph) map { (module, streams, graph) ⇒ streams.log.info(rendering.AsciiTree.asciiTree(GraphTransformations.reverseGraphStartingAt(graph, module))) } }, - licenseInfo <<= (moduleGraph, streams) map showLicenseInfo - )) + licenseInfo <<= (moduleGraph, streams) map showLicenseInfo)) def printAsciiGraphTask = (streams, asciiGraph) map (_.log.info(_)) def dependencyGraphMLTask = - (moduleGraph, dependencyGraphMLFile, streams) map { (graph, resultFile, streams) => + (moduleGraph, dependencyGraphMLFile, streams) map { (graph, resultFile, streams) ⇒ rendering.GraphML.saveAsGraphML(graph, resultFile.getAbsolutePath) streams.log.info("Wrote dependency graph to '%s'" format resultFile) resultFile } def dependencyDotTask = (moduleGraph, dependencyDotHeader, dependencyDotNodeLabel, dependencyDotFile, streams).map { - (graph, dotHead, nodeLabel, outFile, streams) => + (graph, dotHead, nodeLabel, outFile, streams) ⇒ val resultFile = rendering.DOT.saveAsDot(graph, dotHead, nodeLabel, outFile) streams.log.info("Wrote dependency graph to '%s'" format resultFile) resultFile } - def absoluteReportPath = (file: File) => file.getAbsolutePath + def absoluteReportPath = (file: File) ⇒ file.getAbsolutePath def print(key: TaskKey[String]) = (streams, key) map (_.log.info(_)) @@ -127,38 +125,40 @@ object DependencyGraphSettings { def showLicenseInfo(graph: ModuleGraph, streams: TaskStreams) { val output = graph.nodes.filter(_.isUsed).groupBy(_.license).toSeq.sortBy(_._1).map { - case (license, modules) => - license.getOrElse("No license specified")+"\n"+ + case (license, modules) ⇒ + license.getOrElse("No license specified") + "\n" + modules.map(_.id.idString formatted "\t %s").mkString("\n") }.mkString("\n\n") streams.log.info(output) } import Project._ - val shouldForceParser: State => Parser[Boolean] = { (state: State) => + val shouldForceParser: State ⇒ Parser[Boolean] = { (state: State) ⇒ import sbt.complete.DefaultParsers._ (Space ~> token("--force")).?.map(_.isDefined) } - val artifactIdParser: Initialize[State => Parser[ModuleId]] = - resolvedScoped { ctx => (state: State) => - val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil) + val artifactIdParser: Initialize[State ⇒ Parser[ModuleId]] = + resolvedScoped { ctx ⇒ + (state: State) ⇒ + val graph = loadFromContext(moduleGraphStore, ctx, state) getOrElse ModuleGraph(Nil, Nil) - import sbt.complete.DefaultParsers._ - def moduleFrom(modules: Seq[ModuleId]) = - modules.map { m => - (token(m.name) ~ Space ~ token(m.version)).map(_ => m) - }.reduce(_ | _) + import sbt.complete.DefaultParsers._ + def moduleFrom(modules: Seq[ModuleId]) = + modules.map { m ⇒ + (token(m.name) ~ Space ~ token(m.version)).map(_ ⇒ m) + }.reduce(_ | _) - graph.nodes.map(_.id).groupBy(_.organisation).map { - case (org, modules) => - Space ~ token(org) ~ Space ~> moduleFrom(modules) - }.reduceOption(_ | _).getOrElse { - (Space ~> token(StringBasic, "organization") ~ Space ~ token(StringBasic, "module") ~ Space ~ token(StringBasic, "version") ).map { case ((((org, _), mod), _), version) => - ModuleId(org, mod, version) + graph.nodes.map(_.id).groupBy(_.organisation).map { + case (org, modules) ⇒ + Space ~ token(org) ~ Space ~> moduleFrom(modules) + }.reduceOption(_ | _).getOrElse { + (Space ~> token(StringBasic, "organization") ~ Space ~ token(StringBasic, "module") ~ Space ~ token(StringBasic, "version")).map { + case ((((org, _), mod), _), version) ⇒ + ModuleId(org, mod, version) + } } - } } // This is to support 0.13.8's InlineConfigurationWithExcludes while not forcing 0.13.8 @@ -167,17 +167,17 @@ object DependencyGraphSettings { } def crossName(ivyModule: IvySbt#Module) = ivyModule.moduleSettings match { - case ic: InlineConfiguration => ic.module.name - case hm: HasModule if hm.getClass.getName == "sbt.InlineConfigurationWithExcludes" => hm.module.name - case _ => + case ic: InlineConfiguration ⇒ ic.module.name + case hm: HasModule if hm.getClass.getName == "sbt.InlineConfigurationWithExcludes" ⇒ hm.module.name + case _ ⇒ throw new IllegalStateException("sbt-dependency-graph plugin currently only supports InlineConfiguration of ivy settings (the default in sbt)") } val VersionPattern = """(\d+)\.(\d+)\.(\d+)(?:-(.*))?""".r object Version { def unapply(str: String): Option[(Int, Int, Int, Option[String])] = str match { - case VersionPattern(major, minor, fix, appendix) => Some((major.toInt, minor.toInt, fix.toInt, Option(appendix))) - case _ => None + case VersionPattern(major, minor, fix, appendix) ⇒ Some((major.toInt, minor.toInt, fix.toInt, Option(appendix))) + case _ ⇒ None } } @@ -195,17 +195,17 @@ object DependencyGraphSettings { // Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for: // the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked) // the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion - def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) => + def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒ (partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match { - case (Some(res), Some(sh), _) if res == sh => jars - case (Some(res), _, Some(decl)) if res == decl => jars - case _ => Nil + case (Some(res), Some(sh), _) if res == sh ⇒ jars + case (Some(res), _, Some(decl)) if res == decl ⇒ jars + case _ ⇒ Nil } - val subScalaJars: String => Seq[File] = SbtAccess.unmanagedScalaInstanceOnly.value match { - case Some(si) => subUnmanaged(si.version, si.jars) - case None => sv => if(scalaProvider.version == sv) scalaProvider.jars else Nil + val subScalaJars: String ⇒ Seq[File] = SbtAccess.unmanagedScalaInstanceOnly.value match { + case Some(si) ⇒ subUnmanaged(si.version, si.jars) + case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil } - val transform: UpdateReport => UpdateReport = r => Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars) + val transform: UpdateReport ⇒ UpdateReport = r ⇒ Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars) val show = Reference.display(thisProjectRef.value) Classpaths.cachedUpdate(s.cacheDirectory, show, ivyModule.value, (updateConfiguration in ignoreMissingUpdate).value, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, log = s.log) diff --git a/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala b/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala index dc4e976c2..c5c4e8a21 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/GraphTransformations.scala @@ -25,15 +25,15 @@ object GraphTransformations { Nil else deps.get(module) match { - case Some(deps) => - deps.flatMap { to => + case Some(deps) ⇒ + deps.flatMap { to ⇒ (module, to.id) +: visit(to.id, visited + module) } - case None => Nil + case None ⇒ Nil } val edges = visit(root, Set.empty) - val nodes = edges.foldLeft(Set.empty[ModuleId])((set, edge) => set + edge._1 + edge._2).map(graph.module) + val nodes = edges.foldLeft(Set.empty[ModuleId])((set, edge) ⇒ set + edge._1 + edge._2).map(graph.module) ModuleGraph(nodes.toSeq, edges) } @@ -52,7 +52,7 @@ object GraphTransformations { } val newNodes = graph.nodes.map(addScalaLibraryAnnotation).filterNot(isScalaLibrary) - val newEdges = graph.edges.filterNot(e => isScalaLibraryId(e._2)) + val newEdges = graph.edges.filterNot(e ⇒ isScalaLibraryId(e._2)) ModuleGraph(newNodes, newEdges) } } diff --git a/src/main/scala/net/virtualvoid/sbt/graph/Main.scala b/src/main/scala/net/virtualvoid/sbt/graph/Main.scala index 497258260..5d031abc9 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/Main.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/Main.scala @@ -26,7 +26,7 @@ object Main extends App { def usage: String = "Usage: " - val reportFile = args.lift(0).filter(f => new File(f).exists).getOrElse(die(usage)) + val reportFile = args.lift(0).filter(f ⇒ new File(f).exists).getOrElse(die(usage)) val outputFile = args.lift(1).getOrElse(die(usage)) val graph = frontend.IvyReport.fromReportFile(reportFile) rendering.GraphML.saveAsGraphML(graph, outputFile) diff --git a/src/main/scala/net/virtualvoid/sbt/graph/frontend/IvyReport.scala b/src/main/scala/net/virtualvoid/sbt/graph/frontend/IvyReport.scala index 94c9b61e9..164b154ea 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/frontend/IvyReport.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/frontend/IvyReport.scala @@ -18,7 +18,7 @@ package net.virtualvoid.sbt.graph.frontend import net.virtualvoid.sbt.graph._ -import scala.xml.{NodeSeq, Document, Node} +import scala.xml.{ NodeSeq, Document, Node } import scala.xml.parsing.ConstructingParser object IvyReport { @@ -28,16 +28,16 @@ object IvyReport { def fromReportXML(doc: Document): ModuleGraph = { def edgesForModule(id: ModuleId, revision: NodeSeq): Seq[Edge] = for { - caller <- revision \ "caller" + caller ← revision \ "caller" callerModule = moduleIdFromElement(caller, caller.attribute("callerrev").get.text) } yield (moduleIdFromElement(caller, caller.attribute("callerrev").get.text), id) val moduleEdges: Seq[(Module, Seq[Edge])] = for { - mod <- doc \ "dependencies" \ "module" - revision <- mod \ "revision" - rev = revision.attribute("name").get.text - moduleId = moduleIdFromElement(mod, rev) - module = Module(moduleId, + mod ← doc \ "dependencies" \ "module" + revision ← mod \ "revision" + rev = revision.attribute("name").get.text + moduleId = moduleIdFromElement(mod, rev) + module = Module(moduleId, (revision \ "license").headOption.flatMap(_.attribute("name")).map(_.text), evictedByVersion = (revision \ "evicted-by").headOption.flatMap(_.attribute("rev").map(_.text)), error = revision.attribute("error").map(_.text)) @@ -47,7 +47,7 @@ object IvyReport { val info = (doc \ "info").head def infoAttr(name: String): String = - info.attribute(name).getOrElse(throw new IllegalArgumentException("Missing attribute "+name)).text + info.attribute(name).getOrElse(throw new IllegalArgumentException("Missing attribute " + name)).text val rootModule = Module(ModuleId(infoAttr("organisation"), infoAttr("module"), infoAttr("revision"))) ModuleGraph(rootModule +: nodes, edges.flatten) diff --git a/src/main/scala/net/virtualvoid/sbt/graph/model.scala b/src/main/scala/net/virtualvoid/sbt/graph/model.scala index 9af79d129..f4b51cfcb 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/model.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/model.scala @@ -16,12 +16,12 @@ package net.virtualvoid.sbt.graph -import scala.collection.mutable.{MultiMap, HashMap, Set} +import scala.collection.mutable.{ MultiMap, HashMap, Set } case class ModuleId(organisation: String, name: String, version: String) { - def idString: String = organisation+":"+name+":"+version + def idString: String = organisation + ":" + name + ":" + version } case class Module(id: ModuleId, license: Option[String] = None, @@ -34,7 +34,7 @@ case class Module(id: ModuleId, case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) { lazy val modules: Map[ModuleId, Module] = - nodes.map(n => (n.id, n)).toMap + nodes.map(n ⇒ (n.id, n)).toMap def module(id: ModuleId): Module = modules(id) @@ -42,11 +42,11 @@ case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) { createMap(identity) lazy val reverseDependencyMap: Map[ModuleId, Seq[Module]] = - createMap { case (a, b) => (b, a) } + createMap { case (a, b) ⇒ (b, a) } - def createMap(bindingFor: ((ModuleId, ModuleId)) => (ModuleId, ModuleId)): Map[ModuleId, Seq[Module]] = { + def createMap(bindingFor: ((ModuleId, ModuleId)) ⇒ (ModuleId, ModuleId)): Map[ModuleId, Seq[Module]] = { val m = new HashMap[ModuleId, Set[Module]] with MultiMap[ModuleId, Module] - edges.foreach { entry => + edges.foreach { entry ⇒ val (f, t) = bindingFor(entry) m.addBinding(f, module(t)) } @@ -54,7 +54,7 @@ case class ModuleGraph(nodes: Seq[Module], edges: Seq[Edge]) { } } -import sbinary.{Format, DefaultProtocol} +import sbinary.{ Format, DefaultProtocol } object ModuleGraphProtocol extends DefaultProtocol { implicit def seqFormat[T: Format]: Format[Seq[T]] = wrap[Seq[T], List[T]](_.toList, _.toSeq) implicit val ModuleIdFormat: Format[ModuleId] = asProduct3(ModuleId)(ModuleId.unapply(_).get) diff --git a/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala b/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala index f4b21ea95..8da025149 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiGraph.scala @@ -28,7 +28,7 @@ object AsciiGraph { module.id.name + module.extraInfo + "\n" + module.id.organisation + "\n" + module.id.version + - module.error.map("\nerror: "+_).getOrElse("") + + module.error.map("\nerror: " + _).getOrElse("") + module.evictedByVersion.map(_ formatted "\nevicted by: %s").getOrElse("") val vertices = moduleGraph.nodes.map(renderVertex).toList diff --git a/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala b/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala index d406a310e..0843affbf 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/rendering/AsciiTree.scala @@ -25,15 +25,15 @@ object AsciiTree { val deps = graph.dependencyMap // there should only be one root node (the project itself) - val roots = graph.nodes.filter(n => !graph.edges.exists(_._2 == n.id)).sortBy(_.id.idString) - roots.map { root => - AsciiTreeLayout.toAscii[Module](root, node => deps.getOrElse(node.id, Seq.empty[Module]), displayModule) + val roots = graph.nodes.filter(n ⇒ !graph.edges.exists(_._2 == n.id)).sortBy(_.id.idString) + roots.map { root ⇒ + AsciiTreeLayout.toAscii[Module](root, node ⇒ deps.getOrElse(node.id, Seq.empty[Module]), displayModule) }.mkString("\n") } def displayModule(module: Module): String = red(module.id.idString + module.extraInfo + - module.error.map(" (error: "+_+")").getOrElse("") + + module.error.map(" (error: " + _ + ")").getOrElse("") + module.evictedByVersion.map(_ formatted " (evicted by: %s)").getOrElse(""), module.hadError) } diff --git a/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala b/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala index e7cb2c3f5..3eb168e5b 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/rendering/DOT.scala @@ -23,19 +23,17 @@ import net.virtualvoid.sbt.graph.ModuleGraph object DOT { def saveAsDot(graph: ModuleGraph, dotHead: String, - nodeFormation: (String, String, String) => String, + nodeFormation: (String, String, String) ⇒ String, outputFile: File): File = { val nodes = { - for (n <- graph.nodes) - yield - """ "%s"[label=%s]""".format(n.id.idString, - nodeFormation(n.id.organisation, n.id.name, n.id.version)) + for (n ← graph.nodes) + yield """ "%s"[label=%s]""".format(n.id.idString, + nodeFormation(n.id.organisation, n.id.name, n.id.version)) }.mkString("\n") val edges = { - for ( e <- graph.edges) - yield - """ "%s" -> "%s"""".format(e._1.idString, e._2.idString) + for (e ← graph.edges) + yield """ "%s" -> "%s"""".format(e._1.idString, e._2.idString) }.mkString("\n") val dot = "%s\n%s\n%s\n}".format(dotHead, nodes, edges) diff --git a/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala b/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala index 48bf1ce6b..436a90c2e 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/rendering/GraphML.scala @@ -23,27 +23,23 @@ import scala.xml.XML object GraphML { def saveAsGraphML(graph: ModuleGraph, outputFile: String) { val nodesXml = - for (n <- graph.nodes) - yield - - - {n.id.idString} - - + for (n ← graph.nodes) + yield + + { n.id.idString } + + val edgesXml = - for (e <- graph.edges) - yield + for (e ← graph.edges) + yield val xml = - + - {nodesXml} - {edgesXml} + { nodesXml } + { edgesXml } diff --git a/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala b/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala index c7f8e6395..1e6ce563a 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayout.scala @@ -6,50 +6,50 @@ package net.virtualvoid.sbt.graph.util object AsciiTreeLayout { - // [info] foo - // [info] +-bar - // [info] | +-baz - // [info] | - // [info] +-quux - def toAscii[A](top: A, - children: A => Seq[A], - display: A => String, + // [info] foo + // [info] +-bar + // [info] | +-baz + // [info] | + // [info] +-quux + def toAscii[A](top: A, + children: A ⇒ Seq[A], + display: A ⇒ String, maxColumn: Int = defaultColumnSize): String = { - val twoSpaces = " " + " " // prevent accidentally being converted into a tab - def limitLine(s: String): String = - if (s.length > maxColumn) s.slice(0, maxColumn - 2) + ".." - else s - def insertBar(s: String, at: Int): String = + val twoSpaces = " " + " " // prevent accidentally being converted into a tab + def limitLine(s: String): String = + if (s.length > maxColumn) s.slice(0, maxColumn - 2) + ".." + else s + def insertBar(s: String, at: Int): String = if (at < s.length) s.slice(0, at) + - (s(at).toString match { - case " " => "|" - case x => x - }) + - s.slice(at + 1, s.length) + (s(at).toString match { + case " " ⇒ "|" + case x ⇒ x + }) + + s.slice(at + 1, s.length) else s - def toAsciiLines(node: A, level: Int, parents: Set[A]): Vector[String] = - if (parents contains node) // cycle - Vector(limitLine((twoSpaces * level) + "#-" + display(node))) - else { - val line = limitLine((twoSpaces * level) + (if (level == 0) "" else "+-") + display(node)) - val cs = Vector(children(node): _*) - val childLines = cs map { - toAsciiLines(_, level + 1, parents + node) - } - val withBar = childLines.zipWithIndex flatMap { - case (lines, pos) if pos < (cs.size - 1) => lines map { - insertBar(_, 2 * (level + 1)) - } - case (lines, pos) => - if (lines.last.trim != "") lines ++ Vector(twoSpaces * (level + 1)) - else lines - } - line +: withBar - } + def toAsciiLines(node: A, level: Int, parents: Set[A]): Vector[String] = + if (parents contains node) // cycle + Vector(limitLine((twoSpaces * level) + "#-" + display(node))) + else { + val line = limitLine((twoSpaces * level) + (if (level == 0) "" else "+-") + display(node)) + val cs = Vector(children(node): _*) + val childLines = cs map { + toAsciiLines(_, level + 1, parents + node) + } + val withBar = childLines.zipWithIndex flatMap { + case (lines, pos) if pos < (cs.size - 1) ⇒ lines map { + insertBar(_, 2 * (level + 1)) + } + case (lines, pos) ⇒ + if (lines.last.trim != "") lines ++ Vector(twoSpaces * (level + 1)) + else lines + } + line +: withBar + } - toAsciiLines(top, 0, Set.empty).mkString("\n") - } + toAsciiLines(top, 0, Set.empty).mkString("\n") + } def defaultColumnSize: Int = { val termWidth = sbt.SbtAccess.getTerminalWidth diff --git a/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala b/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala index cd110c7e4..94fd5c825 100644 --- a/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala +++ b/src/test/scala/net/virtualvoid/sbt/graph/util/AsciiTreeLayoutSpecs.scala @@ -8,12 +8,12 @@ class AsciiTreeLayoutSpecs extends Specification { case class Leaf(i: Int) extends Tree def children(t: Tree): Seq[Tree] = t match { - case Branch(left, right) => Seq(left, right) - case _: Leaf => Nil + case Branch(left, right) ⇒ Seq(left, right) + case _: Leaf ⇒ Nil } def display(t: Tree): String = t match { - case Branch(left, right) => "Branch" - case Leaf(value) => value.toString * value + case Branch(left, right) ⇒ "Branch" + case Leaf(value) ⇒ value.toString * value } "Graph" should { @@ -66,29 +66,29 @@ class AsciiTreeLayoutSpecs extends Specification { } "cut off cycles" in { AsciiTreeLayout.toAscii[Int](1, Map( - 1 -> Seq(2,3,4), - 2 -> Seq(4,5), + 1 -> Seq(2, 3, 4), + 2 -> Seq(4, 5), 3 -> Seq(), 4 -> Seq(3), - 5 -> Seq(1,4,6,7), + 5 -> Seq(1, 4, 6, 7), 6 -> Seq(), 7 -> Seq()), _.toString).trim === - """1 - | +-2 - | | +-4 - | | | +-3 - | | |\u0020 - | | +-5 - | | #-1 - | | +-4 - | | | +-3 - | | |\u0020 - | | +-6 - | | +-7 - | |\u0020\u0020\u0020 - | +-3 - | +-4 - | +-3""".stripMargin.trim + """1 + | +-2 + | | +-4 + | | | +-3 + | | |\u0020 + | | +-5 + | | #-1 + | | +-4 + | | | +-3 + | | |\u0020 + | | +-6 + | | +-7 + | |\u0020\u0020\u0020 + | +-3 + | +-4 + | +-3""".stripMargin.trim } } }