Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/cecil.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Mono.Cecil/GenericParameterResolver.cs')
-rw-r--r--Mono.Cecil/GenericParameterResolver.cs175
1 files changed, 175 insertions, 0 deletions
diff --git a/Mono.Cecil/GenericParameterResolver.cs b/Mono.Cecil/GenericParameterResolver.cs
new file mode 100644
index 0000000..86525c5
--- /dev/null
+++ b/Mono.Cecil/GenericParameterResolver.cs
@@ -0,0 +1,175 @@
+using Mono.Cecil.Cil;
+using System;
+
+namespace Mono.Cecil {
+ internal sealed class GenericParameterResolver {
+ internal static TypeReference ResolveReturnTypeIfNeeded (MethodReference methodReference)
+ {
+ if (methodReference.DeclaringType.IsArray && methodReference.Name == "Get")
+ return methodReference.ReturnType;
+
+ var genericInstanceMethod = methodReference as GenericInstanceMethod;
+ var 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)
+ {
+ var genericInstanceMethod = method as GenericInstanceMethod;
+ var 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)
+ {
+ var genericInstanceMethod = method as GenericInstanceMethod;
+ var 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)
+ {
+ var byRefType = parameterType as ByReferenceType;
+ if (byRefType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, byRefType);
+
+ var arrayType = parameterType as ArrayType;
+ if (arrayType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, arrayType);
+
+ var genericInstanceType = parameterType as GenericInstanceType;
+ if (genericInstanceType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericInstanceType);
+
+ var genericParameter = parameterType as GenericParameter;
+ if (genericParameter != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericParameter);
+
+ var requiredModifierType = parameterType as RequiredModifierType;
+ if (requiredModifierType != null && ContainsGenericParameters (requiredModifierType))
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType);
+
+ if (ContainsGenericParameters (parameterType))
+ throw new Exception ("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 ArrayType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank);
+ }
+
+ private static ByReferenceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType)
+ {
+ return new ByReferenceType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, byReferenceType.ElementType));
+ }
+
+ private static GenericInstanceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
+ {
+ if (!ContainsGenericParameters (genericInstanceType1))
+ return genericInstanceType1;
+
+ var newGenericInstance = new GenericInstanceType (genericInstanceType1.ElementType);
+
+ foreach (var genericArgument in genericInstanceType1.GenericArguments) {
+ if (!genericArgument.IsGenericParameter) {
+ newGenericInstance.GenericArguments.Add (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, genericArgument));
+ continue;
+ }
+
+ var 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)
+ {
+ var genericParameter = typeReference as GenericParameter;
+ if (genericParameter != null)
+ return true;
+
+ var arrayType = typeReference as ArrayType;
+ if (arrayType != null)
+ return ContainsGenericParameters (arrayType.ElementType);
+
+ var pointerType = typeReference as PointerType;
+ if (pointerType != null)
+ return ContainsGenericParameters (pointerType.ElementType);
+
+ var byRefType = typeReference as ByReferenceType;
+ if (byRefType != null)
+ return ContainsGenericParameters (byRefType.ElementType);
+
+ var sentinelType = typeReference as SentinelType;
+ if (sentinelType != null)
+ return ContainsGenericParameters (sentinelType.ElementType);
+
+ var pinnedType = typeReference as PinnedType;
+ if (pinnedType != null)
+ return ContainsGenericParameters (pinnedType.ElementType);
+
+ var requiredModifierType = typeReference as RequiredModifierType;
+ if (requiredModifierType != null)
+ return ContainsGenericParameters (requiredModifierType.ElementType);
+
+ var genericInstance = typeReference as GenericInstanceType;
+ if (genericInstance != null) {
+ foreach (var genericArgument in genericInstance.GenericArguments) {
+ if (ContainsGenericParameters (genericArgument))
+ return true;
+ }
+
+ return false;
+ }
+
+ if (typeReference is TypeSpecification)
+ throw new NotSupportedException ();
+
+ return false;
+ }
+ }
+}