Add overloads to IAssemblyResolver.Resolve which take a ReaderParameters for better...
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / MetadataResolver.cs
1 //
2 // MetadataResolver.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections.Generic;
31
32 using Mono.Collections.Generic;
33
34 namespace Mono.Cecil {
35
36         public interface IAssemblyResolver {
37                 AssemblyDefinition Resolve (AssemblyNameReference name);
38                 AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters);
39
40                 AssemblyDefinition Resolve (string fullName);
41                 AssemblyDefinition Resolve (string fullName, ReaderParameters parameters);
42         }
43
44         static class MetadataResolver {
45
46                 public static TypeDefinition Resolve (IAssemblyResolver resolver, TypeReference type)
47                 {
48                         type = type.GetElementType ();
49
50                         var scope = type.Scope;
51                         switch (scope.MetadataScopeType) {
52                         case MetadataScopeType.AssemblyNameReference:
53                                 var assembly = resolver.Resolve ((AssemblyNameReference) scope);
54                                 if (assembly == null)
55                                         return null;
56
57                                 return GetType (assembly.MainModule, type);
58                         case MetadataScopeType.ModuleDefinition:
59                                 return GetType ((ModuleDefinition) scope, type);
60                         case MetadataScopeType.ModuleReference:
61                                 var modules = type.Module.Assembly.Modules;
62                                 var module_ref = (ModuleReference) scope;
63                                 for (int i = 0; i < modules.Count; i++) {
64                                         var netmodule = modules [i];
65                                         if (netmodule.Name == module_ref.Name)
66                                                 return GetType (netmodule, type);
67                                 }
68                                 break;
69                         }
70
71                         throw new NotSupportedException ();
72                 }
73
74                 static TypeDefinition GetType (ModuleDefinition module, TypeReference type)
75                 {
76                         if (!type.IsNested)
77                                 return module.GetType (type.Namespace, type.Name);
78
79                         var declaring_type = type.DeclaringType.Resolve ();
80                         if (declaring_type == null)
81                                 return null;
82
83                         return declaring_type.GetNestedType (type.Name);
84                 }
85
86                 public static FieldDefinition Resolve (IAssemblyResolver resolver, FieldReference field)
87                 {
88                         var type = Resolve (resolver, field.DeclaringType);
89                         if (type == null)
90                                 return null;
91
92                         if (!type.HasFields)
93                                 return null;
94
95                         return GetField (resolver, type, field);
96                 }
97
98                 static FieldDefinition GetField (IAssemblyResolver resolver, TypeDefinition type, FieldReference reference)
99                 {
100                         while (type != null) {
101                                 var field = GetField (type.Fields, reference);
102                                 if (field != null)
103                                         return field;
104
105                                 if (type.BaseType == null)
106                                         return null;
107
108                                 type = Resolve (resolver, type.BaseType);
109                         }
110
111                         return null;
112                 }
113
114                 static FieldDefinition GetField (IList<FieldDefinition> fields, FieldReference reference)
115                 {
116                         for (int i = 0; i < fields.Count; i++) {
117                                 var field = fields [i];
118
119                                 if (field.Name != reference.Name)
120                                         continue;
121
122                                 if (!AreSame (field.FieldType, reference.FieldType))
123                                         continue;
124
125                                 return field;
126                         }
127
128                         return null;
129                 }
130
131                 public static MethodDefinition Resolve (IAssemblyResolver resolver, MethodReference method)
132                 {
133                         var type = Resolve (resolver, method.DeclaringType);
134                         if (type == null)
135                                 return null;
136
137                         method = method.GetElementMethod ();
138
139                         if (!type.HasMethods)
140                                 return null;
141
142                         return GetMethod (resolver, type, method);
143                 }
144
145                 static MethodDefinition GetMethod (IAssemblyResolver resolver, TypeDefinition type, MethodReference reference)
146                 {
147                         while (type != null) {
148                                 var method = GetMethod (type.Methods, reference);
149                                 if (method != null)
150                                         return method;
151
152                                 if (type.BaseType == null)
153                                         return null;
154
155                                 type = Resolve (resolver, type.BaseType);
156                         }
157
158                         return null;
159                 }
160
161                 public static MethodDefinition GetMethod (IList<MethodDefinition> methods, MethodReference reference)
162                 {
163                         for (int i = 0; i < methods.Count; i++) {
164                                 var method = methods [i];
165
166                                 if (method.Name != reference.Name)
167                                         continue;
168
169                                 if (!AreSame (method.ReturnType, reference.ReturnType))
170                                         continue;
171
172                                 if (method.HasParameters != reference.HasParameters)
173                                         continue;
174
175                                 if (!method.HasParameters && !reference.HasParameters)
176                                         return method;
177
178                                 if (!AreSame (method.Parameters, reference.Parameters))
179                                         continue;
180
181                                 return method;
182                         }
183
184                         return null;
185                 }
186
187                 static bool AreSame (Collection<ParameterDefinition> a, Collection<ParameterDefinition> b)
188                 {
189                         var count = a.Count;
190
191                         if (count != b.Count)
192                                 return false;
193
194                         if (count == 0)
195                                 return true;
196
197                         for (int i = 0; i < count; i++)
198                                 if (!AreSame (a [i].ParameterType, b [i].ParameterType))
199                                         return false;
200
201                         return true;
202                 }
203
204                 static bool AreSame (TypeSpecification a, TypeSpecification b)
205                 {
206                         if (!AreSame (a.ElementType, b.ElementType))
207                                 return false;
208
209                         if (a.IsGenericInstance)
210                                 return AreSame ((GenericInstanceType) a, (GenericInstanceType) b);
211
212                         if (a.IsRequiredModifier || a.IsOptionalModifier)
213                                 return AreSame ((IModifierType) a, (IModifierType) b);
214
215                         if (a.IsArray)
216                                 return AreSame ((ArrayType) a, (ArrayType) b);
217
218                         return true;
219                 }
220
221                 static bool AreSame (ArrayType a, ArrayType b)
222                 {
223                         if (a.Rank != b.Rank)
224                                 return false;
225
226                         // TODO: dimensions
227
228                         return true;
229                 }
230
231                 static bool AreSame (IModifierType a, IModifierType b)
232                 {
233                         return AreSame (a.ModifierType, b.ModifierType);
234                 }
235
236                 static bool AreSame (GenericInstanceType a, GenericInstanceType b)
237                 {
238                         if (!a.HasGenericArguments)
239                                 return !b.HasGenericArguments;
240
241                         if (!b.HasGenericArguments)
242                                 return false;
243
244                         if (a.GenericArguments.Count != b.GenericArguments.Count)
245                                 return false;
246
247                         for (int i = 0; i < a.GenericArguments.Count; i++)
248                                 if (!AreSame (a.GenericArguments [i], b.GenericArguments [i]))
249                                         return false;
250
251                         return true;
252                 }
253
254                 static bool AreSame (GenericParameter a, GenericParameter b)
255                 {
256                         return a.Position == b.Position;
257                 }
258
259                 static bool AreSame (TypeReference a, TypeReference b)
260                 {
261                         if (a.etype != b.etype)
262                                 return false;
263
264                         if (a.IsGenericParameter)
265                                 return AreSame ((GenericParameter) a, (GenericParameter) b);
266
267                         if (a.IsTypeSpecification ())
268                                 return AreSame ((TypeSpecification) a, (TypeSpecification) b);
269
270                         return a.FullName == b.FullName;
271                 }
272         }
273 }