Merge remote branch 'upstream/master'
[mono.git] / mcs / class / IKVM.Reflection / Module.cs
1 /*
2   Copyright (C) 2009-2010 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using IKVM.Reflection.Metadata;
27 using IKVM.Reflection.Reader;
28
29 namespace IKVM.Reflection
30 {
31         public sealed class RawModule : IDisposable
32         {
33                 private readonly ModuleReader module;
34                 private readonly bool isManifestModule;
35                 private bool imported;
36
37                 internal RawModule(ModuleReader module)
38                 {
39                         this.module = module;
40                         this.isManifestModule = module.Assembly != null;
41                 }
42
43                 public string Location
44                 {
45                         get { return module.FullyQualifiedName; }
46                 }
47
48                 public bool IsManifestModule
49                 {
50                         get { return isManifestModule; }
51                 }
52
53                 private void CheckManifestModule()
54                 {
55                         if (!IsManifestModule)
56                         {
57                                 throw new BadImageFormatException("Module does not contain a manifest");
58                         }
59                 }
60
61                 public AssemblyName GetAssemblyName()
62                 {
63                         CheckManifestModule();
64                         return module.Assembly.GetName();
65                 }
66
67                 public AssemblyName[] GetReferencedAssemblies()
68                 {
69                         return module.__GetReferencedAssemblies();
70                 }
71
72                 public void Dispose()
73                 {
74                         if (!imported)
75                         {
76                                 module.stream.Dispose();
77                         }
78                 }
79
80                 internal Assembly ToAssembly()
81                 {
82                         if (imported)
83                         {
84                                 throw new InvalidOperationException();
85                         }
86                         imported = true;
87                         return module.Assembly;
88                 }
89
90                 internal Module ToModule(Assembly assembly)
91                 {
92                         if (module.Assembly != null)
93                         {
94                                 throw new InvalidOperationException();
95                         }
96                         imported = true;
97                         module.SetAssembly(assembly);
98                         return module;
99                 }
100         }
101
102         public abstract class Module : ICustomAttributeProvider
103         {
104                 internal readonly Universe universe;
105                 internal readonly ModuleTable ModuleTable = new ModuleTable();
106                 internal readonly TypeRefTable TypeRef = new TypeRefTable();
107                 internal readonly TypeDefTable TypeDef = new TypeDefTable();
108                 internal readonly FieldTable Field = new FieldTable();
109                 internal readonly MemberRefTable MemberRef = new MemberRefTable();
110                 internal readonly ConstantTable Constant = new ConstantTable();
111                 internal readonly CustomAttributeTable CustomAttribute = new CustomAttributeTable();
112                 internal readonly FieldMarshalTable FieldMarshal = new FieldMarshalTable();
113                 internal readonly DeclSecurityTable DeclSecurity = new DeclSecurityTable();
114                 internal readonly ClassLayoutTable ClassLayout = new ClassLayoutTable();
115                 internal readonly FieldLayoutTable FieldLayout = new FieldLayoutTable();
116                 internal readonly ParamTable Param = new ParamTable();
117                 internal readonly InterfaceImplTable InterfaceImpl = new InterfaceImplTable();
118                 internal readonly StandAloneSigTable StandAloneSig = new StandAloneSigTable();
119                 internal readonly EventMapTable EventMap = new EventMapTable();
120                 internal readonly EventTable Event = new EventTable();
121                 internal readonly PropertyMapTable PropertyMap = new PropertyMapTable();
122                 internal readonly PropertyTable Property = new PropertyTable();
123                 internal readonly MethodSemanticsTable MethodSemantics = new MethodSemanticsTable();
124                 internal readonly MethodImplTable MethodImpl = new MethodImplTable();
125                 internal readonly ModuleRefTable ModuleRef = new ModuleRefTable();
126                 internal readonly TypeSpecTable TypeSpec = new TypeSpecTable();
127                 internal readonly ImplMapTable ImplMap = new ImplMapTable();
128                 internal readonly FieldRVATable FieldRVA = new FieldRVATable();
129                 internal readonly AssemblyTable AssemblyTable = new AssemblyTable();
130                 internal readonly AssemblyRefTable AssemblyRef = new AssemblyRefTable();
131                 internal readonly MethodDefTable MethodDef = new MethodDefTable();
132                 internal readonly NestedClassTable NestedClass = new NestedClassTable();
133                 internal readonly FileTable File = new FileTable();
134                 internal readonly ExportedTypeTable ExportedType = new ExportedTypeTable();
135                 internal readonly ManifestResourceTable ManifestResource = new ManifestResourceTable();
136                 internal readonly GenericParamTable GenericParam = new GenericParamTable();
137                 internal readonly MethodSpecTable MethodSpec = new MethodSpecTable();
138                 internal readonly GenericParamConstraintTable GenericParamConstraint = new GenericParamConstraintTable();
139
140                 internal Module(Universe universe)
141                 {
142                         this.universe = universe;
143                 }
144
145                 internal Table[] GetTables()
146                 {
147                         Table[] tables = new Table[64];
148                         tables[ModuleTable.Index] = ModuleTable;
149                         tables[TypeRefTable.Index] = TypeRef;
150                         tables[TypeDefTable.Index] = TypeDef;
151                         tables[FieldTable.Index] = Field;
152                         tables[MemberRefTable.Index] = MemberRef;
153                         tables[ConstantTable.Index] = Constant;
154                         tables[CustomAttributeTable.Index] = CustomAttribute;
155                         tables[FieldMarshalTable.Index] = FieldMarshal;
156                         tables[DeclSecurityTable.Index] = DeclSecurity;
157                         tables[ClassLayoutTable.Index] = ClassLayout;
158                         tables[FieldLayoutTable.Index] = FieldLayout;
159                         tables[ParamTable.Index] = Param;
160                         tables[InterfaceImplTable.Index] = InterfaceImpl;
161                         tables[StandAloneSigTable.Index] = StandAloneSig;
162                         tables[EventMapTable.Index] = EventMap;
163                         tables[EventTable.Index] = Event;
164                         tables[PropertyMapTable.Index] = PropertyMap;
165                         tables[PropertyTable.Index] = Property;
166                         tables[MethodSemanticsTable.Index] = MethodSemantics;
167                         tables[MethodImplTable.Index] = MethodImpl;
168                         tables[ModuleRefTable.Index] = ModuleRef;
169                         tables[TypeSpecTable.Index] = TypeSpec;
170                         tables[ImplMapTable.Index] = ImplMap;
171                         tables[FieldRVATable.Index] = FieldRVA;
172                         tables[AssemblyTable.Index] = AssemblyTable;
173                         tables[AssemblyRefTable.Index] = AssemblyRef;
174                         tables[MethodDefTable.Index] = MethodDef;
175                         tables[NestedClassTable.Index] = NestedClass;
176                         tables[FileTable.Index] = File;
177                         tables[ExportedTypeTable.Index] = ExportedType;
178                         tables[ManifestResourceTable.Index] = ManifestResource;
179                         tables[GenericParamTable.Index] = GenericParam;
180                         tables[MethodSpecTable.Index] = MethodSpec;
181                         tables[GenericParamConstraintTable.Index] = GenericParamConstraint;
182                         return tables;
183                 }
184
185                 public virtual void __GetDataDirectoryEntry(int index, out int rva, out int length)
186                 {
187                         throw new NotSupportedException();
188                 }
189
190                 public virtual long __RelativeVirtualAddressToFileOffset(int rva)
191                 {
192                         throw new NotSupportedException();
193                 }
194
195                 public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
196                 {
197                         throw new NotSupportedException();
198                 }
199
200                 public virtual int __Subsystem
201                 {
202                         get { throw new NotSupportedException(); }
203                 }
204
205                 public FieldInfo GetField(string name)
206                 {
207                         return IsResource() ? null : GetModuleType().GetField(name);
208                 }
209
210                 public FieldInfo GetField(string name, BindingFlags bindingFlags)
211                 {
212                         return IsResource() ? null : GetModuleType().GetField(name, bindingFlags);
213                 }
214
215                 public FieldInfo[] GetFields()
216                 {
217                         return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields();
218                 }
219
220                 public FieldInfo[] GetFields(BindingFlags bindingFlags)
221                 {
222                         return IsResource() ? Empty<FieldInfo>.Array : GetModuleType().GetFields(bindingFlags);
223                 }
224
225                 public MethodInfo GetMethod(string name)
226                 {
227                         return IsResource() ? null : GetModuleType().GetMethod(name);
228                 }
229
230                 public MethodInfo GetMethod(string name, Type[] types)
231                 {
232                         return IsResource() ? null : GetModuleType().GetMethod(name, types);
233                 }
234
235                 public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers)
236                 {
237                         return IsResource() ? null : GetModuleType().GetMethod(name, bindingAttr, binder, callConv, types, modifiers);
238                 }
239
240                 public MethodInfo[] GetMethods()
241                 {
242                         return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods();
243                 }
244
245                 public MethodInfo[] GetMethods(BindingFlags bindingFlags)
246                 {
247                         return IsResource() ? Empty<MethodInfo>.Array : GetModuleType().GetMethods(bindingFlags);
248                 }
249
250                 public ConstructorInfo __ModuleInitializer
251                 {
252                         get { return IsResource() ? null : GetModuleType().TypeInitializer; }
253                 }
254
255                 public byte[] ResolveSignature(int metadataToken)
256                 {
257                         ModuleReader rdr = this as ModuleReader;
258                         if (rdr != null)
259                         {
260                                 ByteReader br = rdr.ResolveSignature(metadataToken);
261                                 return br.ReadBytes(br.Length);
262                         }
263                         throw new NotSupportedException();
264                 }
265
266                 public virtual __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
267                 {
268                         throw new NotSupportedException();
269                 }
270
271                 public int MetadataToken
272                 {
273                         get { return IsResource() ? 0 : 1; }
274                 }
275
276                 public abstract int MDStreamVersion { get ;}
277                 public abstract Assembly Assembly { get; }
278                 public abstract string FullyQualifiedName { get; }
279                 public abstract string Name { get; }
280                 public abstract Guid ModuleVersionId { get; }
281                 public abstract Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
282                 public abstract MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
283                 public abstract FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
284                 public abstract MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments);
285
286                 public abstract string ResolveString(int metadataToken);
287                 public abstract Type[] __ResolveOptionalParameterTypes(int metadataToken);
288                 public abstract string ScopeName { get; }
289
290                 internal abstract Type GetTypeImpl(string typeName);
291                 internal abstract void GetTypesImpl(List<Type> list);
292
293                 public Type GetType(string className)
294                 {
295                         return GetType(className, false, false);
296                 }
297
298                 public Type GetType(string className, bool ignoreCase)
299                 {
300                         return GetType(className, false, ignoreCase);
301                 }
302
303                 public Type GetType(string className, bool throwOnError, bool ignoreCase)
304                 {
305                         if (ignoreCase)
306                         {
307                                 throw new NotImplementedException();
308                         }
309                         TypeNameParser parser = TypeNameParser.Parse(className, throwOnError);
310                         if (parser.Error)
311                         {
312                                 return null;
313                         }
314                         if (parser.AssemblyName != null)
315                         {
316                                 if (throwOnError)
317                                 {
318                                         throw new ArgumentException("Type names passed to Module.GetType() must not specify an assembly.");
319                                 }
320                                 else
321                                 {
322                                         return null;
323                                 }
324                         }
325                         return parser.Expand(GetTypeImpl(parser.FirstNamePart), this.Assembly, throwOnError, className);
326                 }
327
328                 public Type[] GetTypes()
329                 {
330                         List<Type> list = new List<Type>();
331                         GetTypesImpl(list);
332                         return list.ToArray();
333                 }
334
335                 public Type[] FindTypes(TypeFilter filter, object filterCriteria)
336                 {
337                         List<Type> list = new List<Type>();
338                         foreach (Type type in GetTypes())
339                         {
340                                 if (filter(type, filterCriteria))
341                                 {
342                                         list.Add(type);
343                                 }
344                         }
345                         return list.ToArray();
346                 }
347
348                 public virtual bool IsResource()
349                 {
350                         return false;
351                 }
352
353                 public Type ResolveType(int metadataToken)
354                 {
355                         return ResolveType(metadataToken, null, null);
356                 }
357
358                 public MethodBase ResolveMethod(int metadataToken)
359                 {
360                         return ResolveMethod(metadataToken, null, null);
361                 }
362
363                 public FieldInfo ResolveField(int metadataToken)
364                 {
365                         return ResolveField(metadataToken, null, null);
366                 }
367
368                 public MemberInfo ResolveMember(int metadataToken)
369                 {
370                         return ResolveMember(metadataToken, null, null);
371                 }
372
373                 public bool IsDefined(Type attributeType, bool inherit)
374                 {
375                         return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit).Count != 0;
376                 }
377
378                 public IList<CustomAttributeData> __GetCustomAttributes(Type attributeType, bool inherit)
379                 {
380                         return CustomAttributeData.__GetCustomAttributes(this, attributeType, inherit);
381                 }
382
383                 public virtual IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
384                 {
385                         return Empty<CustomAttributeData>.Array;
386                 }
387
388                 public abstract AssemblyName[] __GetReferencedAssemblies();
389
390                 internal Type CanonicalizeType(Type type)
391                 {
392                         Type canon;
393                         if (!universe.canonicalizedTypes.TryGetValue(type, out canon))
394                         {
395                                 canon = type;
396                                 universe.canonicalizedTypes.Add(canon, canon);
397                         }
398                         return canon;
399                 }
400
401                 internal abstract Type GetModuleType();
402
403                 internal abstract ByteReader GetBlob(int blobIndex);
404
405                 internal IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
406                 {
407                         return GetCustomAttributes(0x00000001, attributeType);
408                 }
409
410                 internal List<CustomAttributeData> GetCustomAttributes(int metadataToken, Type attributeType)
411                 {
412                         List<CustomAttributeData> list = new List<CustomAttributeData>();
413                         // TODO use binary search?
414                         for (int i = 0; i < CustomAttribute.records.Length; i++)
415                         {
416                                 if (CustomAttribute.records[i].Parent == metadataToken)
417                                 {
418                                         if (attributeType == null)
419                                         {
420                                                 list.Add(new CustomAttributeData(this, i));
421                                         }
422                                         else
423                                         {
424                                                 ConstructorInfo constructor = (ConstructorInfo)ResolveMethod(CustomAttribute.records[i].Type);
425                                                 if (attributeType.IsAssignableFrom(constructor.DeclaringType))
426                                                 {
427                                                         list.Add(new CustomAttributeData(this.Assembly, constructor, GetBlob(CustomAttribute.records[i].Value)));
428                                                 }
429                                         }
430                                 }
431                         }
432                         return list;
433                 }
434
435                 internal IList<CustomAttributeData> GetDeclarativeSecurity(int metadataToken)
436                 {
437                         List<CustomAttributeData> list = new List<CustomAttributeData>();
438                         // TODO use binary search?
439                         for (int i = 0; i < DeclSecurity.records.Length; i++)
440                         {
441                                 if (DeclSecurity.records[i].Parent == metadataToken)
442                                 {
443                                         int action = DeclSecurity.records[i].Action;
444                                         int permissionSet = DeclSecurity.records[i].PermissionSet;
445                                         CustomAttributeData.ReadDeclarativeSecurity(this.Assembly, list, action, GetBlob(permissionSet));
446                                 }
447                         }
448                         return list;
449                 }
450
451                 internal virtual void Dispose()
452                 {
453                 }
454
455                 internal virtual void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
456                 {
457                 }
458         }
459
460         public delegate bool TypeFilter(Type m, object filterCriteria);
461         public delegate bool MemberFilter(MemberInfo m, object filterCriteria);
462 }