using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace HybridCLR.Editor.Meta
|
{
|
|
public class AssemblySorter
|
{
|
class Node
|
{
|
public string Name;
|
public List<Node> Dependencies = new List<Node>();
|
|
public Node(string name)
|
{
|
Name = name;
|
}
|
}
|
|
class TopologicalSorter
|
{
|
|
public static List<Node> Sort(List<Node> nodes)
|
{
|
List<Node> sorted = new List<Node>();
|
HashSet<Node> visited = new HashSet<Node>();
|
HashSet<Node> tempMarks = new HashSet<Node>();
|
|
foreach (var node in nodes)
|
{
|
if (!visited.Contains(node))
|
{
|
Visit(node, visited, tempMarks, sorted);
|
}
|
}
|
return sorted;
|
}
|
|
private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted)
|
{
|
if (tempMarks.Contains(node))
|
{
|
throw new Exception("Detected cyclic dependency!");
|
}
|
|
if (!visited.Contains(node))
|
{
|
tempMarks.Add(node);
|
foreach (var dependency in node.Dependencies)
|
{
|
Visit(dependency, visited, tempMarks, sorted);
|
}
|
tempMarks.Remove(node);
|
visited.Add(node);
|
sorted.Add(node);
|
}
|
}
|
}
|
|
private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs)
|
{
|
var nodes = new List<Node>();
|
var nodeMap = new Dictionary<string, Node>();
|
foreach (var assembly in assemblies)
|
{
|
var node = new Node(assembly);
|
nodes.Add(node);
|
nodeMap.Add(assembly, node);
|
}
|
foreach (var assembly in assemblies)
|
{
|
var node = nodeMap[assembly];
|
foreach (var refAssembly in refs[assembly])
|
{
|
node.Dependencies.Add(nodeMap[refAssembly]);
|
}
|
}
|
var sortedNodes = TopologicalSorter.Sort(nodes);
|
return sortedNodes.Select(node => node.Name).ToList();
|
}
|
|
public static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, IAssemblyResolver assemblyResolver)
|
{
|
var assCache = new AssemblyCache(assemblyResolver);
|
var assRefAssemblies = new Dictionary<string, HashSet<string>>();
|
foreach (var assName in assemblies)
|
{
|
var refAssemblies = new HashSet<string>();
|
var mod = assCache.LoadModule(assName, false);
|
foreach (var refAss in mod.GetAssemblyRefs())
|
{
|
if (assemblies.Contains(refAss.Name.ToString()))
|
{
|
refAssemblies.Add(refAss.Name.ToString());
|
}
|
}
|
assRefAssemblies.Add(assName, refAssemblies);
|
}
|
return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies);
|
}
|
}
|
}
|