diff --git a/README.md b/README.md index feb6cc2..73bd043 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ There are 2 versions of the extractor project. Both projects have the same purpo You can get the .Net Core compilation tools through 2 channels; Download the (CLI) binaries by downloading directly from [the site](https://www.microsoft.com/net/core). -When using the dotnet CLI to build the project, make sure to **restore dependant packages first!**. +When using the dotnet CLI to build the project, make sure to **restore dependent packages first!**. WARN; The build artifact is a .dll file that cannot be executed by itself. To run the program it's required to start the dotnet runtime first; `dotnet extractor.dll [ARGUMENTS]`. @@ -28,7 +28,7 @@ WARN; The build artifact is a .dll file that cannot be executed by itself. To ru Update your Visual Studio **2019** installation to include the `.Net Core cross-platform development`, which can be found under section `Other toolsets`. -Using Visual Studio 2019 is recommended because it handles dependancies and builds the project correctly for YOU. +Using Visual Studio 2019 is recommended because it handles dependencies and builds the project correctly for YOU. There is a community version which is [free to install and use](https://www.visualstudio.com/). @@ -36,7 +36,7 @@ There is a community version which is [free to install and use](https://www.visu > Compile and run the `Mono-Extractor` project! -You can download the Mono tools from [their site](http://www.mono-project.com/download/). Their `msbuild` executable should automatically restore dependant packages. +You can download the Mono tools from [their site](http://www.mono-project.com/download/). Their `msbuild` executable should automatically restore dependent packages. The resulting binary is called 'mono-extractor.exe'. # Usage @@ -47,7 +47,7 @@ Give it the library files you want to decompile and if you want proto2 or proto3 The program can do the following actions automatically: * move types between namespaces according to manual config; -* resolve circular dependancies; +* resolve circular dependencies; * resolve name collisions; * package types underneath a common namespace; * generates proto2/proto3 syntax output. @@ -65,7 +65,7 @@ Extended usage example: > This command is used to generate protobuffer files for [HS proto repository](https://github.com/HearthSim/hsproto) ```bash -extractor --proto3 --debug --resolve-circular-dependancies --automatic-packaging --resolve-name-collisions --outPath "./proto-out" --libPath "%HS_LOCATION%/Hearthstone_Data/Managed" "%HS_LOCATION%/Hearthstone_Data/Managed/Assembly-CSharp.dll" +extractor --proto3 --debug --resolve-circular-dependencies --automatic-packaging --resolve-name-collisions --outPath "./proto-out" --libPath "%HS_LOCATION%/Hearthstone_Data/Managed" "%HS_LOCATION%/Hearthstone_Data/Managed/Assembly-CSharp.dll" "%HS_LOCATION%/Hearthstone_Data/Managed/Assembly-CSharp-firstpass.dll" ``` @@ -81,9 +81,9 @@ WARN; Proto3 syntax is more readable but less accurate. Use Proto2 syntax for em > Defaults to False. -### Resolve circular dependancies +### Resolve circular dependencies -The option `--resolve-circular-dependancies` will run a processor object that detects and solves circular dependancies for you. Both circular dependancies between types and namespaces are detected. +The option `--resolve-circular-dependencies` will run a processor object that detects and solves circular dependencies for you. Both circular dependencies between types and namespaces are detected. > Defaults to False. @@ -103,7 +103,7 @@ The option `--automatic-packaging` will try to group namespaces under the same n The option `--manual-package-file "PATH-TO-INI-FILE"` can be used manually move content of namespaces or specific types to other/new namespaces. See the file `hscode-proto-packaging.ini` in the root of the repo for examples. -It's important to keep the order of processing algorithms in mind! We shouldn't try to manually compensate the behaviour of the automatic dependancy resolver. This has to do with trying to keep a consistent layout of outputted protobuffer files regarding the absolute dependancy on the source material. +It's important to keep the order of processing algorithms in mind! We shouldn't try to manually compensate the behaviour of the automatic dependency resolver. This has to do with trying to keep a consistent layout of outputted protobuffer files regarding the absolute dependency on the source material. > Defaults to "" (empty string) -> nothing will happen. @@ -112,7 +112,7 @@ It's important to keep the order of processing algorithms in mind! We shouldn't The execution order of processing algorithms is always as follows: 1. Manual packaging of namespaces; -2. Resolve circular dependancies; +2. Resolve circular dependencies; 2. Automatic packaging of namespaces; 3. Resolving name collisions. diff --git a/extractor/src/Program.cs b/extractor/src/Program.cs index 8542ea7..1e7e183 100644 --- a/extractor/src/Program.cs +++ b/extractor/src/Program.cs @@ -73,10 +73,10 @@ static int Main(string[] args) program = manualPackager.Process(); } - if (opts.ResolveCircDependancies) + if (opts.ResolveCircDependencies) { - //*----- Searches and resolves circular dependancies -----*// - var depAnalyzer = new DependancyAnalyzer(program); + //*----- Searches and resolves circular dependencies -----*// + var depAnalyzer = new DependencyAnalyzer(program); program = depAnalyzer.Process(); } diff --git a/extractor/src/analyzer/c-sharp/CSAnalyzer.cs b/extractor/src/analyzer/c-sharp/CSAnalyzer.cs index c80f8f8..1eb0b58 100644 --- a/extractor/src/analyzer/c-sharp/CSAnalyzer.cs +++ b/extractor/src/analyzer/c-sharp/CSAnalyzer.cs @@ -12,7 +12,7 @@ class CSAnalyzer : DefaultAnalyzer /* The CSharp analyzer uses Mono.Cecil for type extraction. */ - // Class used for resolving C# dll dependancies. + // Class used for resolving C# dll dependencies. private ReaderParameters _resolverParameters; // List of enum types to be extracted regardless of whether they are referenced @@ -36,9 +36,9 @@ public CSAnalyzer() private void SetupAssemblyResolver() { - // Assemblyresolver locates assembly dependancies for us. + // Assemblyresolver locates assembly dependencies for us. var resolver = new DirAssemblyResolver(); - // The directory of the actual library is added because most dependancies + // The directory of the actual library is added because most dependencies // are located within the same folder. resolver.AddSearchDirectory(_path); // Prepare a parameter for the loadAssembly call later, see Parse(..). diff --git a/extractor/src/processing/DependancyAnalyzer.cs b/extractor/src/processing/DependencyAnalyzer.cs similarity index 88% rename from extractor/src/processing/DependancyAnalyzer.cs rename to extractor/src/processing/DependencyAnalyzer.cs index 321dbc0..96d6935 100644 --- a/extractor/src/processing/DependancyAnalyzer.cs +++ b/extractor/src/processing/DependencyAnalyzer.cs @@ -6,10 +6,10 @@ namespace protoextractor.processing { - class DependancyAnalyzer : DefaultProcessor + class DependencyAnalyzer : DefaultProcessor { /* - This class attempts to resolve circular dependancies in the given program structure. + This class attempts to resolve circular dependencies in the given program structure. */ // It might be needed to extract types into a seperate namespace. @@ -28,13 +28,13 @@ enum NODE_STATE // Maps types to their parent namespace. private Dictionary _TypeNSMapper; - // Dependancies between namespaces. - private Dictionary> _NSDependancies; + // Dependencies between namespaces. + private Dictionary> _NSDependencies; // Direct relations between types. - private Dictionary> _TypeDependancies; + private Dictionary> _TypeDependencies; - // Find circular dependancies, but do not solve them. + // Find circular dependencies, but do not solve them. private bool _DryRun { get; @@ -44,18 +44,18 @@ private bool _DryRun // Keep track of the amount of times we processed the entire program structure. private int Runs; - public DependancyAnalyzer(IRProgram program) : base(program) + public DependencyAnalyzer(IRProgram program) : base(program) { _DryRun = false; Runs = 0; _TypeNSMapper = new Dictionary(); - _NSDependancies = new Dictionary>(); - _TypeDependancies = new Dictionary>(); + _NSDependencies = new Dictionary>(); + _TypeDependencies = new Dictionary>(); } - // Tests for circular dependancies, but does not solve them. - public DependancyAnalyzer DryRun() + // Tests for circular dependencies, but does not solve them. + public DependencyAnalyzer DryRun() { _DryRun = true; @@ -65,25 +65,25 @@ public DependancyAnalyzer DryRun() // Processes the given program (INPLACE) and returns it. public override IRProgram Process() { - Program.Log.OpenBlock("DependancyAnalyzer::Process()"); + Program.Log.OpenBlock("DependencyAnalyzer::Process()"); - // Loop until no more circular dependancies are known. + // Loop until no more circular dependencies are known. while (true) { Runs++; Console.Write('.'); - // Construct dependancy data. - CreateDependancyGraph(); + // Construct dependency data. + CreateDependencyGraph(); try { - // Find and Resolve TYPE circular dependancies. + // Find and Resolve TYPE circular dependencies. CreateTopologicalTypeTree(); } catch (CircularException e) { - var circle = e.CircularDependancies; + var circle = e.CircularDependencies; var circleString = string.Join("\n", circle.Select(x => x.FullName)); Program.Log.Debug("\n" + circleString); @@ -102,12 +102,12 @@ public override IRProgram Process() try { - // Find and Resolve NAMESPACE circular dependancies.. + // Find and Resolve NAMESPACE circular dependencies.. CreateTopologicalNSTree(); } catch (CircularException e) { - var circle = e.CircularDependancies; + var circle = e.CircularDependencies; var circleString = string.Join("\n", circle.Select(x => x.FullName)); Program.Log.Debug("\n" + circleString); @@ -145,19 +145,19 @@ public override IRProgram Process() } Console.WriteLine(); - Program.Log.Info("Resolved all circular dependancies within {0} runs.", Runs); + Program.Log.Info("Resolved all circular dependencies within {0} runs.", Runs); Program.Log.CloseBlock(); return _program; } - // Generate and store dependancies between namespaces AND types. - private void CreateDependancyGraph() + // Generate and store dependencies between namespaces AND types. + private void CreateDependencyGraph() { // Clear all known data. _TypeNSMapper.Clear(); - _NSDependancies.Clear(); - _TypeDependancies.Clear(); + _NSDependencies.Clear(); + _TypeDependencies.Clear(); var orderedNamespaces = _program.Namespaces.OrderBy(ns => ns.FullName); @@ -165,7 +165,7 @@ private void CreateDependancyGraph() { // Set for all namespaces referenced by this namespace. var nsDepSet = new HashSet(); - _NSDependancies[ns] = nsDepSet; + _NSDependencies[ns] = nsDepSet; // For each reference property, find the parent namespace and store that one. foreach (var irClass in ns.Classes) @@ -175,7 +175,7 @@ private void CreateDependancyGraph() // Set for all types referenced by this specific type. var typeDepSet = new HashSet(); - _TypeDependancies[irClass] = typeDepSet; + _TypeDependencies[irClass] = typeDepSet; foreach (var property in irClass.Properties) { @@ -193,7 +193,7 @@ private void CreateDependancyGraph() } var refParentNS = refParent as IRNamespace; - // Store the dependancy between current namespace and the referenced one. + // Store the dependency between current namespace and the referenced one. nsDepSet.Add(refParentNS); // Store the reference between current type and the referenced one. typeDepSet.Add(refType); @@ -206,21 +206,21 @@ private void CreateDependancyGraph() foreach (var irEnum in ns.Enums) { _TypeNSMapper[irEnum] = ns; - _TypeDependancies[irEnum] = new HashSet(); + _TypeDependencies[irEnum] = new HashSet(); } - // Remove our own namespace as dependancy. + // Remove our own namespace as dependency. nsDepSet.Remove(ns); } } #region TYPE_RESOLVE - // Creates a topological tree from the dependancies of the specified type. + // Creates a topological tree from the dependencies of the specified type. private List CreateTopologicalTypeTree() { // List of all visited types. List visited = new List(); - // Topological view of the dependant types. + // Topological view of the dependent types. List topologicalOrder = new List(); // Meta state of each type. @@ -228,10 +228,10 @@ private List CreateTopologicalTypeTree() // Collection of all IR Types. - var allTypes = _TypeDependancies.Keys.ToList(); + var allTypes = _TypeDependencies.Keys.ToList(); // Mark all nodes ALIVE, this means they still need to be processed. - // The main resource of this algorithm is the '_TypeDependancies' variable. + // The main resource of this algorithm is the '_TypeDependencies' variable. foreach (var type in allTypes) { nodeState[type] = NODE_STATE.ALIVE; @@ -280,7 +280,7 @@ private void TypeTopologicalVisit(IRTypeNode node, List topologicalO // Visit this node. visitedNodes.Add(targetNode); - // An undead state means we hit a circular dependancy! + // An undead state means we hit a circular dependency! if (state == NODE_STATE.UNDEAD) { // References from Parent node to child (nested) node are allowed. @@ -301,7 +301,7 @@ private void TypeTopologicalVisit(IRTypeNode node, List topologicalO var circleLength = visitedNodes.Count() - circleEntryIDx; var circle = visitedNodes.GetRange(circleEntryIDx, circleLength); - // If each type belongs to the SAME namespace, there is no circular dependancy! + // If each type belongs to the SAME namespace, there is no circular dependency! if (AllTypesInSameNamespace(circle)) { return; @@ -312,9 +312,9 @@ private void TypeTopologicalVisit(IRTypeNode node, List topologicalO // Node is ALIVE and will be processed. nodeState[targetNode] = NODE_STATE.UNDEAD; - var dependancies = _TypeDependancies[targetNode]; - // Visit all dependancies of this node. - foreach (var dep in dependancies) + var dependencies = _TypeDependencies[targetNode]; + // Visit all dependencies of this node. + foreach (var dep in dependencies) { // Send in a copy of visited nodes so it doesn't litter the list // with non circular types. @@ -328,14 +328,14 @@ private void TypeTopologicalVisit(IRTypeNode node, List topologicalO private void ResolveCircularTypes(List circle) { // All unique types within the given list are moved together into a seperate - // namespace, because that's the only way to solve these kind of circular dependancies. + // namespace, because that's the only way to solve these kind of circular dependencies. // This list will NEVER contain enums! IEnumerable distincttypes = circle.Distinct().Cast(); // TODO: Better naming algorithm?! (Longest commong substring) // The longest substring between the fullnames of each type's namespace. var allTypeNamespaceNames = circle.Select(type => _TypeNSMapper[type].FullName).ToList(); - string newNSName = DependancyUtil.LongestmatchingSubstring(allTypeNamespaceNames).Trim('.'); + string newNSName = DependencyUtil.LongestmatchingSubstring(allTypeNamespaceNames).Trim('.'); // Also construct a shortname from the new namespace fullname string newNSShortName = newNSName.Substring(newNSName.LastIndexOf('.') + 1); @@ -382,7 +382,7 @@ private List CreateTopologicalNSTree() nodeState[ns] = NODE_STATE.ALIVE; } - // Topological walk the dependancy graph. + // Topological walk the dependency graph. foreach (var ns in allNamespaces) { NSTopologicalVisit(ns, topologicalOrder, nodeState, visited); @@ -424,12 +424,12 @@ private void NSTopologicalVisit(IRNamespace node, List topologicalO // Node is ALIVE and will be processed. nodeState[node] = NODE_STATE.UNDEAD; - // Find all dependancies of the current namespace. - var dependancies = _NSDependancies[node]; - // Visit each namespace dependancy. - foreach (var dep in dependancies) + // Find all dependencies of the current namespace. + var dependencies = _NSDependencies[node]; + // Visit each namespace dependency. + foreach (var dep in dependencies) { - // Send a copy of visited nodes to not litter the list of circular dependant nodes + // Send a copy of visited nodes to not litter the list of circular dependent nodes // when we reach an undead node. NSTopologicalVisit(dep, topologicalOrder, nodeState, visitedNodes.ToList()); } @@ -444,10 +444,10 @@ private void ResolveCircularNS(List circle) { if (circle.Count() > 3) { - throw new Exception("This method is not created for solving big circular dependancies!"); + throw new Exception("This method is not created for solving big circular dependencies!"); } - // Suppose there are ONLY DIRECT CIRCULAR DEPENDANCIES. + // Suppose there are ONLY DIRECT CIRCULAR DEPENDENCIES. // This means one namespace points to another which points to the first! var nsOne = circle[0]; var nsTwo = circle[1]; @@ -483,8 +483,8 @@ private List GetAllReferencingClasses(IRNamespace source, IRNamespace r List returnValue = new List(); foreach (var ilClass in source.Classes) // Enums cannot reference other types! { - // Loop each dependancy for the selected type. - var deps = _TypeDependancies[ilClass]; + // Loop each dependency for the selected type. + var deps = _TypeDependencies[ilClass]; foreach (var dep in deps) { // Find and test the parent namespace of the reference. @@ -509,7 +509,7 @@ private int CompareNSHeights(IRNamespace nsOne, IRNamespace nsTwo) List nsNames = new List(); nsNames.Add(nsOne.FullName); nsNames.Add(nsTwo.FullName); - var commonSubstr = DependancyUtil.LongestmatchingSubstring(nsNames); + var commonSubstr = DependencyUtil.LongestmatchingSubstring(nsNames); // Both namespaces share a hypothetical parent namespace. if (commonSubstr.Count() > 0) { @@ -517,10 +517,10 @@ private int CompareNSHeights(IRNamespace nsOne, IRNamespace nsTwo) } // If there is no shared namespace, resort to amount of imports both types do. - var depsNSOne = _NSDependancies[nsOne].Count(); - var depsNSTwo = _NSDependancies[nsTwo].Count(); - // NSTwo has less dependancies, so it's considered closer to the root. - // This is a vague heuristic, ideally the one closer to the root has NO dependancies. + var depsNSOne = _NSDependencies[nsOne].Count(); + var depsNSTwo = _NSDependencies[nsTwo].Count(); + // NSTwo has less dependencies, so it's considered closer to the root. + // This is a vague heuristic, ideally the one closer to the root has NO dependencies. if (depsNSTwo < depsNSOne) { return 1; @@ -597,21 +597,21 @@ private void MoveType(IRTypeNode type, IRNamespace sourceNS, IRNamespace newNS) public class CircularException : Exception { - // List of namespaces that are part of a circular dependancy. + // List of namespaces that are part of a circular dependency. // This list must start AND end with the same element! - public List CircularDependancies + public List CircularDependencies { get; } public CircularException(List circ) { - CircularDependancies = circ; + CircularDependencies = circ; } public CircularException(List circ, Exception inner) : base("", inner) { - CircularDependancies = circ; + CircularDependencies = circ; } public CircularException(string message) diff --git a/extractor/src/processing/DependancyUtil.cs b/extractor/src/processing/DependencyUtil.cs similarity index 97% rename from extractor/src/processing/DependancyUtil.cs rename to extractor/src/processing/DependencyUtil.cs index bcaacd2..936eb0c 100644 --- a/extractor/src/processing/DependancyUtil.cs +++ b/extractor/src/processing/DependencyUtil.cs @@ -3,7 +3,7 @@ namespace protoextractor.processing { - abstract class DependancyUtil + abstract class DependencyUtil { // Returns the longest substring that matches 2 or more types of the given list. // The substrings are taken from the namespaces of each given type! diff --git a/extractor/src/util/Options.cs b/extractor/src/util/Options.cs index ac7638b..a2adfa6 100644 --- a/extractor/src/util/Options.cs +++ b/extractor/src/util/Options.cs @@ -6,9 +6,9 @@ namespace protoextractor.util { class Options { - /* Location for resolving assembly dependancies */ + /* Location for resolving assembly dependencies */ [Option("libPath", Required = true, - HelpText = "The path for resolving input file dependancies.")] + HelpText = "The path for resolving input file dependencies.")] public string LibraryPath { get; @@ -58,9 +58,9 @@ public string LogFile set; } - [Option("resolve-circular-dependancies", Required = false, Default = false, - HelpText = "This switch enables automatic resolving of circular dependancies.")] - public bool ResolveCircDependancies + [Option("resolve-circular-dependencies", Required = false, Default = false, + HelpText = "This switch enables automatic resolving of circular dependencies.")] + public bool ResolveCircDependencies { get; set; @@ -110,7 +110,7 @@ public static IEnumerable Examples ManualPackagingFile = "$(REPO)/hsproto-packaging.ini", OutDirectory = "$(TARGET)/protos", Proto3Syntax = true, - ResolveCircDependancies = true, + ResolveCircDependencies = true, ResolveCollisions = true }); } diff --git a/hsproto-packaging.ini b/hsproto-packaging.ini index 53071df..9609e9b 100644 --- a/hsproto-packaging.ini +++ b/hsproto-packaging.ini @@ -10,7 +10,7 @@ ; spectatorproto = pegasus.spectator ; Move attribute and related types to the protocol namespace. -; This moves solves a circular dependancy, including the name collision introduced +; This moves solves a circular dependency, including the name collision introduced ; after. ; bnet.protocol.attribute = bnet.protocol diff --git a/mono-extractor/mono-extractor.csproj b/mono-extractor/mono-extractor.csproj index 91d60ea..3bb35c7 100644 --- a/mono-extractor/mono-extractor.csproj +++ b/mono-extractor/mono-extractor.csproj @@ -105,11 +105,11 @@ src\processing\DefaultProcessor.cs - - src\processing\DependancyAnalyzer.cs + + src\processing\DependencyAnalyzer.cs - - src\processing\DependancyUtil.cs + + src\processing\DependencyUtil.cs src\processing\LowerCaseNamespaces.cs