PageRenderTime 28ms CodeModel.GetById 11ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 11using System;
 12
 13using Mono.Collections.Generic;
 14
 15namespace Mono.Cecil {
 16
 17	public interface IAssemblyResolver : IDisposable {
 18		AssemblyDefinition Resolve (AssemblyNameReference name);
 19		AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters);
 20	}
 21
 22	public interface IMetadataResolver {
 23		TypeDefinition Resolve (TypeReference type);
 24		FieldDefinition Resolve (FieldReference field);
 25		MethodDefinition Resolve (MethodReference method);
 26	}
 27
 28#if !NET_CORE
 29	[Serializable]
 30#endif
 31	public sealed class ResolutionException : Exception {
 32
 33		readonly MemberReference member;
 34
 35		public MemberReference Member {
 36			get { return member; }
 37		}
 38
 39		public IMetadataScope Scope {
 40			get {
 41				var type = member as TypeReference;
 42				if (type != null)
 43					return type.Scope;
 44
 45				var declaring_type = member.DeclaringType;
 46				if (declaring_type != null)
 47					return declaring_type.Scope;
 48
 49				throw new NotSupportedException ();
 50			}
 51		}
 52
 53		public ResolutionException (MemberReference member)
 54			: base ("Failed to resolve " + member.FullName)
 55		{
 56			if (member == null)
 57				throw new ArgumentNullException ("member");
 58
 59			this.member = member;
 60		}
 61
 62		public ResolutionException (MemberReference member, Exception innerException)
 63			: base ("Failed to resolve " + member.FullName, innerException)
 64		{
 65			if (member == null)
 66				throw new ArgumentNullException ("member");
 67
 68			this.member = member;
 69		}
 70
 71#if !NET_CORE
 72		ResolutionException (
 73			System.Runtime.Serialization.SerializationInfo info,
 74			System.Runtime.Serialization.StreamingContext context)
 75			: base (info, context)
 76		{
 77		}
 78#endif
 79	}
 80
 81	public class MetadataResolver : IMetadataResolver {
 82
 83		readonly IAssemblyResolver assembly_resolver;
 84
 85		public IAssemblyResolver AssemblyResolver {
 86			get { return assembly_resolver; }
 87		}
 88
 89		public MetadataResolver (IAssemblyResolver assemblyResolver)
 90		{
 91			if (assemblyResolver == null)
 92				throw new ArgumentNullException ("assemblyResolver");
 93
 94			assembly_resolver = assemblyResolver;
 95		}
 96
 97		public virtual TypeDefinition Resolve (TypeReference type)
 98		{
 99			Mixin.CheckType (type);
100
101			type = type.GetElementType ();
102
103			var scope = type.Scope;
104
105			if (scope == null)
106				return null;
107
108			switch (scope.MetadataScopeType) {
109			case MetadataScopeType.AssemblyNameReference:
110				var assembly = assembly_resolver.Resolve ((AssemblyNameReference) scope);
111				if (assembly == null)
112					return null;
113
114				return GetType (assembly.MainModule, type);
115			case MetadataScopeType.ModuleDefinition:
116				return GetType ((ModuleDefinition) scope, type);
117			case MetadataScopeType.ModuleReference:
118				var modules = type.Module.Assembly.Modules;
119				var module_ref = (ModuleReference) scope;
120				for (int i = 0; i < modules.Count; i++) {
121					var netmodule = modules [i];
122					if (netmodule.Name == module_ref.Name)
123						return GetType (netmodule, type);
124				}
125				break;
126			}
127
128			throw new NotSupportedException ();
129		}
130
131		static TypeDefinition GetType (ModuleDefinition module, TypeReference reference)
132		{
133			var type = GetTypeDefinition (module, reference);
134			if (type != null)
135				return type;
136
137			if (!module.HasExportedTypes)
138				return null;
139
140			var exported_types = module.ExportedTypes;
141
142			for (int i = 0; i < exported_types.Count; i++) {
143				var exported_type = exported_types [i];
144				if (exported_type.Name != reference.Name)
145					continue;
146
147				if (exported_type.Namespace != reference.Namespace)
148					continue;
149
150				return exported_type.Resolve ();
151			}
152
153			return null;
154		}
155
156		static TypeDefinition GetTypeDefinition (ModuleDefinition module, TypeReference type)
157		{
158			if (!type.IsNested)
159				return module.GetType (type.Namespace, type.Name);
160
161			var declaring_type = type.DeclaringType.Resolve ();
162			if (declaring_type == null)
163				return null;
164
165			return declaring_type.GetNestedType (type.TypeFullName ());
166		}
167
168		public virtual FieldDefinition Resolve (FieldReference field)
169		{
170			Mixin.CheckField (field);
171
172			var type = Resolve (field.DeclaringType);
173			if (type == null)
174				return null;
175
176			if (!type.HasFields)
177				return null;
178
179			return GetField (type, field);
180		}
181
182		FieldDefinition GetField (TypeDefinition type, FieldReference reference)
183		{
184			while (type != null) {
185				var field = GetField (type.Fields, reference);
186				if (field != null)
187					return field;
188
189				if (type.BaseType == null)
190					return null;
191
192				type = Resolve (type.BaseType);
193			}
194
195			return null;
196		}
197
198		static FieldDefinition GetField (Collection<FieldDefinition> fields, FieldReference reference)
199		{
200			for (int i = 0; i < fields.Count; i++) {
201				var field = fields [i];
202
203				if (field.Name != reference.Name)
204					continue;
205
206				if (!AreSame (field.FieldType, reference.FieldType))
207					continue;
208
209				return field;
210			}
211
212			return null;
213		}
214
215		public virtual MethodDefinition Resolve (MethodReference method)
216		{
217			Mixin.CheckMethod (method);
218
219			var type = Resolve (method.DeclaringType);
220			if (type == null)
221				return null;
222
223			method = method.GetElementMethod ();
224
225			if (!type.HasMethods)
226				return null;
227
228			return GetMethod (type, method);
229		}
230
231		MethodDefinition GetMethod (TypeDefinition type, MethodReference reference)
232		{
233			while (type != null) {
234				var method = GetMethod (type.Methods, reference);
235				if (method != null)
236					return method;
237
238				if (type.BaseType == null)
239					return null;
240
241				type = Resolve (type.BaseType);
242			}
243
244			return null;
245		}
246
247		public static MethodDefinition GetMethod (Collection<MethodDefinition> methods, MethodReference reference)
248		{
249			for (int i = 0; i < methods.Count; i++) {
250				var method = methods [i];
251
252				if (method.Name != reference.Name)
253					continue;
254
255				if (method.HasGenericParameters != reference.HasGenericParameters)
256					continue;
257
258				if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count)
259					continue;
260
261				if (!AreSame (method.ReturnType, reference.ReturnType))
262					continue;
263
264				if (method.IsVarArg () != reference.IsVarArg ())
265					continue;
266
267				if (method.IsVarArg () && IsVarArgCallTo (method, reference))
268					return method;
269
270				if (method.HasParameters != reference.HasParameters)
271					continue;
272
273				if (!method.HasParameters && !reference.HasParameters)
274					return method;
275
276				if (!AreSame (method.Parameters, reference.Parameters))
277					continue;
278
279				return method;
280			}
281
282			return null;
283		}
284
285		static bool AreSame (Collection<ParameterDefinition> a, Collection<ParameterDefinition> b)
286		{
287			var count = a.Count;
288
289			if (count != b.Count)
290				return false;
291
292			if (count == 0)
293				return true;
294
295			for (int i = 0; i < count; i++)
296				if (!AreSame (a [i].ParameterType, b [i].ParameterType))
297					return false;
298
299			return true;
300		}
301
302		static bool IsVarArgCallTo (MethodDefinition method, MethodReference reference)
303		{
304			if (method.Parameters.Count >= reference.Parameters.Count)
305				return false;
306
307			if (reference.GetSentinelPosition () != method.Parameters.Count)
308				return false;
309
310			for (int i = 0; i < method.Parameters.Count; i++)
311				if (!AreSame (method.Parameters [i].ParameterType, reference.Parameters [i].ParameterType))
312					return false;
313
314			return true;
315		}
316
317		static bool AreSame (TypeSpecification a, TypeSpecification b)
318		{
319			if (!AreSame (a.ElementType, b.ElementType))
320				return false;
321
322			if (a.IsGenericInstance)
323				return AreSame ((GenericInstanceType) a, (GenericInstanceType) b);
324
325			if (a.IsRequiredModifier || a.IsOptionalModifier)
326				return AreSame ((IModifierType) a, (IModifierType) b);
327
328			if (a.IsArray)
329				return AreSame ((ArrayType) a, (ArrayType) b);
330
331			return true;
332		}
333
334		static bool AreSame (ArrayType a, ArrayType b)
335		{
336			if (a.Rank != b.Rank)
337				return false;
338
339			// TODO: dimensions
340
341			return true;
342		}
343
344		static bool AreSame (IModifierType a, IModifierType b)
345		{
346			return AreSame (a.ModifierType, b.ModifierType);
347		}
348
349		static bool AreSame (GenericInstanceType a, GenericInstanceType b)
350		{
351			if (a.GenericArguments.Count != b.GenericArguments.Count)
352				return false;
353
354			for (int i = 0; i < a.GenericArguments.Count; i++)
355				if (!AreSame (a.GenericArguments [i], b.GenericArguments [i]))
356					return false;
357
358			return true;
359		}
360
361		static bool AreSame (GenericParameter a, GenericParameter b)
362		{
363			return a.Position == b.Position;
364		}
365
366		static bool AreSame (TypeReference a, TypeReference b)
367		{
368			if (ReferenceEquals (a, b))
369				return true;
370
371			if (a == null || b == null)
372				return false;
373
374			if (a.etype != b.etype)
375				return false;
376
377			if (a.IsGenericParameter)
378				return AreSame ((GenericParameter) a, (GenericParameter) b);
379
380			if (a.IsTypeSpecification ())
381				return AreSame ((TypeSpecification) a, (TypeSpecification) b);
382
383			if (a.Name != b.Name || a.Namespace != b.Namespace)
384				return false;
385
386			//TODO: check scope
387
388			return AreSame (a.DeclaringType, b.DeclaringType);
389		}
390	}
391}