GenericParameterResolver.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using ILRuntime.Mono.Cecil.Cil;
  2. using System;
  3. namespace ILRuntime.Mono.Cecil {
  4. internal sealed class GenericParameterResolver {
  5. internal static TypeReference ResolveReturnTypeIfNeeded (MethodReference methodReference)
  6. {
  7. if (methodReference.DeclaringType.IsArray && methodReference.Name == "Get")
  8. return methodReference.ReturnType;
  9. var genericInstanceMethod = methodReference as GenericInstanceMethod;
  10. var declaringGenericInstanceType = methodReference.DeclaringType as GenericInstanceType;
  11. if (genericInstanceMethod == null && declaringGenericInstanceType == null)
  12. return methodReference.ReturnType;
  13. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, methodReference.ReturnType);
  14. }
  15. internal static TypeReference ResolveFieldTypeIfNeeded (FieldReference fieldReference)
  16. {
  17. return ResolveIfNeeded (null, fieldReference.DeclaringType as GenericInstanceType, fieldReference.FieldType);
  18. }
  19. internal static TypeReference ResolveParameterTypeIfNeeded (MethodReference method, ParameterReference parameter)
  20. {
  21. var genericInstanceMethod = method as GenericInstanceMethod;
  22. var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
  23. if (genericInstanceMethod == null && declaringGenericInstanceType == null)
  24. return parameter.ParameterType;
  25. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, parameter.ParameterType);
  26. }
  27. internal static TypeReference ResolveVariableTypeIfNeeded (MethodReference method, VariableReference variable)
  28. {
  29. var genericInstanceMethod = method as GenericInstanceMethod;
  30. var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
  31. if (genericInstanceMethod == null && declaringGenericInstanceType == null)
  32. return variable.VariableType;
  33. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, variable.VariableType);
  34. }
  35. private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance declaringGenericInstanceType, TypeReference parameterType)
  36. {
  37. var byRefType = parameterType as ByReferenceType;
  38. if (byRefType != null)
  39. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, byRefType);
  40. var arrayType = parameterType as ArrayType;
  41. if (arrayType != null)
  42. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, arrayType);
  43. var genericInstanceType = parameterType as GenericInstanceType;
  44. if (genericInstanceType != null)
  45. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericInstanceType);
  46. var genericParameter = parameterType as GenericParameter;
  47. if (genericParameter != null)
  48. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericParameter);
  49. var requiredModifierType = parameterType as RequiredModifierType;
  50. if (requiredModifierType != null && ContainsGenericParameters (requiredModifierType))
  51. return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType);
  52. if (ContainsGenericParameters (parameterType))
  53. throw new Exception ("Unexpected generic parameter.");
  54. return parameterType;
  55. }
  56. private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericParameter genericParameterElement)
  57. {
  58. return (genericParameterElement.MetadataType == MetadataType.MVar)
  59. ? (genericInstanceMethod != null ? genericInstanceMethod.GenericArguments[genericParameterElement.Position] : genericParameterElement)
  60. : genericInstanceType.GenericArguments[genericParameterElement.Position];
  61. }
  62. private static ArrayType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ArrayType arrayType)
  63. {
  64. return new ArrayType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank);
  65. }
  66. private static ByReferenceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType)
  67. {
  68. return new ByReferenceType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, byReferenceType.ElementType));
  69. }
  70. private static GenericInstanceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
  71. {
  72. if (!ContainsGenericParameters (genericInstanceType1))
  73. return genericInstanceType1;
  74. var newGenericInstance = new GenericInstanceType (genericInstanceType1.ElementType);
  75. foreach (var genericArgument in genericInstanceType1.GenericArguments) {
  76. if (!genericArgument.IsGenericParameter) {
  77. newGenericInstance.GenericArguments.Add (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, genericArgument));
  78. continue;
  79. }
  80. var genParam = (GenericParameter)genericArgument;
  81. switch (genParam.Type) {
  82. case GenericParameterType.Type: {
  83. if (genericInstanceType == null)
  84. throw new NotSupportedException ();
  85. newGenericInstance.GenericArguments.Add (genericInstanceType.GenericArguments[genParam.Position]);
  86. }
  87. break;
  88. case GenericParameterType.Method: {
  89. if (genericInstanceMethod == null)
  90. newGenericInstance.GenericArguments.Add (genParam);
  91. else
  92. newGenericInstance.GenericArguments.Add (genericInstanceMethod.GenericArguments[genParam.Position]);
  93. }
  94. break;
  95. }
  96. }
  97. return newGenericInstance;
  98. }
  99. private static bool ContainsGenericParameters (TypeReference typeReference)
  100. {
  101. var genericParameter = typeReference as GenericParameter;
  102. if (genericParameter != null)
  103. return true;
  104. var arrayType = typeReference as ArrayType;
  105. if (arrayType != null)
  106. return ContainsGenericParameters (arrayType.ElementType);
  107. var pointerType = typeReference as PointerType;
  108. if (pointerType != null)
  109. return ContainsGenericParameters (pointerType.ElementType);
  110. var byRefType = typeReference as ByReferenceType;
  111. if (byRefType != null)
  112. return ContainsGenericParameters (byRefType.ElementType);
  113. var sentinelType = typeReference as SentinelType;
  114. if (sentinelType != null)
  115. return ContainsGenericParameters (sentinelType.ElementType);
  116. var pinnedType = typeReference as PinnedType;
  117. if (pinnedType != null)
  118. return ContainsGenericParameters (pinnedType.ElementType);
  119. var requiredModifierType = typeReference as RequiredModifierType;
  120. if (requiredModifierType != null)
  121. return ContainsGenericParameters (requiredModifierType.ElementType);
  122. var genericInstance = typeReference as GenericInstanceType;
  123. if (genericInstance != null) {
  124. foreach (var genericArgument in genericInstance.GenericArguments) {
  125. if (ContainsGenericParameters (genericArgument))
  126. return true;
  127. }
  128. return false;
  129. }
  130. if (typeReference is TypeSpecification)
  131. throw new NotSupportedException ();
  132. return false;
  133. }
  134. }
  135. }