quantum-space-buddies/QNetWeaver/Helpers.cs
2021-06-18 22:40:38 +01:00

237 lines
6.7 KiB
C#

using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Mdb;
using Mono.Cecil.Pdb;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace QNetWeaver
{
internal class Helpers
{
public static string UnityEngineDLLDirectoryName()
{
var directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
return (directoryName == null) ? null : directoryName.Replace("file:\\", "");
}
public static ISymbolReaderProvider GetSymbolReaderProvider(string inputFile)
{
var text = inputFile.Substring(0, inputFile.Length - 4);
ISymbolReaderProvider result;
if (File.Exists(text + ".pdb"))
{
Console.WriteLine("Symbols will be read from " + text + ".pdb");
result = new PdbReaderProvider();
}
else if (File.Exists(text + ".dll.mdb"))
{
Console.WriteLine("Symbols will be read from " + text + ".dll.mdb");
result = new MdbReaderProvider();
}
else
{
Console.WriteLine("No symbols for " + inputFile);
result = null;
}
return result;
}
public static bool InheritsFromSyncList(TypeReference typeRef)
{
try
{
if (typeRef.IsValueType)
{
return false;
}
foreach (var typeReference in ResolveInheritanceHierarchy(typeRef))
{
if (typeReference.IsGenericInstance)
{
var typeDefinition = typeReference.Resolve();
if (typeDefinition.HasGenericParameters && typeDefinition.FullName == Weaver.SyncListType.FullName)
{
return true;
}
}
}
}
catch
{
}
return false;
}
public static IEnumerable<TypeReference> ResolveInheritanceHierarchy(TypeReference type)
{
if (type.IsValueType)
{
yield return type;
yield return Weaver.valueTypeType;
yield return Weaver.objectType;
yield break;
}
while (type != null && type.FullName != Weaver.objectType.FullName)
{
yield return type;
try
{
var typeDefinition = type.Resolve();
if (typeDefinition == null)
{
break;
}
type = typeDefinition.BaseType;
}
catch
{
break;
}
}
yield return Weaver.objectType;
yield break;
}
public static string DestinationFileFor(string outputDir, string assemblyPath)
{
var fileName = Path.GetFileName(assemblyPath);
return Path.Combine(outputDir, fileName);
}
public static string PrettyPrintType(TypeReference type)
{
string result;
if (type.IsGenericInstance)
{
var genericInstanceType = (GenericInstanceType)type;
var text = genericInstanceType.Name.Substring(0, genericInstanceType.Name.Length - 2);
var text2 = "<";
var text3 = ", ";
IEnumerable<TypeReference> genericArguments = genericInstanceType.GenericArguments;
result = text + text2 + string.Join(text3, Enumerable.ToArray<string>(Enumerable.Select<TypeReference, string>(genericArguments, new Func<TypeReference, string>(PrettyPrintType)))) + ">";
}
else if (type.HasGenericParameters)
{
result = type.Name.Substring(0, type.Name.Length - 2) + "<" + string.Join(", ", Enumerable.ToArray<string>(Enumerable.Select<GenericParameter, string>(type.GenericParameters, (GenericParameter x) => x.Name))) + ">";
}
else
{
result = type.Name;
}
return result;
}
public static ReaderParameters ReaderParameters(string assemblyPath, IEnumerable<string> extraPaths, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath)
{
var readerParameters = new ReaderParameters();
if (assemblyResolver == null)
{
assemblyResolver = new DefaultAssemblyResolver();
}
var addSearchDirectoryHelper = new Helpers.AddSearchDirectoryHelper(assemblyResolver);
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
addSearchDirectoryHelper.AddSearchDirectory(UnityEngineDLLDirectoryName());
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityUNetDLLPath));
if (extraPaths != null)
{
foreach (var directory in extraPaths)
{
addSearchDirectoryHelper.AddSearchDirectory(directory);
}
}
readerParameters.AssemblyResolver = assemblyResolver;
readerParameters.SymbolReaderProvider = GetSymbolReaderProvider(assemblyPath);
return readerParameters;
}
public static WriterParameters GetWriterParameters(ReaderParameters readParams)
{
var writerParameters = new WriterParameters();
if (readParams.SymbolReaderProvider is PdbReaderProvider)
{
writerParameters.SymbolWriterProvider = new PdbWriterProvider();
}
else if (readParams.SymbolReaderProvider is MdbReaderProvider)
{
writerParameters.SymbolWriterProvider = new MdbWriterProvider();
}
return writerParameters;
}
public static TypeReference MakeGenericType(TypeReference self, params TypeReference[] arguments)
{
if (self.GenericParameters.Count != arguments.Length)
{
throw new ArgumentException();
}
var genericInstanceType = new GenericInstanceType(self);
foreach (var item in arguments)
{
genericInstanceType.GenericArguments.Add(item);
}
return genericInstanceType;
}
public static MethodReference MakeHostInstanceGeneric(MethodReference self, params TypeReference[] arguments)
{
var methodReference = new MethodReference(self.Name, self.ReturnType, MakeGenericType(self.DeclaringType, arguments))
{
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis,
CallingConvention = self.CallingConvention
};
foreach (var parameterDefinition in self.Parameters)
{
methodReference.Parameters.Add(new ParameterDefinition(parameterDefinition.ParameterType));
}
foreach (var genericParameter in self.GenericParameters)
{
methodReference.GenericParameters.Add(new GenericParameter(genericParameter.Name, methodReference));
}
return methodReference;
}
private class AddSearchDirectoryHelper
{
public AddSearchDirectoryHelper(IAssemblyResolver assemblyResolver)
{
var method = assemblyResolver.GetType().GetMethod("AddSearchDirectory", (BindingFlags)20, null, new Type[]
{
typeof(string)
}, null);
if (method == null)
{
throw new Exception("Assembly resolver doesn't implement AddSearchDirectory method.");
}
_addSearchDirectory = (Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate)Delegate.CreateDelegate(typeof(Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate), assemblyResolver, method);
}
public void AddSearchDirectory(string directory) => _addSearchDirectory(directory);
private readonly Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate _addSearchDirectory;
private delegate void AddSearchDirectoryDelegate(string directory);
}
}
}