diff --git a/Editor/Meta/AssemblySorter.cs b/Editor/Meta/AssemblySorter.cs new file mode 100644 index 0000000..3784b37 --- /dev/null +++ b/Editor/Meta/AssemblySorter.cs @@ -0,0 +1,105 @@ +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 Dependencies = new List(); + + public Node(string name) + { + Name = name; + } + } + + class TopologicalSorter + { + + public static List Sort(List nodes) + { + List sorted = new List(); + HashSet visited = new HashSet(); + HashSet tempMarks = new HashSet(); + + foreach (var node in nodes) + { + if (!visited.Contains(node)) + { + Visit(node, visited, tempMarks, sorted); + } + } + return sorted; + } + + private static void Visit(Node node, HashSet visited, HashSet tempMarks, List 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 SortAssemblyByReferenceOrder(IEnumerable assemblies, Dictionary> refs) + { + var nodes = new List(); + var nodeMap = new Dictionary(); + 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 SortAssemblyByReferenceOrder(IEnumerable assemblies, IAssemblyResolver assemblyResolver) + { + var assCache = new AssemblyCache(assemblyResolver); + var assRefAssemblies = new Dictionary>(); + foreach (var assName in assemblies) + { + var refAssemblies = new HashSet(); + 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); + } + } +} diff --git a/Editor/Meta/AssemblySorter.cs.meta b/Editor/Meta/AssemblySorter.cs.meta new file mode 100644 index 0000000..6fce7f9 --- /dev/null +++ b/Editor/Meta/AssemblySorter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9b8eb45398fa344daa8c6e9b9fbf291 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: