private static void AppendGroupNode(DotStringBuilder result, string rank, string cluster) { result.StartGroup() .AppendConfig("rank", rank) .AppendNode(cluster, "", "style", "invis", "shape", "none", "fixedsize", "true", "width", "0", "height", "0") .EndGroup(); }
private void AddDependenciesBetweenGroups(DotStringBuilder result) { var usedGroups = new HashSet<string>(graph.Vertices.Where(v => v.GroupElement != null) .Select(g => g.GroupElement.Name)); if (usedGroups.Count < 2) return; var usedDeps = architecture.Edges.Where(e => usedGroups.Contains(e.Source) && usedGroups.Contains(e.Target)) .ToList(); if (!usedDeps.Any()) return; IDictionary<string, int> components; int numConnectedComponents = architecture.StronglyConnectedComponents(out components); if (numConnectedComponents < 2) return; //var circularDeps = components.Select(c => new { Group = c.Key, Index = c.Value }) // .Where(e => usedGroups.Contains(e.Group)) // .GroupBy(c => c.Index) // .Where(g => g.Count() > 1); //foreach (var circ in circularDeps) //{ // var nodes = circ.ToList(); // nodes.Add(nodes.First()); // result.Append(prefix) // .Append("{ ") // .Append(string.Join(" -> ", nodes.Select(e => groupInfos[e.Group].TopNode))) // .Append(" [weight=1000];") // .Append("}\n"); // result.Append(prefix) // .Append("{ ") // .Append(string.Join(" -> ", nodes.Select(e => groupInfos[e.Group].BottomNode))) // .Append(" [weight=1000];") // .Append("}\n"); //} foreach (var dep in usedDeps) { if (components[dep.Source] == components[dep.Target]) continue; result.AppendEdge(groupInfos[dep.Source].BottomNode, groupInfos[dep.Target].TopNode, "style", "invis", "weight", "1000"); } }
public void Output(ArchitectureGraph architecture, List<OutputEntry> warnings) { architecture.Vertices.ForEach((proj, i) => ids.Add(proj, i + 1)); var result = new DotStringBuilder("Architecture"); architecture.Vertices.ForEach(v => result.AppendNode(v, v, "shape", "box")); result.AppendSpace(); var deps = new HashSet<GroupDependency>(architecture.Edges); var inversible = new HashSet<GroupDependency>(deps.Where(d => deps.Contains(new GroupDependency(d.Target, d.Source)))); architecture.Edges.ForEach(d => result.AppendEdge(d.Source, d.Target, "style", GetStyle(d), "color", GetColor(d, inversible))); File.WriteAllText(file, result.ToString()); }
//private DependencyGraph Sample(DependencyGraph aGraph, List<OutputEntry> aWarnings, int percent) //{ // var rand = new Random(); // var selected = new HashSet<Library>(aWarnings.SelectMany(w => w.Projects) // .Concat(aGraph.Vertices.Where(v => rand.Next(100) < percent))); // var result = new DependencyGraph(); // result.AddVertexRange(selected); // result.AddEdgeRange(aGraph.Edges.Where(e => selected.Contains(e.Source) && selected.Contains(e.Target))); // return result; //} private string GenerateDot() { var result = new DotStringBuilder("Dependencies"); result.AppendConfig("concentrate", "true"); int clusterIndex = 1; foreach (var group in graph.Vertices.Where(a => a.GroupElement != null) .GroupBy(a => a.GroupElement.Name)) { var groupName = @group.Key; var clusterName = "cluster" + clusterIndex++; var groupInfo = new GroupInfo(clusterName + "_top", clusterName + "_bottom"); groupInfos.Add(groupName, groupInfo); result.StartSubgraph(clusterName); result.AppendConfig("label", groupName); result.AppendConfig("color", "lightgray"); result.AppendConfig("style", "filled"); result.AppendConfig("fontsize", "20"); result.AppendSpace(); AppendGroupNode(result, "min", groupInfo.TopNode); result.AppendSpace(); var projs = new HashSet<Library>(group); projs.ForEach(a => AppendProject(result, a)); result.AppendSpace(); graph.Edges.Where(e => projs.Contains(e.Source) && projs.Contains(e.Target)) .ForEach(d => AppendDependency(result, d)); result.AppendSpace(); AppendGroupNode(result, "max", groupInfo.BottomNode); result.EndSubgraph(); result.AppendSpace(); } graph.Vertices.Where(a => a.GroupElement == null) .ForEach(a => AppendProject(result, a)); result.AppendSpace(); graph.Edges.Where(e => AreFromDifferentGroups(e.Source, e.Target)) .ForEach(d => AppendDependency(result, d)); result.AppendSpace(); AddDependenciesBetweenGroups(result); return result.ToString(); }
private void AppendProject(DotStringBuilder result, Library library) { result.AppendNode(library, library.Name, "shape", library is Project ? "box" : "ellipse", "color", GetColor(warnings.Where(w => w.Projects.Contains(library)))); }
private void AppendDependency(DotStringBuilder result, Dependency dep) { var invert = wrongDependencies.Contains(dep); result.AppendEdge(invert ? dep.Target : dep.Source, invert ? dep.Source : dep.Target, // "style", dep.Type == Dependency.Types.LibraryReference ? "dashed" : null, // "color", GetColor(warnings.Where(w => w.Dependencies.Contains(dep))), // "dir", invert ? "back" : null); }