public static ReferenceGraph CreateGraph(AnalyzeResponse response) { ReferenceGraph rg = new ReferenceGraph(); AnalyzeRequest request = response.Request; // get the list of assemblies that have some data reported for them. var assembliesWithData = response.ReportingResult.GetAssemblyUsageInfo().ToDictionary(x => x.SourceAssembly.AssemblyIdentity, x => x.UsageData); var unresolvedAssemblies = response.ReportingResult.GetUnresolvedAssemblies().Select(x => x.Key).ToList(); // Add every user specified assembly to the graph foreach (var userAsem in request.UserAssemblies) { var node = rg.GetOrAddNodeForAssembly(new ReferenceNode(userAsem.AssemblyIdentity)); // For this node, make sure we capture the data, if we have it. if (assembliesWithData.ContainsKey(node.Assembly)) { node.UsageData = assembliesWithData[node.Assembly]; } // create nodes for all the references, if non platform. foreach (var reference in userAsem.AssemblyReferences) { if (!(assembliesWithData.ContainsKey(reference.ToString()) || unresolvedAssemblies.Contains(reference.ToString()))) { // platform reference (not in the user specified asssemblies and not an unresolved assembly. continue; } var refNode = rg.GetOrAddNodeForAssembly(new ReferenceNode(reference.ToString())); // if the reference is missing, flag it as such. refNode.IsMissing = unresolvedAssemblies.Contains(reference.ToString()); node.AddReferenceToNode(refNode); } } return(rg); }
public Task WriteStreamAsync(Stream stream, AnalyzeResponse response) { // Create a new dgml every time write to a new stream. var dgml = new DGMLManager(); var rg = ReferenceGraph.CreateGraph(response); var analysisResult = response.ReportingResult; var targets = analysisResult.Targets; GenerateTargetContainers(dgml, targets); dgml.SetTitle(response.ApplicationName); // For each target, let's generate the assemblies foreach (var node in rg.Nodes.Keys) { for (int i = 0; i < targets.Count; i++) { double portabilityIndex = 0, portabilityIndexRefs = 0; string missingTypes = null; if (node.UsageData != null) { TargetUsageInfo usageInfo = node.UsageData[i]; portabilityIndex = node.GetPortabilityIndex(i); portabilityIndexRefs = node.GetPortabilityIndexForReferences(i); missingTypes = GenerateMissingTypes(node.Assembly, analysisResult, i); } // generate the node string tfm = targets[i].FullName; Guid nodeGuid = dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}"); string nodeTitle = $"{node.SimpleName}: {Math.Round(portabilityIndex * 100, 2)}%, References: {Math.Round(portabilityIndexRefs * 100, 2)}%"; string nodeCategory = node.IsMissing ? "Unresolved" : GetCategory(Math.Round(portabilityIndex * portabilityIndexRefs * 100, 2)); dgml.AddNode(nodeGuid, nodeTitle, nodeCategory, portabilityIndex, group: string.IsNullOrEmpty(missingTypes) ? null : "Collapsed"); if (dgml.TryGetId(tfm, out Guid frameworkGuid)) { dgml.AddLink(frameworkGuid, nodeGuid, "Contains"); } if (!string.IsNullOrEmpty(missingTypes)) { Guid commentGuid = Guid.NewGuid(); dgml.AddNode(commentGuid, missingTypes, "Comment"); dgml.AddLink(nodeGuid, commentGuid, "Contains"); } } } // generate the references. foreach (var node in rg.Nodes.Keys) { for (int i = 0; i < targets.Count; i++) { // generate the node string tfm = targets[i].FullName; Guid nodeGuid = dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}"); foreach (var refNode in node.Nodes) { Guid refNodeGuid = dgml.GetOrCreateGuid($"{refNode.Assembly},TFM:{tfm}"); dgml.AddLink(nodeGuid, refNodeGuid); } } } dgml.Save(stream); return(Task.CompletedTask); }