[Add] FishNet
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
using MonoFN.Cecil.Cil;
|
||||
using System;
|
||||
|
||||
namespace MonoFN.Cecil
|
||||
{
|
||||
internal sealed class GenericParameterResolver
|
||||
{
|
||||
internal static TypeReference ResolveReturnTypeIfNeeded(MethodReference methodReference)
|
||||
{
|
||||
if (methodReference.DeclaringType.IsArray && methodReference.Name == "Get")
|
||||
return methodReference.ReturnType;
|
||||
|
||||
GenericInstanceMethod genericInstanceMethod = methodReference as GenericInstanceMethod;
|
||||
GenericInstanceType declaringGenericInstanceType = methodReference.DeclaringType as GenericInstanceType;
|
||||
|
||||
if (genericInstanceMethod == null && declaringGenericInstanceType == null)
|
||||
return methodReference.ReturnType;
|
||||
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, methodReference.ReturnType);
|
||||
}
|
||||
|
||||
internal static TypeReference ResolveFieldTypeIfNeeded(FieldReference fieldReference)
|
||||
{
|
||||
return ResolveIfNeeded(null, fieldReference.DeclaringType as GenericInstanceType, fieldReference.FieldType);
|
||||
}
|
||||
|
||||
internal static TypeReference ResolveParameterTypeIfNeeded(MethodReference method, ParameterReference parameter)
|
||||
{
|
||||
GenericInstanceMethod genericInstanceMethod = method as GenericInstanceMethod;
|
||||
GenericInstanceType declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
|
||||
|
||||
if (genericInstanceMethod == null && declaringGenericInstanceType == null)
|
||||
return parameter.ParameterType;
|
||||
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, parameter.ParameterType);
|
||||
}
|
||||
|
||||
internal static TypeReference ResolveVariableTypeIfNeeded(MethodReference method, VariableReference variable)
|
||||
{
|
||||
GenericInstanceMethod genericInstanceMethod = method as GenericInstanceMethod;
|
||||
GenericInstanceType declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
|
||||
|
||||
if (genericInstanceMethod == null && declaringGenericInstanceType == null)
|
||||
return variable.VariableType;
|
||||
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, variable.VariableType);
|
||||
}
|
||||
|
||||
private static TypeReference ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance declaringGenericInstanceType, TypeReference parameterType)
|
||||
{
|
||||
ByReferenceType byRefType = parameterType as ByReferenceType;
|
||||
if (byRefType != null)
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, byRefType);
|
||||
|
||||
ArrayType arrayType = parameterType as ArrayType;
|
||||
if (arrayType != null)
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, arrayType);
|
||||
|
||||
GenericInstanceType genericInstanceType = parameterType as GenericInstanceType;
|
||||
if (genericInstanceType != null)
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, genericInstanceType);
|
||||
|
||||
GenericParameter genericParameter = parameterType as GenericParameter;
|
||||
if (genericParameter != null)
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, genericParameter);
|
||||
|
||||
RequiredModifierType requiredModifierType = parameterType as RequiredModifierType;
|
||||
if (requiredModifierType != null && ContainsGenericParameters(requiredModifierType))
|
||||
return ResolveIfNeeded(genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType);
|
||||
|
||||
if (ContainsGenericParameters(parameterType))
|
||||
throw new("Unexpected generic parameter.");
|
||||
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
private static TypeReference ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericParameter genericParameterElement)
|
||||
{
|
||||
return genericParameterElement.MetadataType == MetadataType.MVar ? genericInstanceMethod != null ? genericInstanceMethod.GenericArguments[genericParameterElement.Position] : genericParameterElement : genericInstanceType.GenericArguments[genericParameterElement.Position];
|
||||
}
|
||||
|
||||
private static ArrayType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ArrayType arrayType)
|
||||
{
|
||||
return new(ResolveIfNeeded(genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank);
|
||||
}
|
||||
|
||||
private static ByReferenceType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType)
|
||||
{
|
||||
return new(ResolveIfNeeded(genericInstanceMethod, genericInstanceType, byReferenceType.ElementType));
|
||||
}
|
||||
|
||||
private static GenericInstanceType ResolveIfNeeded(IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
|
||||
{
|
||||
if (!ContainsGenericParameters(genericInstanceType1))
|
||||
return genericInstanceType1;
|
||||
|
||||
GenericInstanceType newGenericInstance = new(genericInstanceType1.ElementType);
|
||||
|
||||
foreach (TypeReference genericArgument in genericInstanceType1.GenericArguments)
|
||||
{
|
||||
if (!genericArgument.IsGenericParameter)
|
||||
{
|
||||
newGenericInstance.GenericArguments.Add(ResolveIfNeeded(genericInstanceMethod, genericInstanceType, genericArgument));
|
||||
continue;
|
||||
}
|
||||
|
||||
GenericParameter genParam = (GenericParameter)genericArgument;
|
||||
|
||||
switch (genParam.Type)
|
||||
{
|
||||
case GenericParameterType.Type:
|
||||
{
|
||||
if (genericInstanceType == null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
newGenericInstance.GenericArguments.Add(genericInstanceType.GenericArguments[genParam.Position]);
|
||||
}
|
||||
break;
|
||||
|
||||
case GenericParameterType.Method:
|
||||
{
|
||||
if (genericInstanceMethod == null)
|
||||
newGenericInstance.GenericArguments.Add(genParam);
|
||||
else
|
||||
newGenericInstance.GenericArguments.Add(genericInstanceMethod.GenericArguments[genParam.Position]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newGenericInstance;
|
||||
}
|
||||
|
||||
private static bool ContainsGenericParameters(TypeReference typeReference)
|
||||
{
|
||||
GenericParameter genericParameter = typeReference as GenericParameter;
|
||||
if (genericParameter != null)
|
||||
return true;
|
||||
|
||||
ArrayType arrayType = typeReference as ArrayType;
|
||||
if (arrayType != null)
|
||||
return ContainsGenericParameters(arrayType.ElementType);
|
||||
|
||||
PointerType pointerType = typeReference as PointerType;
|
||||
if (pointerType != null)
|
||||
return ContainsGenericParameters(pointerType.ElementType);
|
||||
|
||||
ByReferenceType byRefType = typeReference as ByReferenceType;
|
||||
if (byRefType != null)
|
||||
return ContainsGenericParameters(byRefType.ElementType);
|
||||
|
||||
SentinelType sentinelType = typeReference as SentinelType;
|
||||
if (sentinelType != null)
|
||||
return ContainsGenericParameters(sentinelType.ElementType);
|
||||
|
||||
PinnedType pinnedType = typeReference as PinnedType;
|
||||
if (pinnedType != null)
|
||||
return ContainsGenericParameters(pinnedType.ElementType);
|
||||
|
||||
RequiredModifierType requiredModifierType = typeReference as RequiredModifierType;
|
||||
if (requiredModifierType != null)
|
||||
return ContainsGenericParameters(requiredModifierType.ElementType);
|
||||
|
||||
GenericInstanceType genericInstance = typeReference as GenericInstanceType;
|
||||
if (genericInstance != null)
|
||||
{
|
||||
foreach (TypeReference genericArgument in genericInstance.GenericArguments)
|
||||
{
|
||||
if (ContainsGenericParameters(genericArgument))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeReference is TypeSpecification)
|
||||
throw new NotSupportedException();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user