Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Commit

Permalink
Display the portability of the references for each assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexGhiondea committed Aug 1, 2018
1 parent d82d338 commit 72a18d5
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 48 deletions.
18 changes: 7 additions & 11 deletions src/lib/Microsoft.Fx.Portability.Reports.DGML/DGMLManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
Expand Down Expand Up @@ -52,7 +55,6 @@ class DGMLManager
</DirectedGraph>";
#endregion


XDocument file;
public DGMLManager()
{
Expand All @@ -73,11 +75,6 @@ public bool TryGetId(string value, out Guid frameworkGuid)
return _nodesDictionary.TryGetValue(value, out frameworkGuid);
}

internal void AddId(string value, Guid nodeGuid)
{
_nodesDictionary.Add(value, nodeGuid);
}

internal void AddLink(Guid source, Guid target, string category = null)
{
var element = new XElement(_nameSpace + "Link",
Expand Down Expand Up @@ -120,16 +117,15 @@ internal void Save(Stream stream)
};
}

internal bool GetOrCreateGuid(string nodeLabel, out Guid guid)
internal Guid GetOrCreateGuid(string nodeLabel)
{
if (!_nodesDictionary.TryGetValue(nodeLabel, out guid))
if (!_nodesDictionary.TryGetValue(nodeLabel, out Guid guid))
{
guid = Guid.NewGuid();
_nodesDictionary.Add(nodeLabel, guid);
return false;
}

return true;
return guid;
}
}
}
22 changes: 12 additions & 10 deletions src/lib/Microsoft.Fx.Portability.Reports.DGML/DGMLOutputWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,25 @@ public void WriteStream(Stream stream, AnalyzeResponse response, AnalyzeRequest
{
for (int i = 0; i < targets.Count; i++)
{
double portabilityIndex = 0;
double portabilityIndex = 0, portabilityIndexRefs = 0;
string missingTypes = null;
if (node.UsageData != null)
{
TargetUsageInfo usageInfo = node.UsageData[i];
portabilityIndex = Math.Round(usageInfo.PortabilityIndex * 100.0, 2);
portabilityIndex = node.GetPortabilityIndex(i);
portabilityIndexRefs = node.GetPortabilityIndexForReferences(i);

missingTypes = GenerateMissingTypes(node.Assembly, analysisResult, i);
}

// generate the node
string tfm = targets[i].FullName;
dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}", out Guid nodeGuid);
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, $"{node.SimpleName}, {portabilityIndex}%",
node.IsMissing ? "Unresolved" : GetCategory(portabilityIndex),
dgml.AddNode(nodeGuid, nodeTitle,
nodeCategory,
portabilityIndex,
group: missingTypes.Length == 0 ? null : "Collapsed");

Expand All @@ -80,12 +83,11 @@ public void WriteStream(Stream stream, AnalyzeResponse response, AnalyzeRequest
{
// generate the node
string tfm = targets[i].FullName;
dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}", out Guid nodeGuid);
Guid nodeGuid = dgml.GetOrCreateGuid($"{node.Assembly},TFM:{tfm}");

foreach (var refNode in node.Nodes)
{
dgml.GetOrCreateGuid($"{refNode.Assembly},TFM:{tfm}", out Guid refNodeGuid);

Guid refNodeGuid = dgml.GetOrCreateGuid($"{refNode.Assembly},TFM:{tfm}");
dgml.AddLink(nodeGuid, refNodeGuid);
}
}
Expand All @@ -111,8 +113,8 @@ private void GenerateTargetContainers(IList<FrameworkName> targets)
for (int i = 0; i < targets.Count; i++)
{
string targetFramework = targets[i].FullName;
Guid nodeGuid = Guid.NewGuid();
dgml.AddId(targetFramework, nodeGuid);
Guid nodeGuid = dgml.GetOrCreateGuid(targetFramework);// Guid.NewGuid();
//dgml.AddId(targetFramework, nodeGuid);
dgml.AddNode(nodeGuid, targetFramework, "Target", null, group: "Expanded");
}
}
Expand Down
25 changes: 3 additions & 22 deletions src/lib/Microsoft.Fx.Portability.Reports.DGML/ReferenceGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ namespace Microsoft.Fx.Portability.Reports.DGML
{
class ReferenceGraph
{
public Dictionary<ReferenceNode, ReferenceNode> Nodes { get; set; }

public static ReferenceGraph CreateGraph(AnalyzeResponse response, AnalyzeRequest request)
{
ReferenceGraph rg = new ReferenceGraph();
ReferenceGraph rg = new ReferenceGraph();

// 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);
Expand Down Expand Up @@ -50,30 +52,9 @@ public static ReferenceGraph CreateGraph(AnalyzeResponse response, AnalyzeReques
}
}

if (rg.HasCycles())
{
// do nothing as we don't support this scenario.
return rg;
}

rg.ComputeNewPortabilityIndex();

return rg;
}

private void ComputeNewPortabilityIndex()
{
// TODO: update the index for the assemblies based on their references.
}

private bool HasCycles()
{
//TODO: implement
return false;
}

public Dictionary<ReferenceNode, ReferenceNode> Nodes { get; set; }

public ReferenceGraph()
{
Nodes = new Dictionary<ReferenceNode, ReferenceNode>(new ReferenceNodeComparer());
Expand Down
81 changes: 76 additions & 5 deletions src/lib/Microsoft.Fx.Portability.Reports.DGML/ReferenceNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Fx.Portability.Reporting.ObjectModel;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Microsoft.Fx.Portability.Reports.DGML
{
class ReferenceNode
{
private bool _searchInGraph = false;

public List<TargetUsageInfo> UsageData { get; set; }

public string Assembly { get; set; }

public bool Unresolved { get; set; }

public HashSet<ReferenceNode> Nodes { get; set; }
public bool IsMissing { get; internal set; }

public string SimpleName
{
get
Expand All @@ -19,12 +31,14 @@ public string SimpleName
return "Unresolved: " + new AssemblyName(Assembly).Name;
}
}

public ReferenceNode(string AssemblyName, bool unresolved = false)
{
Assembly = AssemblyName;
this.Unresolved = unresolved;
Nodes = new HashSet<ReferenceNode>();
}

public override int GetHashCode()
{
return Assembly.GetHashCode();
Expand All @@ -40,13 +54,70 @@ public override string ToString()
return Assembly;
}

public List<TargetUsageInfo> UsageData { get; set; }
public double GetPortabilityIndex(int target)
{
return UsageData[target].PortabilityIndex;
}

public string Assembly { get; set; }
public double GetPortabilityIndexForReferences(int target)
{
// if we don't have any outgoing references, it is a good sign!
if (Nodes.Count == 0)
return 1;

public bool Unresolved { get; set; }
// sum up the number of calls to available APIs and the ones for not available APIs for references.
if (!TryGetAPICountFromReferences(target, out int availableApis, out int unavailableApis))
{
//cycle detected
return 1;
}
else
{
// remove the calls from the current node.
availableApis -= UsageData[target].GetAvailableAPICalls();
unavailableApis -= UsageData[target].GetUnavailableAPICalls();

public HashSet<ReferenceNode> Nodes { get; set; }
public bool IsMissing { get; internal set; }
// prevent Div/0
if (availableApis == 0 && unavailableApis == 0)
return 0;

return availableApis / ((double)availableApis + unavailableApis);
}
}

public bool TryGetAPICountFromReferences(int target, out int availAPIs, out int unavailAPIs)
{
availAPIs = UsageData[target].GetAvailableAPICalls();
unavailAPIs = UsageData[target].GetUnavailableAPICalls();

// We are going to use a flag on the object to detect if we have a reference cycle while computing the APIs for the references.
if (_searchInGraph == true)
{
//cycle!!!
_searchInGraph = false; //reset this flag
return false;
}
else
{
_searchInGraph = true;
}

foreach (var item in Nodes)
{
if (!item.TryGetAPICountFromReferences(target, out int refCountAvail, out int refCountUnavail))
{
//cycle!
_searchInGraph = false; //reset this flag

return false;
}

availAPIs += refCountAvail;
unavailAPIs += refCountUnavail;
}

_searchInGraph = false;
return true;
}
}
}

0 comments on commit 72a18d5

Please sign in to comment.