-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathDgmlExport.cs
More file actions
98 lines (84 loc) · 3.08 KB
/
Copy pathDgmlExport.cs
File metadata and controls
98 lines (84 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using CSharpCodeAnalyst.CodeGraph.Colors;
using CSharpCodeAnalyst.CodeGraph.Graph;
namespace CSharpCodeAnalyst.CodeGraph.Export;
public static class DgmlExport
{
/// <summary>
/// Exports the given nodes and edges to a dgml file.
/// Note that the "Contains" relationship is treated as hierarchy information
/// to build sub-graphs in the output file.
/// </summary>
public static void Export(string fileName, Graph.CodeGraph graph)
{
var builder = new DgmlFileBuilder();
WriteCategories(builder);
// Nodes and groups.
var containsRelationships = new List<(string sourceId, string targetId)>();
HashSet<string> containers = [];
foreach (var node in graph.Nodes.Values)
{
if (node.Children.Any())
{
builder.AddGroup(node.Id, node.Name, node.ElementType.ToString());
containers.Add(node.Id);
}
else
{
builder.AddNodeById(node.Id, node.Name, node.ElementType.ToString());
}
containsRelationships.AddRange(node.Children.Select(c => (node.Id, c.Id)));
}
// Regular relationships
var normal = new List<Relationship>();
graph.ForEachNode(e => normal.AddRange(e.Relationships));
foreach (var edge in normal)
{
// Omit the calls label for better readability.
var edgeLabel = GetEdgeLabel(edge);
builder.AddEdgeById(edge.SourceId, edge.TargetId, edgeLabel);
}
// Containment relationships
foreach (var edge in containsRelationships)
{
if (containers.Contains(edge.targetId))
{
builder.AddGroupToGroup(edge.sourceId, edge.targetId);
}
else
{
builder.AddNodeToGroup(edge.sourceId, edge.targetId);
}
}
builder.WriteOutput(fileName);
}
private static string GetEdgeLabel(Relationship relationship)
{
// Omit the label text for now. The color makes it clear that it is a call relationship
if (relationship.Type == RelationshipType.Calls || relationship.Type == RelationshipType.Invokes)
{
return string.Empty;
}
// We can see this by the dotted line
if (relationship.Type == RelationshipType.Implements || relationship.Type == RelationshipType.Inherits)
{
return string.Empty;
}
if (relationship.Type == RelationshipType.Uses)
{
return string.Empty;
}
if (relationship.Type == RelationshipType.UsesAttribute)
{
return string.Empty;
}
return relationship.Type.ToString();
}
private static void WriteCategories(DgmlFileBuilder writer)
{
var elementTypes = Enum.GetValues(typeof(CodeElementType)).Cast<CodeElementType>();
foreach (var type in elementTypes)
{
writer.AddCategory(type.ToString(), "Background", $"#{ColorDefinitions.GetRbgOf(type):X}");
}
}
}