/Mono.Cecil/MetadataResolver.cs

http://github.com/jbevain/cecil · C# · 391 lines · 278 code · 102 blank · 11 comment · 105 complexity · 91e96837f10f1b3070c7141f179ddeb1 MD5 · raw file

  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using Mono.Collections.Generic;
  12. namespace Mono.Cecil {
  13. public interface IAssemblyResolver : IDisposable {
  14. AssemblyDefinition Resolve (AssemblyNameReference name);
  15. AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters);
  16. }
  17. public interface IMetadataResolver {
  18. TypeDefinition Resolve (TypeReference type);
  19. FieldDefinition Resolve (FieldReference field);
  20. MethodDefinition Resolve (MethodReference method);
  21. }
  22. #if !NET_CORE
  23. [Serializable]
  24. #endif
  25. public sealed class ResolutionException : Exception {
  26. readonly MemberReference member;
  27. public MemberReference Member {
  28. get { return member; }
  29. }
  30. public IMetadataScope Scope {
  31. get {
  32. var type = member as TypeReference;
  33. if (type != null)
  34. return type.Scope;
  35. var declaring_type = member.DeclaringType;
  36. if (declaring_type != null)
  37. return declaring_type.Scope;
  38. throw new NotSupportedException ();
  39. }
  40. }
  41. public ResolutionException (MemberReference member)
  42. : base ("Failed to resolve " + member.FullName)
  43. {
  44. if (member == null)
  45. throw new ArgumentNullException ("member");
  46. this.member = member;
  47. }
  48. public ResolutionException (MemberReference member, Exception innerException)
  49. : base ("Failed to resolve " + member.FullName, innerException)
  50. {
  51. if (member == null)
  52. throw new ArgumentNullException ("member");
  53. this.member = member;
  54. }
  55. #if !NET_CORE
  56. ResolutionException (
  57. System.Runtime.Serialization.SerializationInfo info,
  58. System.Runtime.Serialization.StreamingContext context)
  59. : base (info, context)
  60. {
  61. }
  62. #endif
  63. }
  64. public class MetadataResolver : IMetadataResolver {
  65. readonly IAssemblyResolver assembly_resolver;
  66. public IAssemblyResolver AssemblyResolver {
  67. get { return assembly_resolver; }
  68. }
  69. public MetadataResolver (IAssemblyResolver assemblyResolver)
  70. {
  71. if (assemblyResolver == null)
  72. throw new ArgumentNullException ("assemblyResolver");
  73. assembly_resolver = assemblyResolver;
  74. }
  75. public virtual TypeDefinition Resolve (TypeReference type)
  76. {
  77. Mixin.CheckType (type);
  78. type = type.GetElementType ();
  79. var scope = type.Scope;
  80. if (scope == null)
  81. return null;
  82. switch (scope.MetadataScopeType) {
  83. case MetadataScopeType.AssemblyNameReference:
  84. var assembly = assembly_resolver.Resolve ((AssemblyNameReference) scope);
  85. if (assembly == null)
  86. return null;
  87. return GetType (assembly.MainModule, type);
  88. case MetadataScopeType.ModuleDefinition:
  89. return GetType ((ModuleDefinition) scope, type);
  90. case MetadataScopeType.ModuleReference:
  91. var modules = type.Module.Assembly.Modules;
  92. var module_ref = (ModuleReference) scope;
  93. for (int i = 0; i < modules.Count; i++) {
  94. var netmodule = modules [i];
  95. if (netmodule.Name == module_ref.Name)
  96. return GetType (netmodule, type);
  97. }
  98. break;
  99. }
  100. throw new NotSupportedException ();
  101. }
  102. static TypeDefinition GetType (ModuleDefinition module, TypeReference reference)
  103. {
  104. var type = GetTypeDefinition (module, reference);
  105. if (type != null)
  106. return type;
  107. if (!module.HasExportedTypes)
  108. return null;
  109. var exported_types = module.ExportedTypes;
  110. for (int i = 0; i < exported_types.Count; i++) {
  111. var exported_type = exported_types [i];
  112. if (exported_type.Name != reference.Name)
  113. continue;
  114. if (exported_type.Namespace != reference.Namespace)
  115. continue;
  116. return exported_type.Resolve ();
  117. }
  118. return null;
  119. }
  120. static TypeDefinition GetTypeDefinition (ModuleDefinition module, TypeReference type)
  121. {
  122. if (!type.IsNested)
  123. return module.GetType (type.Namespace, type.Name);
  124. var declaring_type = type.DeclaringType.Resolve ();
  125. if (declaring_type == null)
  126. return null;
  127. return declaring_type.GetNestedType (type.TypeFullName ());
  128. }
  129. public virtual FieldDefinition Resolve (FieldReference field)
  130. {
  131. Mixin.CheckField (field);
  132. var type = Resolve (field.DeclaringType);
  133. if (type == null)
  134. return null;
  135. if (!type.HasFields)
  136. return null;
  137. return GetField (type, field);
  138. }
  139. FieldDefinition GetField (TypeDefinition type, FieldReference reference)
  140. {
  141. while (type != null) {
  142. var field = GetField (type.Fields, reference);
  143. if (field != null)
  144. return field;
  145. if (type.BaseType == null)
  146. return null;
  147. type = Resolve (type.BaseType);
  148. }
  149. return null;
  150. }
  151. static FieldDefinition GetField (Collection<FieldDefinition> fields, FieldReference reference)
  152. {
  153. for (int i = 0; i < fields.Count; i++) {
  154. var field = fields [i];
  155. if (field.Name != reference.Name)
  156. continue;
  157. if (!AreSame (field.FieldType, reference.FieldType))
  158. continue;
  159. return field;
  160. }
  161. return null;
  162. }
  163. public virtual MethodDefinition Resolve (MethodReference method)
  164. {
  165. Mixin.CheckMethod (method);
  166. var type = Resolve (method.DeclaringType);
  167. if (type == null)
  168. return null;
  169. method = method.GetElementMethod ();
  170. if (!type.HasMethods)
  171. return null;
  172. return GetMethod (type, method);
  173. }
  174. MethodDefinition GetMethod (TypeDefinition type, MethodReference reference)
  175. {
  176. while (type != null) {
  177. var method = GetMethod (type.Methods, reference);
  178. if (method != null)
  179. return method;
  180. if (type.BaseType == null)
  181. return null;
  182. type = Resolve (type.BaseType);
  183. }
  184. return null;
  185. }
  186. public static MethodDefinition GetMethod (Collection<MethodDefinition> methods, MethodReference reference)
  187. {
  188. for (int i = 0; i < methods.Count; i++) {
  189. var method = methods [i];
  190. if (method.Name != reference.Name)
  191. continue;
  192. if (method.HasGenericParameters != reference.HasGenericParameters)
  193. continue;
  194. if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count)
  195. continue;
  196. if (!AreSame (method.ReturnType, reference.ReturnType))
  197. continue;
  198. if (method.IsVarArg () != reference.IsVarArg ())
  199. continue;
  200. if (method.IsVarArg () && IsVarArgCallTo (method, reference))
  201. return method;
  202. if (method.HasParameters != reference.HasParameters)
  203. continue;
  204. if (!method.HasParameters && !reference.HasParameters)
  205. return method;
  206. if (!AreSame (method.Parameters, reference.Parameters))
  207. continue;
  208. return method;
  209. }
  210. return null;
  211. }
  212. static bool AreSame (Collection<ParameterDefinition> a, Collection<ParameterDefinition> b)
  213. {
  214. var count = a.Count;
  215. if (count != b.Count)
  216. return false;
  217. if (count == 0)
  218. return true;
  219. for (int i = 0; i < count; i++)
  220. if (!AreSame (a [i].ParameterType, b [i].ParameterType))
  221. return false;
  222. return true;
  223. }
  224. static bool IsVarArgCallTo (MethodDefinition method, MethodReference reference)
  225. {
  226. if (method.Parameters.Count >= reference.Parameters.Count)
  227. return false;
  228. if (reference.GetSentinelPosition () != method.Parameters.Count)
  229. return false;
  230. for (int i = 0; i < method.Parameters.Count; i++)
  231. if (!AreSame (method.Parameters [i].ParameterType, reference.Parameters [i].ParameterType))
  232. return false;
  233. return true;
  234. }
  235. static bool AreSame (TypeSpecification a, TypeSpecification b)
  236. {
  237. if (!AreSame (a.ElementType, b.ElementType))
  238. return false;
  239. if (a.IsGenericInstance)
  240. return AreSame ((GenericInstanceType) a, (GenericInstanceType) b);
  241. if (a.IsRequiredModifier || a.IsOptionalModifier)
  242. return AreSame ((IModifierType) a, (IModifierType) b);
  243. if (a.IsArray)
  244. return AreSame ((ArrayType) a, (ArrayType) b);
  245. return true;
  246. }
  247. static bool AreSame (ArrayType a, ArrayType b)
  248. {
  249. if (a.Rank != b.Rank)
  250. return false;
  251. // TODO: dimensions
  252. return true;
  253. }
  254. static bool AreSame (IModifierType a, IModifierType b)
  255. {
  256. return AreSame (a.ModifierType, b.ModifierType);
  257. }
  258. static bool AreSame (GenericInstanceType a, GenericInstanceType b)
  259. {
  260. if (a.GenericArguments.Count != b.GenericArguments.Count)
  261. return false;
  262. for (int i = 0; i < a.GenericArguments.Count; i++)
  263. if (!AreSame (a.GenericArguments [i], b.GenericArguments [i]))
  264. return false;
  265. return true;
  266. }
  267. static bool AreSame (GenericParameter a, GenericParameter b)
  268. {
  269. return a.Position == b.Position;
  270. }
  271. static bool AreSame (TypeReference a, TypeReference b)
  272. {
  273. if (ReferenceEquals (a, b))
  274. return true;
  275. if (a == null || b == null)
  276. return false;
  277. if (a.etype != b.etype)
  278. return false;
  279. if (a.IsGenericParameter)
  280. return AreSame ((GenericParameter) a, (GenericParameter) b);
  281. if (a.IsTypeSpecification ())
  282. return AreSame ((TypeSpecification) a, (TypeSpecification) b);
  283. if (a.Name != b.Name || a.Namespace != b.Namespace)
  284. return false;
  285. //TODO: check scope
  286. return AreSame (a.DeclaringType, b.DeclaringType);
  287. }
  288. }
  289. }