Moved a couple of folders and wrote some code

This commit is contained in:
Madhav Kapa
2023-06-01 11:21:49 -07:00
parent 0eea70ab4e
commit e8684391ca
1380 changed files with 2766 additions and 13987 deletions

View File

@ -0,0 +1,54 @@
using MonoFN.Cecil;
using System.Linq;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class CustomAttributeExtensions
{
/// <summary>
/// Finds a field within an attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="customAttr"></param>
/// <param name="field"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
internal static T GetField<T>(this CustomAttribute customAttr, string field, T defaultValue)
{
foreach (CustomAttributeNamedArgument customField in customAttr.Fields)
{
if (customField.Name == field)
{
return (T)customField.Argument.Value;
}
}
return defaultValue;
}
/// <summary>
/// Returns if any of the attributes match IAtrribute.
/// </summary>
/// <typeparam name="TAttribute"></typeparam>
/// <param name="attributeProvider"></param>
/// <returns></returns>
internal static bool HasCustomAttribute<TAttribute>(this ICustomAttributeProvider attributeProvider)
{
return attributeProvider.CustomAttributes.Any(attr => attr.AttributeType.Is<TAttribute>());
}
/// <summary>
/// Returns if ca is of type target.
/// </summary>
/// <param name="ca"></param>
/// <param name="targetFullName"></param>
/// <returns></returns>
internal static bool Is(this CustomAttribute ca, string targetFullName)
{
return ca.AttributeType.FullName == targetFullName;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a66d771ab331fae408142a5c04abd74e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Cil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Unity.CompilationPipeline.Common.Diagnostics;
namespace FishNet.CodeGenerating.Helping
{
internal static class Diagnostics
{
internal static void AddError(this List<DiagnosticMessage> diagnostics, string message)
{
diagnostics.AddMessage(DiagnosticType.Error, (SequencePoint)null, message);
}
internal static void AddWarning(this List<DiagnosticMessage> diagnostics, string message)
{
diagnostics.AddMessage(DiagnosticType.Warning, (SequencePoint)null, message);
}
internal static void AddError(this List<DiagnosticMessage> diagnostics, MethodDefinition methodDef, string message)
{
diagnostics.AddMessage(DiagnosticType.Error, methodDef.DebugInformation.SequencePoints.FirstOrDefault(), message);
}
internal static void AddMessage(this List<DiagnosticMessage> diagnostics, DiagnosticType diagnosticType, SequencePoint sequencePoint, string message)
{
diagnostics.Add(new DiagnosticMessage
{
DiagnosticType = diagnosticType,
File = sequencePoint?.Document.Url.Replace($"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}", ""),
Line = sequencePoint?.StartLine ?? 0,
Column = sequencePoint?.StartColumn ?? 0,
MessageData = $" - {message}"
});
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fb7b65b572b01444cbe3c9d830cd3587
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,38 @@
using FishNet.CodeGenerating.Extension;
using MonoFN.Cecil;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class FieldReferenceExtensions
{
/// <summary>
/// Gets a Resolve favoring cached results first.
/// </summary>
internal static FieldDefinition CachedResolve(this FieldReference fieldRef, CodegenSession session)
{
return session.GetClass<GeneralHelper>().GetFieldReferenceResolve(fieldRef);
}
public static FieldReference MakeHostGenericIfNeeded(this FieldDefinition fd, CodegenSession session)
{
TypeReference declaringTr = fd.DeclaringType;
if (declaringTr.HasGenericParameters)
{
GenericInstanceType git = declaringTr.MakeGenericInstanceType();
FieldReference result = new FieldReference(fd.Name, fd.FieldType, git);
return result;
}
else
{
return session.ImportReference(fd);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d983ebd0c9e1b745902030c2f7a8e99
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,191 @@
using FishNet.CodeGenerating.Helping.Extension;
using MonoFN.Cecil;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FishNet.CodeGenerating.Helping
{
internal static class Constructors
{
/// <summary>
/// Gets the first constructor that optionally has, or doesn't have parameters.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static MethodDefinition GetFirstConstructor(this TypeReference typeRef, CodegenSession session, bool requireParameters)
{
return typeRef.CachedResolve(session).GetFirstConstructor(requireParameters);
}
/// <summary>
/// Gets the first constructor that optionally has, or doesn't have parameters.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static MethodDefinition GetFirstConstructor(this TypeDefinition typeDef, bool requireParameters)
{
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor && methodDef.IsPublic)
{
if (requireParameters && methodDef.Parameters.Count > 0)
return methodDef;
else if (!requireParameters && methodDef.Parameters.Count == 0)
return methodDef;
}
}
return null;
}
/// <summary>
/// Gets the first public constructor with no parameters.
/// </summary>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session)
{
return typeRef.CachedResolve(session).GetConstructor();
}
/// <summary>
/// Gets the first public constructor with no parameters.
/// </summary>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeDefinition typeDef)
{
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == 0)
return methodDef;
}
return null;
}
/// <summary>
/// Gets all constructors on typeDef.
/// </summary>
/// <returns></returns>
public static List<MethodDefinition> GetConstructors(this TypeDefinition typeDef)
{
List<MethodDefinition> lst = new List<MethodDefinition>();
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor)
lst.Add(methodDef);
}
return lst;
}
/// <summary>
/// Gets constructor which has arguments.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, Type[] arguments)
{
return typeRef.CachedResolve(session).GetConstructor(arguments);
}
/// <summary>
/// Gets constructor which has arguments.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeDefinition typeDef, Type[] arguments)
{
Type[] argsCopy = (arguments == null) ? new Type[0] : arguments;
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length)
{
bool match = true;
for (int i = 0; i < argsCopy.Length; i++)
{
if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName)
{
match = false;
break;
}
}
if (match)
return methodDef;
}
}
return null;
}
/// <summary>
/// Gets constructor which has arguments.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, TypeReference[] arguments)
{
return typeRef.CachedResolve(session).GetConstructor(arguments);
}
/// <summary>
/// Gets constructor which has arguments.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeDefinition typeDef, TypeReference[] arguments)
{
TypeReference[] argsCopy = (arguments == null) ? new TypeReference[0] : arguments;
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length)
{
bool match = true;
for (int i = 0; i < argsCopy.Length; i++)
{
if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName)
{
match = false;
break;
}
}
if (match)
return methodDef;
}
}
return null;
}
/// <summary>
/// Resolves the constructor with parameterCount for typeRef.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, int parameterCount)
{
return typeRef.CachedResolve(session).GetConstructor(parameterCount);
}
/// <summary>
/// Resolves the constructor with parameterCount for typeRef.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
public static MethodDefinition GetConstructor(this TypeDefinition typeDef, int parameterCount)
{
foreach (MethodDefinition methodDef in typeDef.Methods)
{
if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == parameterCount)
return methodDef;
}
return null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a7e03137ca78704e999f3a3dc68b953
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,169 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Cil;
using System.Collections.Generic;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class ILProcessorExtensions
{
/// <summary>
/// Creates a debug log for text without any conditions.
/// </summary>
public static void DebugLog(this ILProcessor processor, CodegenSession session, string txt)
{
processor.Emit(OpCodes.Ldstr, txt);
processor.Emit(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
}
/// <summary>
/// Creates a debug log for vd without any conditions.
/// </summary>
public static void DebugLog(this ILProcessor processor, CodegenSession session, VariableDefinition vd)
{
processor.Emit(OpCodes.Ldloc, vd);
processor.Emit(OpCodes.Box, vd.VariableType);
processor.Emit(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
}
/// <summary>
/// Creates a debug log for vd without any conditions.
/// </summary>
public static void DebugLog(this ILProcessor processor, CodegenSession session, FieldDefinition fd, bool loadArg0)
{
if (loadArg0)
processor.Emit(OpCodes.Ldarg_0);
processor.Emit(OpCodes.Ldfld, fd);
processor.Emit(OpCodes.Box, fd.FieldType);
processor.Emit(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
}
/// <summary>
/// Creates a debug log for pd without any conditions.
/// </summary>
public static void DebugLog(this ILProcessor processor, CodegenSession session, ParameterDefinition pd)
{
processor.Emit(OpCodes.Ldloc, pd);
processor.Emit(OpCodes.Box, pd.ParameterType);
processor.Emit(OpCodes.Call, session.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
}
///// <summary>
///// Creates a debug log for mr without any conditions.
///// </summary>
//public static void DebugLog(this ILProcessor processor, MethodReference mr)
//{
// processor.Emit(OpCodes.Call, mr);
// processor.Emit(OpCodes.Box, mr.ReturnType);
// processor.Emit(OpCodes.Call, base.GetClass<GeneralHelper>().Debug_LogCommon_MethodRef);
//}
/// <summary>
/// Inserts instructions at the beginning.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void InsertAt(this ILProcessor processor, int target, List<Instruction> instructions)
{
for (int i = 0; i < instructions.Count; i++)
processor.Body.Instructions.Insert(i + target, instructions[i]);
}
/// <summary>
/// Inserts instructions at the beginning.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void InsertFirst(this ILProcessor processor, List<Instruction> instructions)
{
for (int i = 0; i < instructions.Count; i++)
processor.Body.Instructions.Insert(i, instructions[i]);
}
/// <summary>
/// Inserts instructions at the end while also moving Ret down.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void InsertLast(this ILProcessor processor, List<Instruction> instructions)
{
bool retRemoved = false;
int startingCount = processor.Body.Instructions.Count;
//Remove ret if it exist and add it back in later.
if (startingCount > 0)
{
if (processor.Body.Instructions[startingCount - 1].OpCode == OpCodes.Ret)
{
processor.Body.Instructions.RemoveAt(startingCount - 1);
retRemoved = true;
}
}
foreach (Instruction inst in instructions)
processor.Append(inst);
//Add ret back if it was removed.
if (retRemoved)
processor.Emit(OpCodes.Ret);
}
/// <summary>
/// Inserts instructions before target.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void InsertBefore(this ILProcessor processor, Instruction target, List<Instruction> instructions)
{
int index = processor.Body.Instructions.IndexOf(target);
for (int i = 0; i < instructions.Count; i++)
processor.Body.Instructions.Insert(index + i, instructions[i]);
}
/// <summary>
/// Adds instructions to the end of processor.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void Add(this ILProcessor processor, List<Instruction> instructions)
{
for (int i = 0; i < instructions.Count; i++)
processor.Body.Instructions.Add(instructions[i]);
}
/// <summary>
/// Inserts instructions before returns. Only works on void types.
/// </summary>
/// <param name="processor"></param>
/// <param name="instructions"></param>
public static void InsertBeforeReturns(this ILProcessor processor, CodegenSession session, List<Instruction> instructions)
{
if (processor.Body.Method.ReturnType.FullName != session.Module.TypeSystem.Void.FullName)
{
session.LogError($"Cannot insert instructions before returns on {processor.Body.Method.FullName} because it does not return void.");
return;
}
/* Insert at the end of the method
* and get the first instruction that was inserted.
* Any returns or breaks which would exit the method
* will jump to this instruction instead. */
processor.InsertLast(instructions);
Instruction startInst = processor.Body.Instructions[processor.Body.Instructions.Count - instructions.Count];
//Look for anything that jumps to rets.
for (int i = 0; i < processor.Body.Instructions.Count; i++)
{
Instruction inst = processor.Body.Instructions[i];
if (inst.Operand is Instruction operInst)
{
if (operInst.OpCode == OpCodes.Ret)
inst.Operand = startInst;
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 820cf8401d4d71c4196dda444559ef8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Cil;
using System;
using System.Collections.Generic;
namespace FishNet.CodeGenerating.Helping
{
public static class Instructions
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 360667149f16b6c4aba61fd05427cbfb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,55 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Cil;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class MethodDefinitionExtensions
{
/// <summary>
/// Clears the method content and returns ret.
/// </summary>
internal static void ClearMethodWithRet(this MethodDefinition md, CodegenSession session, ModuleDefinition importReturnModule = null)
{
md.Body.Instructions.Clear();
ILProcessor processor = md.Body.GetILProcessor();
processor.Add(session.GetClass<GeneralHelper>().CreateRetDefault(md, importReturnModule));
}
/// <summary>
/// Returns the ParameterDefinition index from end of parameters.
/// </summary>
/// <param name="md"></param>
/// <param name="index"></param>
/// <returns></returns>
internal static ParameterDefinition GetEndParameter(this MethodDefinition md, int index)
{
//Not enough parameters.
if (md.Parameters.Count < (index + 1))
return null;
return md.Parameters[md.Parameters.Count - (index + 1)];
}
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, TypeReference variableTypeRef)
{
VariableDefinition variableDef = new VariableDefinition(variableTypeRef);
methodDef.Body.Variables.Add(variableDef);
return variableDef;
}
/// <summary>
/// Creates a variable type within the body and returns it's VariableDef.
/// </summary>
internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, CodegenSession session, System.Type variableType)
{
return CreateVariable(methodDef, session.GetClass<GeneralHelper>().GetTypeReference(variableType));
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 999d4ae4862274f4ba50569c221976dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,155 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Rocks;
using System;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class MethodReferenceExtensions
{
/// <summary>
/// Makes a generic method with specified arguments.
/// </summary>
/// <param name="method"></param>
/// <param name="genericArguments"></param>
/// <returns></returns>
public static GenericInstanceMethod MakeGenericMethod(this MethodReference method, params TypeReference[] genericArguments)
{
GenericInstanceMethod result = new GenericInstanceMethod(method);
foreach (TypeReference argument in genericArguments)
result.GenericArguments.Add(argument);
return result;
}
/// <summary>
/// Makes a generic method with the same arguments as the original.
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public static GenericInstanceMethod MakeGenericMethod(this MethodReference method)
{
GenericInstanceMethod result = new GenericInstanceMethod(method);
foreach (ParameterDefinition pd in method.Parameters)
result.GenericArguments.Add(pd.ParameterType);
return result;
}
/// <summary>
/// Returns a method reference for a generic method.
/// </summary>
public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference typeReference)
{
return mr.GetMethodReference(session, new TypeReference[] { typeReference });
}
/// <summary>
/// Returns a method reference for a generic method.
/// </summary>
public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference[] typeReferences)
{
if (mr.HasGenericParameters)
{
if (typeReferences == null || typeReferences.Length == 0)
{
session.LogError($"Method {mr.Name} has generic parameters but TypeReferences are null or 0 length.");
return null;
}
else
{
GenericInstanceMethod gim = mr.MakeGenericMethod(typeReferences);
return gim;
}
}
else
{
return mr;
}
}
/// <summary>
/// Gets a Resolve favoring cached results first.
/// </summary>
internal static MethodDefinition CachedResolve(this MethodReference methodRef, CodegenSession session)
{
return session.GetClass<GeneralHelper>().GetMethodReferenceResolve(methodRef);
}
/// <summary>
/// Given a method of a generic class such as ArraySegment`T.get_Count,
/// and a generic instance such as ArraySegment`int
/// Creates a reference to the specialized method ArraySegment`int`.get_Count
/// <para> Note that calling ArraySegment`T.get_Count directly gives an invalid IL error </para>
/// </summary>
/// <param name="self"></param>
/// <param name="instanceType"></param>
/// <returns></returns>
public static MethodReference MakeHostInstanceGeneric(this MethodReference self, CodegenSession session, GenericInstanceType instanceType)
{
MethodReference reference = new MethodReference(self.Name, self.ReturnType, instanceType)
{
CallingConvention = self.CallingConvention,
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis
};
foreach (ParameterDefinition parameter in self.Parameters)
reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
foreach (GenericParameter generic_parameter in self.GenericParameters)
reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
return session.ImportReference(reference);
}
/// <summary>
/// Given a method of a generic class such as ArraySegment`T.get_Count,
/// and a generic instance such as ArraySegment`int
/// Creates a reference to the specialized method ArraySegment`int`.get_Count
/// <para> Note that calling ArraySegment`T.get_Count directly gives an invalid IL error </para>
/// </summary>
/// <param name="self"></param>
/// <param name="instanceType"></param>
/// <returns></returns>
public static MethodReference MakeHostInstanceGeneric(this MethodReference self, TypeReference typeRef, params TypeReference[] args)
{
GenericInstanceType git = typeRef.MakeGenericInstanceType(args);
MethodReference reference = new MethodReference(self.Name, self.ReturnType, git)
{
CallingConvention = self.CallingConvention,
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis
};
foreach (ParameterDefinition parameter in self.Parameters)
reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
foreach (GenericParameter generic_parameter in self.GenericParameters)
reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
return reference;
}
public static bool Is<T>(this MethodReference method, string name)
{
return method.DeclaringType.Is<T>() && method.Name == name;
}
public static bool Is<T>(this TypeReference td)
{
return Is(td, typeof(T));
}
public static bool Is(this TypeReference td, Type t)
{
if (t.IsGenericType)
{
return td.GetElementType().FullName == t.FullName;
}
return td.FullName == t.FullName;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee1c15a06ab386e439ec5aa41e3496f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,63 @@
using FishNet.CodeGenerating.ILCore;
using MonoFN.Cecil;
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace FishNet.CodeGenerating.Helping.Extension
{
public static class ModuleDefinitionExtensions
{
/// <summary>
/// Gets a class within a module.
/// </summary>
/// <param name="moduleDef"></param>
/// <returns></returns>
public static TypeDefinition GetClass(this ModuleDefinition moduleDef, string className, string namespaceName = "")
{
if (namespaceName.Length == 0)
namespaceName = FishNetILPP.RUNTIME_ASSEMBLY_NAME;
return moduleDef.GetType(namespaceName, className);
}
public static MethodReference ImportReference(this ModuleDefinition moduleDef, Expression<Action> expression)
{
return ImportReference(moduleDef, (LambdaExpression)expression);
}
public static MethodReference ImportReference<T>(this ModuleDefinition module, Expression<Action<T>> expression)
{
return ImportReference(module, (LambdaExpression)expression);
}
public static MethodReference ImportReference(this ModuleDefinition module, LambdaExpression expression)
{
if (expression.Body is MethodCallExpression outermostExpression)
{
MethodInfo methodInfo = outermostExpression.Method;
return module.ImportReference(methodInfo);
}
if (expression.Body is NewExpression newExpression)
{
ConstructorInfo methodInfo = newExpression.Constructor;
// constructor is null when creating an ArraySegment<object>
methodInfo = methodInfo ?? newExpression.Type.GetConstructors()[0];
return module.ImportReference(methodInfo);
}
if (expression.Body is MemberExpression memberExpression)
{
var property = memberExpression.Member as PropertyInfo;
return module.ImportReference(property.GetMethod);
}
throw new ArgumentException($"Invalid Expression {expression.Body.GetType()}");
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42648785493390646898f5fa13e1dfd6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
using MonoFN.Cecil;
using System;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class ParameterDefinitionExtensions
{
/// <summary>
/// Returns if parameterDef is Type.
/// </summary>
/// <param name="parameterDef"></param>
/// <param name="type"></param>
/// <returns></returns>
public static bool Is(this ParameterDefinition parameterDef, Type type)
{
return parameterDef.ParameterType.FullName == type.FullName;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31071055a2e388141b8f11e1ba4e147e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,521 @@
using FishNet.CodeGenerating.Extension;
using MonoFN.Cecil;
using MonoFN.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class TypeDefinitionExtensionsOld
{
/// <summary>
/// Creates a GenericInstanceType and adds parameters.
/// </summary>
internal static GenericInstanceType CreateGenericInstanceType(this TypeDefinition type, Collection<GenericParameter> parameters)
{
GenericInstanceType git = new GenericInstanceType(type);
foreach (GenericParameter gp in parameters)
git.GenericArguments.Add(gp);
return git;
}
/// <summary>
/// Finds public fields in type and base type
/// </summary>
/// <param name="variable"></param>
/// <returns></returns>
public static IEnumerable<FieldDefinition> FindAllPublicFields(this TypeDefinition typeDef, CodegenSession session
, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
{
GeneralHelper gh = session.GetClass<GeneralHelper>();
while (typeDef != null)
{
if (IsExcluded(typeDef, excludedBaseTypes, excludedAssemblyPrefixes))
break;
foreach (FieldDefinition fd in typeDef.Fields)
{
if (fd.IsStatic)
continue;
if (fd.IsNotSerialized)
continue;
if (gh.CodegenExclude(fd))
continue;
if (fd.IsPrivate)
continue;
yield return fd;
}
try { typeDef = typeDef.BaseType?.CachedResolve(session); }
catch { break; }
}
}
/// <summary>
/// Finds public properties on typeDef and all base types which have a public get/set accessor.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
public static IEnumerable<PropertyDefinition> FindAllPublicProperties(this TypeDefinition typeDef, CodegenSession session
, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
{
GeneralHelper gh = session.GetClass<GeneralHelper>();
while (typeDef != null)
{
if (IsExcluded(typeDef, excludedBaseTypes, excludedAssemblyPrefixes))
break;
foreach (PropertyDefinition pd in typeDef.Properties)
{
//Missing get or set method.
if (pd.GetMethod == null || pd.SetMethod == null)
continue;
if (gh.CodegenExclude(pd))
continue;
if (pd.GetMethod.IsPrivate)
continue;
if (pd.SetMethod.IsPrivate)
continue;
if (pd.GetMethod.ReturnType.IsGenericParameter)
continue;
yield return pd;
}
try { typeDef = typeDef.BaseType?.CachedResolve(session); }
catch { break; }
}
}
/// <summary>
/// Returns if typeDef is excluded.
/// </summary>
private static bool IsExcluded(TypeDefinition typeDef, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
{
if (excludedBaseTypes != null)
{
foreach (System.Type t in excludedBaseTypes)
{
if (typeDef.FullName == t.FullName)
return true;
}
}
if (excludedAssemblyPrefixes != null)
{
foreach (string s in excludedAssemblyPrefixes)
{
int len = s.Length;
string tdAsmName = typeDef.Module.Assembly.FullName;
if (tdAsmName.Length >= len && tdAsmName.Substring(0, len).ToLower() == s.ToLower())
return true;
}
}
//Fall through, not excluded.
return false;
}
/// <summary>
/// Returns if typeDef is excluded.
/// </summary>
public static bool IsExcluded(this TypeDefinition typeDef, string excludedAssemblyPrefix)
{
int len = excludedAssemblyPrefix.Length;
string tdAsmName = typeDef.Module.Assembly.FullName;
if (tdAsmName.Length >= len && tdAsmName.Substring(0, len).ToLower() == excludedAssemblyPrefix.ToLower())
return true;
//Fall through, not excluded.
return false;
}
/// <summary>
/// Returns if typeDef or any of it's parents inherit from NetworkBehaviour.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
internal static bool InheritsNetworkBehaviour(this TypeDefinition typeDef, CodegenSession session)
{
string nbFullName = session.GetClass<NetworkBehaviourHelper>().FullName;
TypeDefinition copyTd = typeDef;
while (copyTd != null)
{
if (copyTd.FullName == nbFullName)
return true;
copyTd = copyTd.GetNextBaseTypeDefinition(session);
}
//Fall through, network behaviour not found.
return false;
}
/// <summary>
/// Returns a nested TypeDefinition of name.
/// </summary>
internal static TypeDefinition GetNestedType(this TypeDefinition typeDef, string name)
{
foreach (TypeDefinition nestedTd in typeDef.NestedTypes)
{
if (nestedTd.Name == name)
return nestedTd;
}
return null;
}
/// <summary>
/// Returns if the BaseType for TypeDef exist and is not NetworkBehaviour,
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
internal static bool CanProcessBaseType(this TypeDefinition typeDef, CodegenSession session)
{
return (typeDef != null && typeDef.BaseType != null && typeDef.BaseType.FullName != session.GetClass<NetworkBehaviourHelper>().FullName);
}
/// <summary>
/// Returns if the BaseType for TypeDef exist and is not NetworkBehaviour,
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
internal static TypeDefinition GetNextBaseClassToProcess(this TypeDefinition typeDef, CodegenSession session)
{
if (typeDef.BaseType != null && typeDef.BaseType.FullName != session.GetClass<NetworkBehaviourHelper>().FullName)
return typeDef.BaseType.CachedResolve(session);
else
return null;
}
internal static TypeDefinition GetLastBaseClass(this TypeDefinition typeDef, CodegenSession session)
{
TypeDefinition copyTd = typeDef;
while (copyTd.BaseType != null)
copyTd = copyTd.BaseType.CachedResolve(session);
return copyTd;
}
/// <summary>
/// Searches for a type in current and inherited types.
/// </summary>
internal static TypeDefinition GetClassInInheritance(this TypeDefinition typeDef, CodegenSession session, string typeFullName)
{
TypeDefinition copyTd = typeDef;
do
{
if (copyTd.FullName == typeFullName)
return copyTd;
if (copyTd.BaseType != null)
copyTd = copyTd.BaseType.CachedResolve(session);
else
copyTd = null;
} while (copyTd != null);
//Not found.
return null;
}
/// <summary>
/// Searches for a type in current and inherited types.
/// </summary>
internal static TypeDefinition GetClassInInheritance(this TypeDefinition typeDef, CodegenSession session, TypeDefinition targetTypeDef)
{
if (typeDef == null)
return null;
TypeDefinition copyTd = typeDef;
do
{
if (copyTd == targetTypeDef)
return copyTd;
if (copyTd.BaseType != null)
copyTd = copyTd.BaseType.CachedResolve(session);
else
copyTd = null;
} while (copyTd != null);
//Not found.
return null;
}
/// <summary>
/// Returns if typeDef is static (abstract, sealed).
/// </summary>
internal static bool IsStatic(this TypeDefinition typeDef)
{
//Combining flags in a single check some reason doesn't work right with HasFlag.
return (typeDef.Attributes.HasFlag(TypeAttributes.Abstract) && typeDef.Attributes.HasFlag(TypeAttributes.Sealed));
}
/// <summary>
/// Gets an enum underlying type for typeDef.
/// </summary>
/// <param name="typeDef"></param>
/// <returns></returns>
internal static TypeReference GetEnumUnderlyingTypeReference(this TypeDefinition typeDef)
{
foreach (FieldDefinition field in typeDef.Fields)
{
if (!field.IsStatic)
return field.FieldType;
}
throw new ArgumentException($"Invalid enum {typeDef.FullName}");
}
/// <summary>
/// Returns if typeDef is derived from type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="typeDef"></param>
/// <returns></returns>
internal static bool InheritsFrom<T>(this TypeDefinition typeDef, CodegenSession session)
{
return typeDef.InheritsFrom(session, typeof(T));
}
/// <summary>
/// Returns if typeDef is derived from type.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="type"></param>
/// <returns></returns>
internal static bool InheritsFrom(this TypeDefinition typeDef, CodegenSession session, Type type)
{
if (!typeDef.IsClass)
return false;
TypeDefinition copyTd = typeDef;
while (copyTd.BaseType != null)
{
if (copyTd.BaseType.IsType(type))
return true;
copyTd = copyTd.GetNextBaseTypeDefinition(session);
}
//Fall through.
return false;
}
/// <summary>
/// Adds a method to typeDef.
/// </summary>
/// <param name="typDef"></param>
/// <param name="methodName"></param>
/// <param name="attributes"></param>
/// <returns></returns>
internal static MethodDefinition AddMethod(this TypeDefinition typDef, string methodName, MethodAttributes attributes)
{
return AddMethod(typDef, methodName, attributes, typDef.Module.ImportReference(typeof(void)));
}
/// <summary>
/// Adds a method to typeDef.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="methodName"></param>
/// <param name="attributes"></param>
/// <param name="typeReference"></param>
/// <returns></returns>
internal static MethodDefinition AddMethod(this TypeDefinition typeDef, string methodName, MethodAttributes attributes, TypeReference typeReference)
{
var method = new MethodDefinition(methodName, attributes, typeReference);
typeDef.Methods.Add(method);
return method;
}
/// <summary>
/// Finds the first method by a given name.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="methodName"></param>
/// <returns></returns>
internal static MethodDefinition GetMethod(this TypeDefinition typeDef, string methodName)
{
return typeDef.Methods.FirstOrDefault(method => method.Name == methodName);
}
/// <summary>
/// Finds the first method by a given name.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="methodName"></param>
/// <returns></returns>
internal static MethodDefinition GetMethod(this TypeDefinition typeDef, string methodName, Type[] types)
{
throw new NotImplementedException();
}
/// <summary>
/// Returns if a type is a subclass of another.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="ClassTypeFullName"></param>
/// <returns></returns>
internal static bool IsSubclassOf(this TypeDefinition typeDef,CodegenSession session, string ClassTypeFullName)
{
if (!typeDef.IsClass) return false;
TypeReference baseTypeRef = typeDef.BaseType;
while (baseTypeRef != null)
{
if (baseTypeRef.FullName == ClassTypeFullName)
{
return true;
}
try
{
baseTypeRef = baseTypeRef.CachedResolve(session).BaseType;
}
catch
{
return false;
}
}
return false;
}
/// <summary>
/// Gets a field reference by name.
/// </summary>
/// <param name="typeDef"></param>
/// <param name="fieldName"></param>
/// <returns></returns>
public static FieldReference GetFieldReference(this TypeDefinition typeDef, string fieldName, CodegenSession session)
{
if (typeDef.HasFields)
{
for (int i = 0; i < typeDef.Fields.Count; i++)
{
if (typeDef.Fields[i].Name == fieldName)
return session.ImportReference(typeDef.Fields[i]);
}
}
return null;
}
/// <summary>
/// Returns if the TypeDefinition implements TInterface.
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <param name="typeDef"></param>
/// <returns></returns>
public static bool ImplementsInterface<TInterface>(this TypeDefinition typeDef)
{
for (int i = 0; i < typeDef.Interfaces.Count; i++)
{
if (typeDef.Interfaces[i].InterfaceType.Is<TInterface>())
return true;
}
return false;
}
/// <summary>
/// Returns if the TypeDefinition implements TInterface.
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <param name="typeDef"></param>
/// <returns></returns>
public static bool ImplementsInterface(this TypeDefinition typeDef, string interfaceName)
{
for (int i = 0; i < typeDef.Interfaces.Count; i++)
{
if (typeDef.Interfaces[i].InterfaceType.FullName == interfaceName)
return true;
}
return false;
}
/// <summary>
/// Returns if the TypeDefinition implements TInterface.
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <param name="typeDef"></param>
/// <returns></returns>
public static bool ImplementsInterfaceRecursive<T>(this TypeDefinition typeDef, CodegenSession session)
{
TypeDefinition climbTypeDef = typeDef;
while (climbTypeDef != null)
{
if (climbTypeDef.Interfaces.Any(i => i.InterfaceType.Is<T>()))
return true;
try
{
if (climbTypeDef.BaseType != null)
climbTypeDef = climbTypeDef.BaseType.CachedResolve(session);
else
climbTypeDef = null;
}
//Could not resolve assembly; can happen for assemblies being checked outside FishNet/csharp.
catch (AssemblyResolutionException)
{
break;
}
}
return false;
}
/// <summary>
/// Returns if the TypeDefinition implements TInterface.
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <param name="typeDef"></param>
/// <returns></returns>
public static bool ImplementsInterfaceRecursive(this TypeDefinition typeDef, CodegenSession session, string interfaceName)
{
TypeDefinition climbTypeDef = typeDef;
while (climbTypeDef != null)
{
if (climbTypeDef.Interfaces.Any(i => i.InterfaceType.FullName == interfaceName))
return true;
try
{
if (climbTypeDef.BaseType != null)
climbTypeDef = climbTypeDef.BaseType.CachedResolve(session);
else
climbTypeDef = null;
}
//Could not resolve assembly; can happen for assemblies being checked outside FishNet/csharp.
catch (AssemblyResolutionException)
{
break;
}
}
return false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 645e49fe7eeff3a4e9eb65d77fc6e2ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,138 @@
using MonoFN.Cecil;
using MonoFN.Cecil.Rocks;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FishNet.CodeGenerating.Helping.Extension
{
internal static class TypeReferenceExtensionsOld
{
/// <summary>
/// Gets a Resolve favoring cached results first.
/// </summary>
internal static TypeDefinition CachedResolve(this TypeReference typeRef, CodegenSession session)
{
return session.GetClass<GeneralHelper>().GetTypeReferenceResolve(typeRef);
}
/// <summary>
/// Returns if typeRef is a class or struct.
/// </summary>
internal static bool IsClassOrStruct(this TypeReference typeRef, CodegenSession session)
{
TypeDefinition typeDef = typeRef.CachedResolve(session);
return (!typeDef.IsPrimitive && !typeDef.IsEnum && (typeDef.IsClass || typeDef.IsValueType));
}
/// <summary>
/// Returns all properties on typeRef and all base types which have a public get/set accessor.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static IEnumerable<PropertyDefinition> FindAllSerializableProperties(this TypeReference typeRef, CodegenSession session, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
{
return typeRef.CachedResolve(session).FindAllPublicProperties(session, excludedBaseTypes, excludedAssemblyPrefixes);
}
/// <summary>
/// Gets all public fields in typeRef and base type.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static IEnumerable<FieldDefinition> FindAllSerializableFields(this TypeReference typeRef, CodegenSession session,
System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
{
return typeRef.Resolve().FindAllPublicFields(session, excludedBaseTypes, excludedAssemblyPrefixes);
}
/// <summary>
/// Returns if a typeRef is type.
/// </summary>
/// <param name="typeRef"></param>
/// <param name="type"></param>
/// <returns></returns>
public static bool IsType(this TypeReference typeRef, Type type)
{
if (type.IsGenericType)
return typeRef.GetElementType().FullName == type.FullName;
else
return typeRef.FullName == type.FullName;
}
/// <summary>
/// Returns if typeRef is a multidimensional array.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static bool IsMultidimensionalArray(this TypeReference typeRef)
{
return typeRef is ArrayType arrayType && arrayType.Rank > 1;
}
/// <summary>
/// Returns if typeRef can be resolved.
/// </summary>
/// <param name="typeRef"></param>
/// <returns></returns>
public static bool CanBeResolved(this TypeReference typeRef, CodegenSession session)
{
while (typeRef != null)
{
if (typeRef.Scope.Name == "Windows")
{
return false;
}
if (typeRef.Scope.Name == "mscorlib")
{
TypeDefinition resolved = typeRef.CachedResolve(session);
return resolved != null;
}
try
{
typeRef = typeRef.CachedResolve(session).BaseType;
}
catch
{
return false;
}
}
return true;
}
/// <summary>
/// Creates a generic type out of another type, if needed.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static TypeReference ConvertToGenericIfNeeded(this TypeDefinition type)
{
if (type.HasGenericParameters)
{
// get all the generic parameters and make a generic instance out of it
TypeReference[] genericTypes = new TypeReference[type.GenericParameters.Count];
for (int i = 0; i < type.GenericParameters.Count; i++)
{
genericTypes[i] = type.GenericParameters[i].GetElementType();
}
return type.MakeGenericInstanceType(genericTypes);
}
else
{
return type;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2344f5ab0fda07b498c03fbe0e082c14
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: